Skip to content

Commit 33df10a

Browse files
committed
🚸🐛 Add a QuteDataTraits and fix some trait/tag bugs
- Add a QuteDataTraits - dedicated class to hold traits so we can have easier bare linking - Rename collectTraitsFrom to getTraits, and pull Tag adding into QuteDataTraits - Fix creature statblock so it doesn't generate traits property when we don't have any generic traits - Fix some items being incorrectly tagged with their source (e.g. tagged as "trait/preparation-sog2" rather than "trait/preparation") - Fix some incorrectly formatted markdown links when the trait is surrounded in square brackets (e.g. for classes and magical traditions) Fix
1 parent e14e37d commit 33df10a

File tree

14 files changed

+183
-82
lines changed

14 files changed

+183
-82
lines changed

examples/templates/pf2etools/creature2md-yamlStatblock.txt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,20 @@ sourcebook: {source.quoted}
2626
name: {name.quoted}
2727
level: Creature {level}
2828

29+
{#let alignment=traits.getFirst("Alignment") rarity=traits.getFirst("Rarity") size=traits.getFirst("Size") genericTraits=traits.genericTraits}
2930
{#if alignment}
30-
alignment: {alignment}
31+
alignment: {alignment.withoutTitle.quoted}
3132
{/if}{#if rarity}
32-
rarity: {rarity}
33+
rarity: {rarity.withoutTitle.quoted}
3334
{/if}{#if size}
34-
size: {size}
35-
{/if}{#if traits}
35+
size: {size.withoutTitle.quoted}
36+
{/if}{#if genericTraits}
3637
traits:
37-
{#each traits}
38-
{! Don't include traits which are already included above by the statblock layout !}
39-
{#if !it.title || !(it.title.contains("Alignment Trait") || it.title.contains("Size Trait") || it.title.contains("Rarity Trait"))}
40-
- "{it.withoutTitle}"
41-
{/if}
38+
{#each genericTraits}
39+
- {it.withoutTitle.quoted}
4240
{/each}
4341
{/if}
42+
{/let}
4443

4544
{#if perception}
4645
modifier: {perception}

src/main/java/dev/ebullient/convert/tools/pf2e/Json2QuteBase.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,20 @@
22

33
import java.util.ArrayList;
44
import java.util.List;
5-
import java.util.Set;
65
import com.fasterxml.jackson.databind.JsonNode;
76

87
import dev.ebullient.convert.tools.Tags;
98
import dev.ebullient.convert.tools.pf2e.qute.Pf2eQuteBase;
109
import dev.ebullient.convert.tools.pf2e.qute.Pf2eQuteNote;
11-
import dev.ebullient.convert.tools.pf2e.qute.QuteDataRef;
10+
import dev.ebullient.convert.tools.pf2e.qute.QuteDataTraits;
1211

1312
public abstract class Json2QuteBase implements JsonSource {
1413
protected final Pf2eIndex index;
1514
protected final Pf2eIndexType type;
1615
protected final JsonNode rootNode;
1716
protected final Pf2eSources sources;
1817
protected final Tags tags;
19-
protected final Set<QuteDataRef> traits;
18+
protected final QuteDataTraits traits;
2019
protected final List<String> entries;
2120

2221
public Json2QuteBase(Pf2eIndex index, Pf2eIndexType type, JsonNode rootNode) {
@@ -29,7 +28,7 @@ public Json2QuteBase(Pf2eIndex index, Pf2eIndexType type, JsonNode rootNode, Pf2
2928
this.rootNode = rootNode;
3029
this.sources = sources;
3130
this.tags = new Tags(sources);
32-
this.traits = collectTraitsFrom(rootNode, tags);
31+
this.traits = getTraits(rootNode).addToTags(tags);
3332
this.entries = new ArrayList<>(SourceField.entries.transformListFrom(rootNode, this, "##"));
3433
}
3534

src/main/java/dev/ebullient/convert/tools/pf2e/Json2QuteDeity.java

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
import static dev.ebullient.convert.StringUtil.toOrdinal;
77
import static dev.ebullient.convert.StringUtil.toTitleCase;
88

9-
import java.util.Collection;
109
import java.util.List;
1110
import java.util.Map;
1211
import java.util.TreeMap;
@@ -19,7 +18,6 @@
1918
import dev.ebullient.convert.qute.NamedText;
2019
import dev.ebullient.convert.tools.pf2e.Pf2eJsonNodeReader.Pf2eAttack;
2120
import dev.ebullient.convert.tools.pf2e.qute.QuteDataActivity.Activity;
22-
import dev.ebullient.convert.tools.pf2e.qute.QuteDataRef;
2321
import dev.ebullient.convert.tools.pf2e.qute.QuteDeity;
2422
import dev.ebullient.convert.tools.pf2e.qute.QuteInlineAttack;
2523
import dev.ebullient.convert.tools.pf2e.qute.QuteInlineAttack.AttackRangeType;
@@ -154,10 +152,6 @@ private NamedText buildAvatarAbility(JsonNode abilityNode) {
154152
}
155153

156154
private QuteInlineAttack buildAvatarAttack(JsonNode actionNode, AttackRangeType rangeType) {
157-
Collection<QuteDataRef> traits = collectTraitsFrom(actionNode, tags);
158-
Pf2eDeity.preciousMetal.getListOfStrings(actionNode, tui()).stream().map(QuteDataRef::new).forEach(traits::add);
159-
Pf2eDeity.traitNote.getTextFrom(actionNode).map(QuteDataRef::new).ifPresent(traits::add);
160-
161155
return new QuteInlineAttack(
162156
Pf2eAttack.name.getTextOrDefault(actionNode, "attack"),
163157
Pf2eActivity.toQuteActivity(this, Activity.single, null),
@@ -167,7 +161,9 @@ private QuteInlineAttack buildAvatarAttack(JsonNode actionNode, AttackRangeType
167161
.map(field -> field.getTextOrEmpty(actionNode))
168162
.filter(StringUtil::isPresent)
169163
.toList(),
170-
traits,
164+
getTraits(actionNode).addToTags(tags)
165+
.addTraits(Pf2eDeity.preciousMetal.getListOfStrings(actionNode, tui()))
166+
.addTrait(Pf2eDeity.traitNote.getTextOrEmpty(actionNode)),
171167
Pf2eDeity.note.replaceTextFrom(actionNode, this),
172168
this);
173169
}

src/main/java/dev/ebullient/convert/tools/pf2e/Json2QuteItem.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ public static QuteItemWeaponData buildWeaponData(JsonNode source,
318318
JsonSource convert, Tags tags) {
319319

320320
QuteItemWeaponData weaponData = new QuteItemWeaponData();
321-
weaponData.traits = convert.collectTraitsFrom(source, tags);
321+
weaponData.traits = convert.getTraits(source).addToTags(tags);
322322
weaponData.type = SourceField.type.getTextOrEmpty(source);
323323
weaponData.damage = getDamageString(source, convert);
324324

src/main/java/dev/ebullient/convert/tools/pf2e/JsonSource.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import static dev.ebullient.convert.StringUtil.join;
44

55
import java.util.ArrayList;
6-
import java.util.Collection;
76
import java.util.List;
87
import java.util.stream.Collectors;
98
import com.fasterxml.jackson.databind.JsonNode;
@@ -13,11 +12,9 @@
1312
import dev.ebullient.convert.io.Tui;
1413
import dev.ebullient.convert.qute.QuteUtil;
1514
import dev.ebullient.convert.tools.JsonNodeReader.FieldValue;
16-
import dev.ebullient.convert.tools.Tags;
1715
import dev.ebullient.convert.tools.pf2e.Json2QuteItem.Pf2eItem;
1816
import dev.ebullient.convert.tools.pf2e.qute.Pf2eQuteBase;
1917
import dev.ebullient.convert.tools.pf2e.qute.QuteDataActivity;
20-
import dev.ebullient.convert.tools.pf2e.qute.QuteDataRef;
2118

2219
public interface JsonSource extends JsonTextReplacement {
2320

@@ -584,9 +581,7 @@ default List<String> embedGenericData(String tag, JsonNode data) {
584581
text.add("title: " + title);
585582

586583
// Add traits
587-
Tags tags = new Tags();
588-
Collection<QuteDataRef> traits = collectTraitsFrom(data, tags);
589-
text.add(join(" ", traits) + " ");
584+
text.add(join(" ", getTraits(data)) + " ");
590585
maybeAddBlankLine(text);
591586

592587
// Add rendered sections

src/main/java/dev/ebullient/convert/tools/pf2e/JsonTextReplacement.java

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,19 @@
66

77
import java.util.ArrayList;
88
import java.util.List;
9-
import java.util.Set;
10-
import java.util.TreeSet;
119
import java.util.regex.MatchResult;
1210
import java.util.regex.Pattern;
13-
import java.util.stream.Collectors;
11+
import java.util.stream.Collector;
1412
import com.fasterxml.jackson.databind.JsonNode;
1513

1614
import dev.ebullient.convert.config.CompendiumConfig;
1715
import dev.ebullient.convert.io.Tui;
1816
import dev.ebullient.convert.tools.JsonNodeReader;
1917
import dev.ebullient.convert.tools.JsonNodeReader.FieldValue;
2018
import dev.ebullient.convert.tools.JsonTextConverter;
21-
import dev.ebullient.convert.tools.Tags;
2219
import dev.ebullient.convert.tools.pf2e.qute.QuteDataActivity.Activity;
2320
import dev.ebullient.convert.tools.pf2e.qute.QuteDataRef;
21+
import dev.ebullient.convert.tools.pf2e.qute.QuteDataTraits;
2422

2523
public interface JsonTextReplacement extends JsonTextConverter<Pf2eIndexType> {
2624
enum Field implements Pf2eJsonNodeReader {
@@ -219,17 +217,15 @@ default String replaceActionAs(MatchResult match) {
219217
/**
220218
* Collect and linkify traits from the specified node.
221219
*
222-
* @param tags The tags to populate while collecting traits. If null, then don't populate any tags.
223-
*
224-
* @return a set of {@link QuteDataRef}s to trait notes, or an empty set (never null)
220+
* @return a {@link QuteDataTraits} which may be empty (never null)
225221
*/
226-
default Set<QuteDataRef> collectTraitsFrom(JsonNode sourceNode, Tags tags) {
222+
default QuteDataTraits getTraits(JsonNode sourceNode) {
227223
return Field.traits.getListOfStrings(sourceNode, tui()).stream()
228-
.peek(tags == null ? (t -> {}) : t -> tags.add("trait", t))
229-
.sorted()
230-
.map(s -> linkify(Pf2eIndexType.trait, s))
231-
.map(QuteDataRef::fromMarkdownLink)
232-
.collect(Collectors.toCollection(TreeSet::new));
224+
.map(s -> QuteDataRef.fromMarkdownLink(linkify(Pf2eIndexType.trait, s)))
225+
.collect(Collector.of(QuteDataTraits::new, QuteDataTraits::add, (a, b) -> {
226+
a.addAll(b);
227+
return b;
228+
}));
233229
}
234230

235231
default String linkifyRuneItem(MatchResult match) {
@@ -373,6 +369,8 @@ default String linkifyTrait(String match) {
373369
default String linkifyTrait(JsonNode traitNode, String linkText) {
374370
if (traitNode != null) {
375371
String source = SourceField.source.getTextOrEmpty(traitNode);
372+
// Some traits are surrounded in square brackets. Strip this out to avoid messing up link rendering.
373+
linkText = linkText.replaceFirst("^\\[(.*)]$", "$1");
376374

377375
return "[%s](%s/%s%s.md \"%s\")".formatted(
378376
linkText,

src/main/java/dev/ebullient/convert/tools/pf2e/Pf2eJsonNodeReader.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@
77
import static java.util.Objects.requireNonNullElse;
88

99
import java.util.ArrayList;
10+
import java.util.Collection;
1011
import java.util.List;
1112
import java.util.Map;
1213
import java.util.Objects;
1314
import java.util.Optional;
14-
import java.util.Set;
1515
import java.util.function.Function;
1616
import java.util.function.Predicate;
1717
import java.util.stream.Collector;
@@ -95,7 +95,7 @@ default List<QuteInlineAttack> getAttacksFrom(JsonNode source, JsonSource conver
9595
* traits from these activation components to {@code traits}. Return an empty list if we couldn't get activation
9696
* components.
9797
*/
98-
default List<String> getActivationComponentsFrom(JsonNode source, Set<QuteDataRef> traits, JsonSource convert) {
98+
default List<String> getActivationComponentsFrom(JsonNode source, Collection<QuteDataRef> traits, JsonSource convert) {
9999
List<String> rawComponents = getListOfStrings(source, convert.tui()).stream()
100100
.map(s -> s.replaceFirst("^\\((%s)\\)$", "\1")) // remove parens
101101
.toList();
@@ -655,7 +655,7 @@ public static QuteInlineAttack getAttack(JsonNode node, JsonSource convert) {
655655
attack.getIntFrom(node).orElse(null),
656656
formattedDamage,
657657
types.replaceTextFromList(node, convert),
658-
convert.collectTraitsFrom(node, null),
658+
convert.getTraits(node),
659659
hasMultilineEffect ? List.of() : attackEffects,
660660
hasMultilineEffect ? String.join("\n", attackEffects) : null,
661661
noMAP.booleanOrDefault(node, false) ? List.of() : List.of("no multiple attack penalty"),

src/main/java/dev/ebullient/convert/tools/pf2e/qute/QuteCreature.java

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -95,27 +95,6 @@ public QuteCreature(
9595
this.ritualCasting = ritualCasting;
9696
}
9797

98-
/** Return the size of this creature, or null if it has none. */
99-
public String getSize() {
100-
return traits.stream()
101-
.filter(ref -> ref.title() != null && ref.title().contains("Size Trait"))
102-
.findAny().map(QuteDataRef::displayText).orElse(null);
103-
}
104-
105-
/** The alignment of this creature, or null if it has none. */
106-
public String getAlignment() {
107-
return traits.stream()
108-
.filter(ref -> ref.title() != null && ref.title().contains("Alignment Trait"))
109-
.findAny().map(QuteDataRef::displayText).orElse(null);
110-
}
111-
112-
/** The rarity of this creature, or null if it has none. */
113-
public String getRarity() {
114-
return traits.stream()
115-
.filter(ref -> ref.title() != null && ref.title().contains("Rarity Trait"))
116-
.findAny().map(QuteDataRef::displayText).orElse(null);
117-
}
118-
11998
/**
12099
* The languages and language features known by a creature. Example default output:
121100
*

src/main/java/dev/ebullient/convert/tools/pf2e/qute/QuteDataRef.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717
public record QuteDataRef(String displayText, String notePath, String title) implements Comparable<QuteDataRef> {
1818

19-
private static final Pattern MARKDOWN_LINK_PAT = Pattern.compile("^\\[(?<display>[^]]+)]\\((?<path>.*?)(?: \"(?<title>.*)\")?\\)$");
19+
private static final Pattern MARKDOWN_LINK_PAT = Pattern.compile("^\\[(?<display>.+)]\\((?<path>.*?)(?: \"(?<title>.*)\")?\\)$");
2020

2121
public QuteDataRef(String displayText) {
2222
this(displayText, null, null);

0 commit comments

Comments
 (0)