@optolith/entity-descriptions 0.1.1 → 0.2.0

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.
Files changed (72) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/lib/entities/combatTechnique.d.ts +4 -4
  3. package/lib/entities/combatTechnique.js +7 -7
  4. package/lib/entities/experienceLevel.d.ts +1 -1
  5. package/lib/entities/experienceLevel.js +3 -3
  6. package/lib/entities/focusRule.d.ts +8 -0
  7. package/lib/entities/focusRule.js +18 -0
  8. package/lib/entities/liturgicalChant.d.ts +6 -6
  9. package/lib/entities/liturgicalChant.js +27 -56
  10. package/lib/entities/optionalRule.d.ts +5 -0
  11. package/lib/entities/optionalRule.js +16 -0
  12. package/lib/entities/partial/rated/activatable/castingTime.d.ts +3 -15
  13. package/lib/entities/partial/rated/activatable/castingTime.js +19 -34
  14. package/lib/entities/partial/rated/activatable/checkResultBased.d.ts +1 -1
  15. package/lib/entities/partial/rated/activatable/checkResultBased.js +2 -2
  16. package/lib/entities/partial/rated/activatable/cost.d.ts +3 -19
  17. package/lib/entities/partial/rated/activatable/cost.js +82 -99
  18. package/lib/entities/partial/rated/activatable/duration.d.ts +5 -24
  19. package/lib/entities/partial/rated/activatable/duration.js +40 -57
  20. package/lib/entities/partial/rated/activatable/effect.d.ts +3 -3
  21. package/lib/entities/partial/rated/activatable/effect.js +7 -7
  22. package/lib/entities/partial/rated/activatable/index.d.ts +5 -33
  23. package/lib/entities/partial/rated/activatable/index.js +23 -41
  24. package/lib/entities/partial/rated/activatable/isMinimumMaximum.d.ts +20 -0
  25. package/lib/entities/partial/rated/activatable/isMinimumMaximum.js +19 -0
  26. package/lib/entities/partial/rated/activatable/nonModifiableSuffix.d.ts +16 -0
  27. package/lib/entities/partial/rated/activatable/nonModifiableSuffix.js +55 -0
  28. package/lib/entities/partial/rated/activatable/parensIf.d.ts +1 -1
  29. package/lib/entities/partial/rated/activatable/parensIf.js +3 -1
  30. package/lib/entities/partial/rated/activatable/range.d.ts +4 -20
  31. package/lib/entities/partial/rated/activatable/range.js +59 -100
  32. package/lib/entities/partial/rated/activatable/speed.d.ts +1 -1
  33. package/lib/entities/partial/rated/activatable/speed.js +1 -1
  34. package/lib/entities/partial/rated/activatable/targetCategory.d.ts +3 -7
  35. package/lib/entities/partial/rated/activatable/targetCategory.js +30 -26
  36. package/lib/entities/partial/rated/improvementCost.d.ts +2 -2
  37. package/lib/entities/partial/rated/skillCheck.d.ts +2 -2
  38. package/lib/entities/partial/responsiveText.d.ts +7 -4
  39. package/lib/entities/partial/responsiveText.js +8 -2
  40. package/lib/entities/partial/units/energy.d.ts +12 -0
  41. package/lib/entities/partial/units/energy.js +30 -0
  42. package/lib/entities/partial/units/length.d.ts +8 -0
  43. package/lib/entities/partial/units/length.js +12 -0
  44. package/lib/entities/partial/units/timeSpan.d.ts +8 -0
  45. package/lib/entities/partial/units/timeSpan.js +22 -0
  46. package/lib/entities/skill.d.ts +2 -2
  47. package/lib/entities/skill.js +3 -3
  48. package/lib/entities/spell.d.ts +6 -6
  49. package/lib/entities/spell.js +27 -56
  50. package/lib/helpers/locale.d.ts +8 -0
  51. package/lib/helpers/locale.js +1 -0
  52. package/lib/index.d.ts +45 -1
  53. package/lib/index.js +22 -1
  54. package/lib/references/index.d.ts +4 -0
  55. package/lib/references/index.js +46 -0
  56. package/lib/references/occurrence.d.ts +4 -0
  57. package/lib/references/occurrence.js +3 -0
  58. package/lib/references/page.d.ts +23 -0
  59. package/lib/references/page.js +61 -0
  60. package/lib/references/pageRange.d.ts +30 -0
  61. package/lib/references/pageRange.js +58 -0
  62. package/package.json +7 -3
  63. package/lib/entities/partial/rated/activatable/isMaximum.d.ts +0 -6
  64. package/lib/entities/partial/rated/activatable/isMaximum.js +0 -10
  65. package/lib/entities/partial/rated/activatable/modifiableParameter.d.ts +0 -8
  66. package/lib/entities/partial/rated/activatable/modifiableParameter.js +0 -9
  67. package/lib/entities/partial/rated/activatable/nonModifiable.d.ts +0 -9
  68. package/lib/entities/partial/rated/activatable/nonModifiable.js +0 -75
  69. package/lib/entities/partial/rated/activatable/units.d.ts +0 -13
  70. package/lib/entities/partial/rated/activatable/units.js +0 -53
  71. package/lib/libraryEntry.d.ts +0 -52
  72. package/lib/libraryEntry.js +0 -17
@@ -0,0 +1,30 @@
1
+ import { assertExhaustive } from "@optolith/helpers/typeSafety";
2
+ import { Entity } from "../rated/activatable/entity.js";
3
+ const lengthUnitTranslationKeys = {
4
+ ArcaneEnergy: "{0} AE",
5
+ KarmaPoints: "{0} KP",
6
+ };
7
+ /**
8
+ * Returns the text for an energy unit.
9
+ */
10
+ export const formatEnergy = (locale, unit, value) => {
11
+ const key = lengthUnitTranslationKeys[unit];
12
+ return locale.translate(key, value);
13
+ };
14
+ /**
15
+ * Returns the text for an energy unit that is based on the entity type.
16
+ */
17
+ export const formatEnergyByEntity = (locale, entity, value) => {
18
+ switch (entity) {
19
+ case Entity.Cantrip:
20
+ case Entity.Spell:
21
+ case Entity.Ritual:
22
+ return formatEnergy(locale, "ArcaneEnergy", value);
23
+ case Entity.Blessing:
24
+ case Entity.LiturgicalChant:
25
+ case Entity.Ceremony:
26
+ return formatEnergy(locale, "KarmaPoints", value);
27
+ default:
28
+ return assertExhaustive(entity);
29
+ }
30
+ };
@@ -0,0 +1,8 @@
1
+ import { LocaleEnvironment } from "../../../helpers/locale.js";
2
+ import { ResponsiveTextSize } from "../responsiveText.js";
3
+ type LengthUnit = "Steps" | "Miles";
4
+ /**
5
+ * Returns the text for a length unit.
6
+ */
7
+ export declare const formatLength: (locale: LocaleEnvironment, responsiveTextSize: ResponsiveTextSize, unit: LengthUnit, value: number | string) => string;
8
+ export {};
@@ -0,0 +1,12 @@
1
+ import { responsive } from "../responsiveText.js";
2
+ const lengthUnitTranslationKeys = {
3
+ Steps: ["{0} yards", "{0} yd"],
4
+ Miles: ["{0} miles", "{0} mi."],
5
+ };
6
+ /**
7
+ * Returns the text for a length unit.
8
+ */
9
+ export const formatLength = (locale, responsiveTextSize, unit, value) => {
10
+ const [fullKey, compressedKey] = lengthUnitTranslationKeys[unit];
11
+ return responsive(responsiveTextSize, () => locale.translate(fullKey, value), () => locale.translate(compressedKey, value));
12
+ };
@@ -0,0 +1,8 @@
1
+ import { LocaleEnvironment } from "../../../helpers/locale.js";
2
+ import { ResponsiveTextSize } from "../responsiveText.js";
3
+ type TimeSpanUnit = "Seconds" | "Minutes" | "Hours" | "Days" | "Weeks" | "Months" | "Years" | "Centuries" | "Actions" | "CombatRounds" | "SeductionActions" | "Rounds";
4
+ /**
5
+ * Returns the text for a time span unit.
6
+ */
7
+ export declare const formatTimeSpan: (locale: LocaleEnvironment, responsiveTextSize: ResponsiveTextSize, unit: TimeSpanUnit, value: number | string) => string;
8
+ export {};
@@ -0,0 +1,22 @@
1
+ import { responsive } from "../responsiveText.js";
2
+ const timeSpanUnitTranslationKeys = {
3
+ Seconds: ["{0} seconds", "{0} s"],
4
+ Minutes: ["{0} minutes", "{0} min"],
5
+ Hours: ["{0} hours", "{0} h"],
6
+ Days: ["{0} days", "{0} d"],
7
+ Weeks: ["{0} weeks", "{0} wks."],
8
+ Months: ["{0} months", "{0} mos."],
9
+ Years: ["{0} years", "{0} yrs."],
10
+ Centuries: ["{0} centuries", "{0} cent."],
11
+ Actions: ["{0} actions", "{0} act"],
12
+ CombatRounds: ["{0} combat rounds", "{0} CR"],
13
+ SeductionActions: ["{0} seduction actions", "{0} SA"],
14
+ Rounds: ["{0} rounds", "{0} rnds"],
15
+ };
16
+ /**
17
+ * Returns the text for a time span unit.
18
+ */
19
+ export const formatTimeSpan = (locale, responsiveTextSize, unit, value) => {
20
+ const [fullKey, compressedKey] = timeSpanUnitTranslationKeys[unit];
21
+ return responsive(responsiveTextSize, () => locale.translate(fullKey, value), () => locale.translate(compressedKey, value));
22
+ };
@@ -4,10 +4,10 @@ import { All, GetById } from "../helpers/getTypes.js";
4
4
  /**
5
5
  * Get a JSON representation of the rules text for a skill.
6
6
  */
7
- export declare const getSkillLibraryEntry: import("../libraryEntry.js").LibraryEntryCreator<Skill | undefined, {
7
+ export declare const getSkillEntityDescription: import("../index.js").EntityDescriptionCreator<Skill | undefined, {
8
8
  getAttributeById: GetById.Static.Attribute;
9
9
  blessedTraditions: All.Static.BlessedTraditions;
10
10
  diseases: All.Static.Diseases;
11
11
  regions: All.Static.Regions;
12
12
  cache: NewApplicationsAndUsesCache;
13
- }, import("../libraryEntry.js").LibraryEntry>;
13
+ }, import("../index.js").EntityDescription>;
@@ -1,12 +1,12 @@
1
1
  import { isNotNullish } from "@optolith/helpers/nullable";
2
2
  import { assertExhaustive } from "@optolith/helpers/typeSafety";
3
- import { createLibraryEntryCreator } from "../libraryEntry.js";
3
+ import { createEntityDescriptionCreator } from "../index.js";
4
4
  import { createImprovementCost } from "./partial/rated/improvementCost.js";
5
5
  import { getTextForCheck } from "./partial/rated/skillCheck.js";
6
6
  /**
7
7
  * Get a JSON representation of the rules text for a skill.
8
8
  */
9
- export const getSkillLibraryEntry = createLibraryEntryCreator((entry, { getAttributeById, blessedTraditions, diseases, regions, cache }) => ({ translate, translateMap, localeCompare }) => {
9
+ export const getSkillEntityDescription = createEntityDescriptionCreator(({ getAttributeById, blessedTraditions, diseases, regions, cache }, { translate, translateMap, compare: localeCompare }, entry) => {
10
10
  const translation = translateMap(entry.translations);
11
11
  if (translation === undefined) {
12
12
  return undefined;
@@ -55,7 +55,7 @@ export const getSkillLibraryEntry = createLibraryEntryCreator((entry, { getAttri
55
55
  return {
56
56
  title: translation.name,
57
57
  className: "skill",
58
- content: [
58
+ body: [
59
59
  newApplications.length === 0
60
60
  ? undefined
61
61
  : {
@@ -6,16 +6,16 @@ import { GetById } from "../helpers/getTypes.js";
6
6
  /**
7
7
  * Get a JSON representation of the rules text for a cantrip.
8
8
  */
9
- export declare const getCantripLibraryEntry: import("../libraryEntry.js").LibraryEntryCreator<Cantrip | undefined, {
9
+ export declare const getCantripEntityDescription: import("../index.js").EntityDescriptionCreator<Cantrip | undefined, {
10
10
  getTargetCategoryById: GetById.Static.TargetCategory;
11
11
  getPropertyById: GetById.Static.Property;
12
12
  getMagicalTraditionById: GetById.Static.MagicalTradition;
13
13
  getCurriculumById: GetById.Static.Curriculum;
14
- }, import("../libraryEntry.js").LibraryEntry>;
14
+ }, import("../index.js").EntityDescription>;
15
15
  /**
16
16
  * Get a JSON representation of the rules text for a skill.
17
17
  */
18
- export declare const getSpellLibraryEntry: import("../libraryEntry.js").LibraryEntryCreator<Spell | undefined, {
18
+ export declare const getSpellEntityDescription: import("../index.js").EntityDescriptionCreator<Spell | undefined, {
19
19
  getAttributeById: GetById.Static.Attribute;
20
20
  getSpirit: () => DerivedCharacteristic | undefined;
21
21
  getToughness: () => DerivedCharacteristic | undefined;
@@ -23,11 +23,11 @@ export declare const getSpellLibraryEntry: import("../libraryEntry.js").LibraryE
23
23
  getTargetCategoryById: GetById.Static.TargetCategory;
24
24
  getPropertyById: GetById.Static.Property;
25
25
  getMagicalTraditionById: GetById.Static.MagicalTradition;
26
- }, import("../libraryEntry.js").LibraryEntry>;
26
+ }, import("../index.js").EntityDescription>;
27
27
  /**
28
28
  * Get a JSON representation of the rules text for a ritual.
29
29
  */
30
- export declare const getRitualLibraryEntry: import("../libraryEntry.js").LibraryEntryCreator<Ritual | undefined, {
30
+ export declare const getRitualEntityDescription: import("../index.js").EntityDescriptionCreator<Ritual | undefined, {
31
31
  getAttributeById: GetById.Static.Attribute;
32
32
  getSpirit: () => DerivedCharacteristic | undefined;
33
33
  getToughness: () => DerivedCharacteristic | undefined;
@@ -35,4 +35,4 @@ export declare const getRitualLibraryEntry: import("../libraryEntry.js").Library
35
35
  getTargetCategoryById: GetById.Static.TargetCategory;
36
36
  getPropertyById: GetById.Static.Property;
37
37
  getMagicalTraditionById: GetById.Static.MagicalTradition;
38
- }, import("../libraryEntry.js").LibraryEntry>;
38
+ }, import("../index.js").EntityDescription>;
@@ -1,13 +1,13 @@
1
1
  import { isNotNullish, mapNullable } from "@optolith/helpers/nullable";
2
2
  import { assertExhaustive } from "@optolith/helpers/typeSafety";
3
- import { createLibraryEntryCreator, } from "../libraryEntry.js";
4
- import { getTextForCantripDuration } from "./partial/rated/activatable/duration.js";
3
+ import { createEntityDescriptionCreator, } from "../index.js";
4
+ import { getDurationTranslationForCantrip } from "./partial/rated/activatable/duration.js";
5
5
  import { getTextForEffect } from "./partial/rated/activatable/effect.js";
6
6
  import { Entity } from "./partial/rated/activatable/entity.js";
7
- import { getTextForFastOneTimePerformanceParameters, getTextForFastSustainedPerformanceParameters, getTextForSlowOneTimePerformanceParameters, getTextForSlowSustainedPerformanceParameters, } from "./partial/rated/activatable/index.js";
7
+ import { getFastOneTimePerformanceParametersTranslations, getFastSustainedPerformanceParametersTranslations, getSlowOneTimePerformanceParametersTranslations, getSlowSustainedPerformanceParametersTranslations, } from "./partial/rated/activatable/index.js";
8
8
  import { parensIf } from "./partial/rated/activatable/parensIf.js";
9
9
  import { getTextForCantripRange } from "./partial/rated/activatable/range.js";
10
- import { getTextForTargetCategory } from "./partial/rated/activatable/targetCategory.js";
10
+ import { getTargetCategoryTranslation } from "./partial/rated/activatable/targetCategory.js";
11
11
  import { createImprovementCost } from "./partial/rated/improvementCost.js";
12
12
  import { getTextForCheck } from "./partial/rated/skillCheck.js";
13
13
  import { ResponsiveTextSize } from "./partial/responsiveText.js";
@@ -53,21 +53,18 @@ const getTraditionNameForArcaneSpellworksById = (ref, getMagicalTraditionById, t
53
53
  /**
54
54
  * Get a JSON representation of the rules text for a cantrip.
55
55
  */
56
- export const getCantripLibraryEntry = createLibraryEntryCreator((entry, { getTargetCategoryById, getPropertyById, getMagicalTraditionById, getCurriculumById, }) => ({ translate, translateMap, localeCompare }) => {
56
+ export const getCantripEntityDescription = createEntityDescriptionCreator(({ getTargetCategoryById, getPropertyById, getMagicalTraditionById, getCurriculumById, }, locale, entry) => {
57
+ const { translate, translateMap, compare: localeCompare } = locale;
57
58
  const translation = translateMap(entry.translations);
58
59
  if (translation === undefined) {
59
60
  return undefined;
60
61
  }
61
- const range = getTextForCantripRange({ translate }, entry.parameters.range, {
62
- responsiveText: ResponsiveTextSize.Full,
63
- });
64
- const duration = getTextForCantripDuration({ translate, translateMap }, entry.parameters.duration, {
65
- responsiveText: ResponsiveTextSize.Full,
66
- });
62
+ const range = getTextForCantripRange(locale, ResponsiveTextSize.Full, entry.parameters.range);
63
+ const duration = getDurationTranslationForCantrip(locale, ResponsiveTextSize.Full, entry.parameters.duration);
67
64
  return {
68
65
  title: translation.name,
69
66
  className: "cantrip",
70
- content: [
67
+ body: [
71
68
  {
72
69
  label: translate("Effect"),
73
70
  value: translation.effect,
@@ -84,7 +81,7 @@ export const getCantripLibraryEntry = createLibraryEntryCreator((entry, { getTar
84
81
  ? `***${duration}*** (${translation.duration})`
85
82
  : duration,
86
83
  },
87
- getTextForTargetCategory({ translate, translateMap, getTargetCategoryById }, entry.target),
84
+ getTargetCategoryTranslation(getTargetCategoryById, locale, entry.target),
88
85
  getTextForProperty({ translate, translateMap, getPropertyById }, entry.property),
89
86
  mapNullable(entry.note, (note) => ({
90
87
  label: translate("Note"),
@@ -119,13 +116,14 @@ export const getCantripLibraryEntry = createLibraryEntryCreator((entry, { getTar
119
116
  })(),
120
117
  })),
121
118
  ],
122
- src: entry.src,
119
+ references: entry.src,
123
120
  };
124
121
  });
125
122
  /**
126
123
  * Get a JSON representation of the rules text for a skill.
127
124
  */
128
- export const getSpellLibraryEntry = createLibraryEntryCreator((entry, { getAttributeById, getSpirit, getToughness, getSkillModificationLevelById, getTargetCategoryById, getPropertyById, getMagicalTraditionById, }) => ({ translate, translateMap, localeCompare }) => {
125
+ export const getSpellEntityDescription = createEntityDescriptionCreator(({ getAttributeById, getSpirit, getToughness, getSkillModificationLevelById, getTargetCategoryById, getPropertyById, getMagicalTraditionById, }, locale, entry) => {
126
+ const { translate, translateMap, compare: localeCompare } = locale;
129
127
  const translation = translateMap(entry.translations);
130
128
  if (translation === undefined) {
131
129
  return undefined;
@@ -133,23 +131,9 @@ export const getSpellLibraryEntry = createLibraryEntryCreator((entry, { getAttri
133
131
  const { castingTime, cost, range, duration } = (() => {
134
132
  switch (entry.parameters.tag) {
135
133
  case "OneTime":
136
- return getTextForFastOneTimePerformanceParameters({
137
- getSkillModificationLevelById,
138
- translate,
139
- translateMap,
140
- }, entry.parameters.one_time, {
141
- entity: Entity.Spell,
142
- responsiveText: ResponsiveTextSize.Full,
143
- });
134
+ return getFastOneTimePerformanceParametersTranslations(getSkillModificationLevelById, locale, Entity.Spell, ResponsiveTextSize.Full, entry.parameters.one_time);
144
135
  case "Sustained":
145
- return getTextForFastSustainedPerformanceParameters({
146
- getSkillModificationLevelById,
147
- translate,
148
- translateMap,
149
- }, entry.parameters.sustained, {
150
- entity: Entity.Spell,
151
- responsiveText: ResponsiveTextSize.Full,
152
- });
136
+ return getFastSustainedPerformanceParametersTranslations(getSkillModificationLevelById, locale, Entity.Spell, ResponsiveTextSize.Full, entry.parameters.sustained);
153
137
  default:
154
138
  return assertExhaustive(entry.parameters);
155
139
  }
@@ -157,14 +141,14 @@ export const getSpellLibraryEntry = createLibraryEntryCreator((entry, { getAttri
157
141
  return {
158
142
  title: translation.name,
159
143
  className: "spell",
160
- content: [
144
+ body: [
161
145
  getTextForCheck({ translate, translateMap, getAttributeById }, entry.check, {
162
146
  value: entry.check_penalty,
163
147
  responsiveText: ResponsiveTextSize.Full,
164
148
  getSpirit,
165
149
  getToughness,
166
150
  }),
167
- ...getTextForEffect(translation.effect, translate),
151
+ ...getTextForEffect(locale, translation.effect),
168
152
  {
169
153
  label: translate("Casting Time"),
170
154
  value: castingTime !== translation.casting_time.full
@@ -189,18 +173,19 @@ export const getSpellLibraryEntry = createLibraryEntryCreator((entry, { getAttri
189
173
  ? `***${duration}*** (${translation.duration.full})`
190
174
  : duration,
191
175
  },
192
- getTextForTargetCategory({ translate, translateMap, getTargetCategoryById }, entry.target),
176
+ getTargetCategoryTranslation(getTargetCategoryById, locale, entry.target),
193
177
  getTextForProperty({ translate, translateMap, getPropertyById }, entry.property),
194
178
  getTextForTraditions({ translate, translateMap, localeCompare, getMagicalTraditionById }, entry.traditions),
195
179
  createImprovementCost(translate, entry.improvement_cost),
196
180
  ],
197
- src: entry.src,
181
+ references: entry.src,
198
182
  };
199
183
  });
200
184
  /**
201
185
  * Get a JSON representation of the rules text for a ritual.
202
186
  */
203
- export const getRitualLibraryEntry = createLibraryEntryCreator((entry, { getAttributeById, getSpirit, getToughness, getSkillModificationLevelById, getTargetCategoryById, getPropertyById, getMagicalTraditionById, }) => ({ translate, translateMap, localeCompare }) => {
187
+ export const getRitualEntityDescription = createEntityDescriptionCreator(({ getAttributeById, getSpirit, getToughness, getSkillModificationLevelById, getTargetCategoryById, getPropertyById, getMagicalTraditionById, }, locale, entry) => {
188
+ const { translate, translateMap, compare: localeCompare } = locale;
204
189
  const translation = translateMap(entry.translations);
205
190
  if (translation === undefined) {
206
191
  return undefined;
@@ -208,23 +193,9 @@ export const getRitualLibraryEntry = createLibraryEntryCreator((entry, { getAttr
208
193
  const { castingTime, cost, range, duration } = (() => {
209
194
  switch (entry.parameters.tag) {
210
195
  case "OneTime":
211
- return getTextForSlowOneTimePerformanceParameters({
212
- getSkillModificationLevelById,
213
- translate,
214
- translateMap,
215
- }, entry.parameters.one_time, {
216
- entity: Entity.Ritual,
217
- responsiveText: ResponsiveTextSize.Full,
218
- });
196
+ return getSlowOneTimePerformanceParametersTranslations(getSkillModificationLevelById, locale, Entity.Ritual, ResponsiveTextSize.Full, entry.parameters.one_time);
219
197
  case "Sustained":
220
- return getTextForSlowSustainedPerformanceParameters({
221
- getSkillModificationLevelById,
222
- translate,
223
- translateMap,
224
- }, entry.parameters.sustained, {
225
- entity: Entity.Ritual,
226
- responsiveText: ResponsiveTextSize.Full,
227
- });
198
+ return getSlowSustainedPerformanceParametersTranslations(getSkillModificationLevelById, locale, Entity.Ritual, ResponsiveTextSize.Full, entry.parameters.sustained);
228
199
  default:
229
200
  return assertExhaustive(entry.parameters);
230
201
  }
@@ -232,14 +203,14 @@ export const getRitualLibraryEntry = createLibraryEntryCreator((entry, { getAttr
232
203
  return {
233
204
  title: translation.name,
234
205
  className: "ritual",
235
- content: [
206
+ body: [
236
207
  getTextForCheck({ translate, translateMap, getAttributeById }, entry.check, {
237
208
  value: entry.check_penalty,
238
209
  responsiveText: ResponsiveTextSize.Full,
239
210
  getSpirit,
240
211
  getToughness,
241
212
  }),
242
- ...getTextForEffect(translation.effect, translate),
213
+ ...getTextForEffect(locale, translation.effect),
243
214
  {
244
215
  label: translate("Ritual Time"),
245
216
  value: castingTime !== translation.casting_time.full
@@ -264,11 +235,11 @@ export const getRitualLibraryEntry = createLibraryEntryCreator((entry, { getAttr
264
235
  ? `***${duration}*** (${translation.duration.full})`
265
236
  : duration,
266
237
  },
267
- getTextForTargetCategory({ translate, translateMap, getTargetCategoryById }, entry.target),
238
+ getTargetCategoryTranslation(getTargetCategoryById, locale, entry.target),
268
239
  getTextForProperty({ translate, translateMap, getPropertyById }, entry.property),
269
240
  getTextForTraditions({ translate, translateMap, localeCompare, getMagicalTraditionById }, entry.traditions),
270
241
  createImprovementCost(translate, entry.improvement_cost),
271
242
  ],
272
- src: entry.src,
243
+ references: entry.src,
273
244
  };
274
245
  });
@@ -0,0 +1,8 @@
1
+ import { Compare } from "@optolith/helpers/compare";
2
+ import { Translate, TranslateMap } from "./translate.js";
3
+ export type LocaleEnvironment = {
4
+ id: string;
5
+ translate: Translate;
6
+ translateMap: TranslateMap;
7
+ compare: Compare<string>;
8
+ };
@@ -0,0 +1 @@
1
+ export {};
package/lib/index.d.ts CHANGED
@@ -1 +1,45 @@
1
- export {};
1
+ import { PublicationRefs } from "optolith-database-schema/types/source/_PublicationRef";
2
+ import { GetById } from "./helpers/getTypes.js";
3
+ import { LocaleEnvironment } from "./helpers/locale.js";
4
+ /**
5
+ * Creates a function that creates the JSON representation of the rules text for
6
+ * a library entry.
7
+ */
8
+ export declare const createEntityDescriptionCreator: <T, A extends object = Record<string, never>>(fn: EntityDescriptionCreator<T, A, RawEntityDescription>) => EntityDescriptionCreator<T | undefined, A>;
9
+ /**
10
+ * A function that creates the JSON representation of the rules text for a
11
+ * library entry.
12
+ */
13
+ export type EntityDescriptionCreator<T, A extends object = Record<string, never>, R = EntityDescription> = (databaseAccessors: A & {
14
+ getPublicationById: GetById.Static.Publication;
15
+ }, locale: LocaleEnvironment, entry: T) => R | undefined;
16
+ /**
17
+ * A JSON representation of the rules text for a library entry.
18
+ */
19
+ export type EntityDescription = {
20
+ title: string;
21
+ subtitle?: string;
22
+ className: string;
23
+ body: EntityDescriptionSection[];
24
+ references?: string;
25
+ };
26
+ /**
27
+ * A JSON representation of the rules text for a library entry that has not been
28
+ * cleaned up.
29
+ */
30
+ export type RawEntityDescription = {
31
+ title: string;
32
+ subtitle?: string;
33
+ className: string;
34
+ body: (EntityDescriptionSection | undefined)[];
35
+ references?: PublicationRefs;
36
+ };
37
+ /**
38
+ * A slice of the content of a library entry text.
39
+ */
40
+ export type EntityDescriptionSection = {
41
+ label?: string;
42
+ value: string | number;
43
+ noIndent?: boolean;
44
+ className?: string;
45
+ };
package/lib/index.js CHANGED
@@ -1 +1,22 @@
1
- export {};
1
+ import { filterNonNullable } from "@optolith/helpers/array";
2
+ import { getReferencesTranslation } from "./references/index.js";
3
+ /**
4
+ * Creates a function that creates the JSON representation of the rules text for
5
+ * a library entry.
6
+ */
7
+ export const createEntityDescriptionCreator = (fn) => (databaseAccessors, locale, entry) => {
8
+ if (entry === undefined) {
9
+ return undefined;
10
+ }
11
+ const rawEntry = fn(databaseAccessors, locale, entry);
12
+ if (rawEntry === undefined) {
13
+ return undefined;
14
+ }
15
+ return {
16
+ ...rawEntry,
17
+ body: filterNonNullable(rawEntry.body),
18
+ references: rawEntry.references === undefined
19
+ ? undefined
20
+ : getReferencesTranslation(databaseAccessors.getPublicationById, locale, rawEntry.references),
21
+ };
22
+ };
@@ -0,0 +1,4 @@
1
+ import { PublicationRefs } from "optolith-database-schema/types/source/_PublicationRef";
2
+ import { GetById } from "../helpers/getTypes.js";
3
+ import { LocaleEnvironment } from "../helpers/locale.js";
4
+ export declare const getReferencesTranslation: (getPublicationById: GetById.Static.Publication, locale: LocaleEnvironment, references: PublicationRefs) => string;
@@ -0,0 +1,46 @@
1
+ import { isNotNullish } from "@optolith/helpers/nullable";
2
+ import { assertExhaustive } from "@optolith/helpers/typeSafety";
3
+ import { isSimpleOccurrence, isSimpleOccurrences, isVersionedOccurrence, } from "./occurrence.js";
4
+ import { fromRawPageRange, normalizePageRanges, numberRangeToPageRange, printPageRange, printPageRanges, } from "./pageRange.js";
5
+ export const getReferencesTranslation = (getPublicationById, locale, references) => references
6
+ .map((ref) => {
7
+ const publication = getPublicationById(ref.id.publication);
8
+ const publicationTranslations = locale.translateMap(publication?.translations);
9
+ const occurrences = locale.translateMap(ref.occurrences);
10
+ if (publication === undefined ||
11
+ publicationTranslations === undefined ||
12
+ occurrences === undefined) {
13
+ return undefined;
14
+ }
15
+ if (isSimpleOccurrence(occurrences)) {
16
+ return `${publicationTranslations.name} ${printPageRange(locale.translate, numberRangeToPageRange(occurrences))}`;
17
+ }
18
+ if (isSimpleOccurrences(occurrences)) {
19
+ const ranges = normalizePageRanges(occurrences.map(numberRangeToPageRange));
20
+ return `${publicationTranslations.name} ${printPageRanges(locale.translate, ranges)}`;
21
+ }
22
+ if (isVersionedOccurrence(occurrences)) {
23
+ const initialPageRanges = normalizePageRanges(occurrences.initial.pages.map(fromRawPageRange));
24
+ const initial = occurrences.initial.printing === undefined
25
+ ? printPageRanges(locale.translate, initialPageRanges)
26
+ : `${printPageRanges(locale.translate, initialPageRanges)} (${locale.translate("since the {0}. printing", occurrences.initial.printing)})`;
27
+ const revisions = occurrences.revisions?.map((rev) => {
28
+ switch (rev.tag) {
29
+ case "Since": {
30
+ const pageRanges = normalizePageRanges(rev.since.pages.map(fromRawPageRange));
31
+ return `${printPageRanges(locale.translate, pageRanges)} (${locale.translate("since the {0}. printing", rev.since.printing)})`;
32
+ }
33
+ case "Deprecated": {
34
+ return locale.translate("removed in {0}. printing", rev.deprecated.printing);
35
+ }
36
+ default:
37
+ return assertExhaustive(rev);
38
+ }
39
+ }) ?? [];
40
+ const allPageRanges = [initial, ...revisions].join("; ");
41
+ return `${publicationTranslations.name} ${allPageRanges}`;
42
+ }
43
+ return assertExhaustive(occurrences);
44
+ })
45
+ .filter(isNotNullish)
46
+ .join("; ");
@@ -0,0 +1,4 @@
1
+ import { Occurrence, SimpleOccurrence, SimpleOccurrences, VersionedOccurrence } from "optolith-database-schema/types/source/_PublicationRef";
2
+ export declare const isSimpleOccurrence: (occurrence: Occurrence) => occurrence is SimpleOccurrence;
3
+ export declare const isSimpleOccurrences: (occurrence: Occurrence) => occurrence is SimpleOccurrences;
4
+ export declare const isVersionedOccurrence: (occurrence: Occurrence) => occurrence is VersionedOccurrence;
@@ -0,0 +1,3 @@
1
+ export const isSimpleOccurrence = (occurrence) => Object.hasOwn(occurrence, "first_page");
2
+ export const isSimpleOccurrences = (occurrence) => Array.isArray(occurrence);
3
+ export const isVersionedOccurrence = (occurrence) => Object.hasOwn(occurrence, "initial");
@@ -0,0 +1,23 @@
1
+ import { Compare } from "@optolith/helpers/compare";
2
+ import { Page } from "optolith-database-schema/types/source/_PublicationRef";
3
+ import { Translate } from "../helpers/translate.js";
4
+ /**
5
+ * A comparison function for two pages.
6
+ */
7
+ export declare const comparePage: Compare<Page>;
8
+ /**
9
+ * Checks if two pages are equal.
10
+ */
11
+ export declare const equalsPage: (a: Page, b: Page) => boolean;
12
+ /**
13
+ * Returns the successor of a page.
14
+ */
15
+ export declare const succ: (page: Page) => Page;
16
+ /**
17
+ * Creates a page object for a page number.
18
+ */
19
+ export declare const numberToPage: (number: number) => Page;
20
+ /**
21
+ * Returns a string representation of a page.
22
+ */
23
+ export declare const printPage: (translate: Translate, page: Page) => string;
@@ -0,0 +1,61 @@
1
+ import { assertExhaustive } from "@optolith/helpers/typeSafety";
2
+ /**
3
+ * A comparison function for two pages.
4
+ */
5
+ export const comparePage = (a, b) => {
6
+ switch (a.tag) {
7
+ case "InsideCoverFront":
8
+ return b.tag === "InsideCoverFront" ? 0 : -1;
9
+ case "InsideCoverBack":
10
+ return b.tag === "InsideCoverBack" ? 0 : 1;
11
+ case "Numbered":
12
+ return b.tag === "Numbered"
13
+ ? a.numbered - b.numbered
14
+ : b.tag === "InsideCoverFront"
15
+ ? 1
16
+ : -1;
17
+ default:
18
+ return assertExhaustive(a);
19
+ }
20
+ };
21
+ /**
22
+ * Checks if two pages are equal.
23
+ */
24
+ export const equalsPage = (a, b) => comparePage(a, b) === 0;
25
+ /**
26
+ * Returns the successor of a page.
27
+ */
28
+ export const succ = (page) => {
29
+ switch (page.tag) {
30
+ case "InsideCoverFront":
31
+ return { tag: "Numbered", numbered: 1 };
32
+ case "InsideCoverBack":
33
+ return { tag: "InsideCoverFront", inside_cover_front: {} };
34
+ case "Numbered":
35
+ return { tag: "Numbered", numbered: page.numbered + 1 };
36
+ default:
37
+ return assertExhaustive(page);
38
+ }
39
+ };
40
+ /**
41
+ * Creates a page object for a page number.
42
+ */
43
+ export const numberToPage = (number) => ({
44
+ tag: "Numbered",
45
+ numbered: number,
46
+ });
47
+ /**
48
+ * Returns a string representation of a page.
49
+ */
50
+ export const printPage = (translate, page) => {
51
+ switch (page.tag) {
52
+ case "InsideCoverFront":
53
+ return translate("Front Cover Inside");
54
+ case "InsideCoverBack":
55
+ return translate("Back Cover Inside");
56
+ case "Numbered":
57
+ return page.numbered.toString();
58
+ default:
59
+ return assertExhaustive(page);
60
+ }
61
+ };
@@ -0,0 +1,30 @@
1
+ import { Page, PageRange as RawPageRange, SimpleOccurrence } from "optolith-database-schema/types/source/_PublicationRef";
2
+ import { Translate } from "../helpers/translate.js";
3
+ /**
4
+ * A range of pages, including the first and last page, if the range includes
5
+ * more than on page.
6
+ */
7
+ export type PageRange = {
8
+ firstPage: Page;
9
+ lastPage?: Page;
10
+ };
11
+ /**
12
+ * Converts a numeric range to a page object range.
13
+ */
14
+ export declare const numberRangeToPageRange: (numberRange: SimpleOccurrence) => PageRange;
15
+ /**
16
+ * Converts a page object range from the database to a local page object range.
17
+ */
18
+ export declare const fromRawPageRange: (pageRange: RawPageRange) => PageRange;
19
+ /**
20
+ * Sorts and combines page ranges while removing duplicates.
21
+ */
22
+ export declare const normalizePageRanges: (ranges: PageRange[]) => PageRange[];
23
+ /**
24
+ * Returns a string representation of a page range.
25
+ */
26
+ export declare const printPageRange: (translate: Translate, pageRange: PageRange) => string;
27
+ /**
28
+ * Returns a string representation of a list of page ranges.
29
+ */
30
+ export declare const printPageRanges: (translate: Translate, pageRanges: PageRange[]) => string;