1
+ # 5eTools Entries Tagger
2
+ # ======================
3
+ #
4
+ # A hastily spun-out auto-tagger for `entries`-like strings. This script recursively traverses through a given
5
+ # JSON file, looking for any property named `entries`, `entry`, or `items`. If it finds any of these properties,
6
+ # it applies the `Tag-Entry` function below onto it, which is itself just a huge bundle of regex to try to tag
7
+ # some content by semantics. It then spits out a new JSON file with "_TAGGED" appended to the filename in the
8
+ # same directory.
9
+ #
10
+ # The regex was written originally for use in my bulk creature converters, so some extra work could be done if you
11
+ # want (though good luck). It aims to accurately tag things with minimal false positives, so you're more likely to
12
+ # have false negatives (i.e. things that should be tagged but aren't). It also obviously can't tag formatting
13
+ # choices (e.g. `{@b bold text}`) or 'innumerable' lists (e.g. creatures, items, spells). It should ignore text
14
+ # that is already tagged, but I wouldn't trust that necessarily and instead recommend you just don't tag text
15
+ # before running this. In summary, don't expect it to do all the work for you, but # it'll get you 60% of the way
16
+ # there!
17
+ #
18
+ # Note: this script requires PowerShell 6 or higher. Windows 10 only has PowerShell 5 installed by default.
19
+ #
20
+ # Usage:
21
+ # & <path to script> -Path <path to homebrew file>
22
+ #
23
+ # Parameters:
24
+ # -Path (string; required): absolute or relative path to a file or directory
25
+ #
26
+ # Examples:
27
+ # & .\entries-tagger.ps1 -Path ".\Anti-Brew-Conversion Gang; Spappz's Scroll of Suffering.json"
28
+ #
29
+ #
30
+ # Spappz 2023
31
+ #
32
+ # MIT License
33
+
34
+
35
+ PARAM (
36
+ [Parameter (Mandatory , ValueFromPipeline , Position = 0 )][String ]$Path
37
+ )
38
+
39
+ function Tag-Entry {
40
+ PARAM (
41
+ [Parameter (Mandatory )][String ]$text
42
+ )
43
+ PROCESS {
44
+ return (
45
+ $text -replace ' ^\s+' -replace ' \s+$' -replace ' {2,}' , ' ' `
46
+ -replace ' (?<=\()([\dd \+\-×x\*÷\/\*]+\d)(?=\))' , ' {@damage $1}' `
47
+ -replace ' \b(\d+d[\dd \+\-×x\*÷/]*\d)(?=( (\w){4,11})? damage\b)' , ' {@damage $1}' `
48
+ -replace ' (?<=\brolls? (a )?)(d\d+)\b(?![{|])' , ' {@dice $2}' `
49
+ -replace ' (?<!@d(amage|ice)) (\d+d[\dd \+\-×x\*÷/]*\d)\b(?![{|])' , ' {@dice $2}' `
50
+ -creplace ' (?<!\w)\+?(\-?\d)(?= (to hit|modifier))' , ' {@hit $1}' `
51
+ -creplace ' \bDC ?(\d+)\b(?![{|])' , ' {@dc $1}' `
52
+ -replace " (?<=\b(be(comes?)?|is( ?n[o']t)?|while|a(nd?|lso)?|or|th(e|at)) )(blinded|charmed|deafened|frightened|grappled|in(capacitated|nvisible)|p(aralyz|etrifi|oison)ed|restrained|stunned|unconscious)\b" , ' {@condition $6}' `
53
+ -replace " (?<=\b(knocked|pushed|shoved|becomes?|falls?|while|lands?) )(prone|unconscious)\b" , ' {@condition $2}' `
54
+ -replace " (?<=levels? of )exhaustion\b" , " {@condition exhaustion}" `
55
+ -creplace ' (?<=\()(A(thletics|crobatics|rcana|nimal Handling)|Per(ception|formance|suasion)|S(leight of Hand|tealth|urvival)|In(sight|vestigation|timidation)|Nature|Religion|Medicine|History|Deception)(?=\))' , ' {@skill $1}' `
56
+ -creplace ' \b(A(thletics|crobatics|rcana|nimal Handling)|Per(ception|formance|suasion)|S(leight of Hand|tealth|urvival)|In(sight|vestigation|timidation)|Nature|Religion|Medicine|History|Deception)(?= (check|modifier|bonus|roll|score))' , ' {@skill $1}' `
57
+ -replace ' (?<!cast (the )?)\b(darkvision|blindsight|tr(emorsense|uesight))\b(?!( spell|[{|]))' , ' {@sense $2}' `
58
+ -creplace " \b(Attack(?! roll)|Cast a Spell|D(ash|isengage|odge)|H(elp|ide)|Ready|Search|Use an Object)\b(?![{|])" , ' {@action $1}' `
59
+ -replace ' \bopportunity attack\b(?![{|])' , ' {@action opportunity attack}' `
60
+ -replace ' \b(opportunity attacks|attacks? of opportunity)\b' , ' {@action opportunity attack||$1}' `
61
+ -replace ' \b(\d\d?) percent chance\b' , ' {@chance $1} chance'
62
+ )
63
+ }
64
+ }
65
+
66
+ # ##
67
+
68
+ # Preamble rubbish
69
+ if ((Test-Path $Path )) {
70
+ $target = Get-Item $Path
71
+ if ($target.Extension -eq " .json" ) {
72
+ try {
73
+ $brew = Get-Content $target - Encoding Utf8 | ConvertFrom-Json
74
+ if (-not $brew._meta ) {
75
+ Write-Error " `` $target `` doesn't contain 5eTools homebrew JSON."
76
+ break
77
+ }
78
+ } catch {
79
+ Write-Error " `` $target `` contains invalid JSON."
80
+ break
81
+ }
82
+ } else {
83
+ Write-Error " `` $target `` isn't a JSON file."
84
+ break
85
+ }
86
+ } else {
87
+ Write-Error " `` $Path `` doesn't exist."
88
+ break
89
+ }
90
+
91
+ # ##
92
+
93
+ # Recursive JSON object walker to pick out entry-like strings
94
+
95
+ function Traverse-Tree {
96
+ PARAM (
97
+ [Parameter (Mandatory , Position = 0 )]$obj ,
98
+ [Parameter (Mandatory , Position = 1 )][bool ]$isEntry
99
+ )
100
+ PROCESS {
101
+ if ($isEntry -and $obj -is [String ]) {
102
+ return (Tag- Entry $obj )
103
+ } elseif ($obj -is [PSCustomObject ]) {
104
+ foreach ($prop in $obj.PSObject.Properties ) {
105
+ if ($prop.Name -in @ (' entries' , ' items' , ' entry' )) {
106
+ $isEntry = $true
107
+ } else {
108
+ $isEntry = $false
109
+ }
110
+ $prop.Value = Traverse- Tree $prop.Value $isEntry
111
+ }
112
+ return $obj
113
+ } elseif ($obj -is [Array ]) {
114
+ for ($i = 0 ; $i -lt $obj.Count ; $i ++ ) {
115
+ $obj [$i ] = Traverse- Tree $obj [$i ] $isEntry
116
+ }
117
+ Write-Output @ ($obj ) - NoEnumerate
118
+ } else {
119
+ return $obj
120
+ }
121
+ }
122
+ }
123
+
124
+ $brew = Traverse- Tree $brew $false
125
+
126
+ # ##
127
+
128
+ # Output the rubbish
129
+
130
+ $outPath = $Path -replace ' \.json$' , ' _TAGGED.json'
131
+ (
132
+ [Regex ]::Replace(
133
+ (ConvertTo-Json $brew - Depth 99 ),
134
+ " \\u(?<Value>\w{4})" ,
135
+ {
136
+ PARAM ($Matches )
137
+ (
138
+ [char ](
139
+ [int ]::Parse(
140
+ $Matches.Groups [' Value' ].Value, [System.Globalization.NumberStyles ]::HexNumber
141
+ )
142
+ )
143
+ ).ToString()
144
+ }
145
+ ) -replace ' —' , ' \u2014' -replace ' –' , ' \u2013' -replace ' −' , ' \u2212'
146
+ ) | Out-File - FilePath $outPath - Encoding UTF8
0 commit comments