I'm working on another parser with a similar situation. I'm not positive about the GM notes, but I think it only puts a LF instead of a CRLF. Despite how the data is separated, without the html formatting it's not super obvious where the actions are. So,
Code: Select all
Actions
Ability Name 1. Ability Description 1
Ability Name 2. Ability Description 2
Ability Description 2 second paragraph
Will be a problem. For my data I have to reformat it putting the description all on one line. If there is a second paragraph I use <br><br> to break it, but still no CRLF. I also use : instead of . for the "action" key word postfix.
So, for my example:
Code: Select all
Race: Lashunta
Summary: Charismatic and telepathic race of scholars with two subspecies: one tall and lean, the other short and muscular.
Ability Adjustments
Korasha: +2 Chr, +2 Str, -2 Wis
Damaya: +2 Chr, +2 Int, -2 Con
Hit Points: 4
Size: Medium
Type: humanoid
Subtype: lashunta
Subraces: korasha, damaya
Vision: normal
Move: 30
Source: Core
RACIAL TRAITS
Dimorphic: Korasha lashuntas are muscular but often brash and unobservant. Damaya lashuntas are typically clever and well-spoken but somewhat delicate.
Lashunta Magic: Lashuntas gain the following Spell-Like abilities
At will: daze, psychokinetic hand
1/day: detect thoughts
Limited Telepathy: Lashuntas can mentally communicate with any creatures within 30 feet with whom they share a language. Conversing telepathically with multiple creatures simultaneously is just as difficult as listening to multiple people speaking.
Student: Lashuntas love to learn, and they receive a +2 racial bonus to any two skills of their choice.
I have this:
Code: Select all
@@ @parser_Races
[H: keywords = json.append("","Race","Summary","Ability Adjustments","Hit Points","Size","Type","Subtype","Subraces","Vision","Move","Source")]
[H: keywords.init = json.append("","","","",0,"","","","","",0,"")]
[H: datablocks = json.append("","RACIAL TRAITS")]
<!-- initialize race data structure -->
[H: raceObj = "{}"]
[H, foreach(keyword,keywords): raceObj = json.set(raceObj,keyword,json.get(keywords.init,roll.count))]
[H, foreach(block,datablocks): raceObj = json.set(raceObj,block,"{}")]
<!-- put each line of raw data in to a json array. -->
[H: EOL = decode("%0A")]
[H: buttonIndex = getMacroIndexes("Races")]
[H: lines = json.fromList(getMacroCommand(buttonIndex),EOL)]
<!-- loop through lines building structured data -->
<!-- initialize variables for data parsing -->
[H: keyword.main = ""]
[H: keyword.block = ""]
[H: thisRace = ""]
[H: thisBlock = ""]
<!-- about formatting text and different types:
keyword.main: keyword.data
keyword.main
keyword.indent: keyword.data
keyword.block
keyword.sub: keyword.data
keyword.indent: keyword.data
-->
[H, foreach(line,lines), code: {
<!-- get line data -->
[H, if(json.isEmpty(line)), code: {
[H: nextLine = 1]
};{
<!-- get keyword and keyword.data -->
[H: id = strfind(line,"^([^:]+):*")]
[H, if(getFindCount(id)): keyword = trim(getGroup(id,1,1)); keyword = ""]
[H, if(! json.isEmpty(keyword) && listCount(line,":") >= 2): keyword.data = trim(listGet(line,1,":")); keyword.data = trim(line)]
[H: keyword.isValid = json.contains(keywords,keyword)]
[H: keyword.isBlock = json.contains(datablocks,keyword)]
[H: keyword.hasIndent = startsWith(line," ")]
}]
<!-- keyword.main closes any block data -->
[H, if( ! nextLine && keyword.isValid && ! json.isEmpty(keyword.block)), code: {
[H, if(! json.isEmpty(thisBlock)): thisRace = json.set(thisRace,keyword.block,thisBlock)]
[H: keyword.main = keyword]
[H: keyword.block = ""]
[H: thisBlock = ""]
};{}]
<!-- keyword.block closes any opened main data blocks -->
[H, if( ! nextLine && keyword.isBlock && ! json.isEmpty(keyword.main)), code: {
[H: keyword.main = ""]
[H: keyword.block = keyword]
};{}]
<!-- check for new race -->
[H, if(! nextLine && keyword == "Race"), code: {
[H, if(! json.isEmpty(thisRace)): allRaces = json.set(allRaces,json.get(thisRace,"Race"),thisRace)]
[H: thisRace = raceObj]
[H: thisRace = json.set(thisRace,"Race",keyword.data)]
[H: nextLine = 1]
};{}]
<!-- Enter simple keyword.data -->
[H, if(! nextLine && keyword.isValid && ! json.isEmpty(keyword.data)), code: {
[H: thisRace = json.set(thisRace,keyword,keyword.data)]
[H: nextLine = 1]
};{}]
<!-- keyword.main with indent -->
[H, if(! nextLine &&
}]
!!
As you can see it's still a WIP, but the gist of it is I have certain keywords I separate by data with and block keywords to tell me the next "keys" (key:info) are blocked even though not on my main keyword list. I will also be using an indent as another form of blocked data to build my data.
I haven't figured it all out for myself, but I'll post an update when I do. I think GMNotes and putting the data in a macro will process the same way.
TL;DR - You'll have to reformat you input to get rid of 2nd paragraph, use <br><br> instead of CRLF and then you could use the EOL to get your different lines of abilities.