finished parser protoype
This commit is contained in:
parent
6c63f25bcf
commit
eaa0e0f74b
237
src/index.ts
237
src/index.ts
@ -1,89 +1,198 @@
|
||||
// TODO file handle?
|
||||
import { FileHandle, open } from 'fs/promises';
|
||||
// const file = await fsPromise.open('./words.txt', 'r');
|
||||
const TOC_PREFIX_TAG = '## '
|
||||
const TOC_PREFIX_COMMENT = '#'
|
||||
const TOC_TAG_SEPARATOR = ':'
|
||||
const TOC_LINE_MAX_LENGTH = 1024
|
||||
/*
|
||||
https://wowwiki-archive.fandom.com/wiki/TOC_format
|
||||
https://wowpedia.fandom.com/wiki/TOC_format
|
||||
*/
|
||||
import { FileHandle } from 'fs/promises';
|
||||
export const TOC_PREFIX_TAG = '## '
|
||||
export const TOC_PREFIX_COMMENT = '#'
|
||||
export const TOC_TAG_DELIMITER = ':'
|
||||
export const TOC_LINE_MAX_LENGTH = 1024
|
||||
|
||||
export type TOC = {/*interface: number, title: string, titleLocalized: Record<string,string>, xTags: Record<string, string>,*/ allTags: Record<string, string>,files: string[]}
|
||||
export const TOC_TAG_NAME_INTERFACE = 'Interface'
|
||||
export const TOC_TAG_NAME_TITLE = 'Title'
|
||||
export const TOC_TAG_NAME_NOTES = 'Notes'
|
||||
export const TOC_TAG_NAME_ICONTEXTURE = 'IconTexture'
|
||||
export const TOC_TAG_NAME_ICONATLAS = 'IconAtlas'
|
||||
export const TOC_TAG_NAME_ADDONCOMPARTMENTFUNC = 'AddonCompartmentFunc'
|
||||
export const TOC_TAG_NAME_ADDONCOMPARTMENTFUNCONENTER = 'AddonCompartmentFuncOnEnter'
|
||||
export const TOC_TAG_NAME_ADDONCOMPARTMENTFUNCONLEAVE = 'AddonCompartmentFuncOnLeave'
|
||||
export const TOC_TAG_NAME_LOADONDEMAND = 'LoadOnDemand'
|
||||
export const TOC_TAG_NAME_OPTIONALDEPS = 'OptionalDeps'
|
||||
export const TOC_TAG_NAME_LOADWITH = 'LoadWith'
|
||||
export const TOC_TAG_NAME_LOADMANAGERS = 'LoadManagers'
|
||||
export const TOC_TAG_NAME_DEFAULTSTATE = 'DefaultState'
|
||||
export const TOC_TAG_NAME_SAVEDVARIABLES = 'SavedVariables'
|
||||
export const TOC_TAG_NAME_SAVEDVARIABESPERCHARACTER = 'SavedVariablesPerCharacter'
|
||||
export const TOC_TAG_NAME_AUTHOR = 'Author'
|
||||
export const TOC_TAG_NAME_VERSION = 'Version'
|
||||
|
||||
export const parse = async function(file: FileHandle, strict = true) {
|
||||
const result: TOC = {
|
||||
// interface: 0,
|
||||
// title: '',
|
||||
// titleLocalized: {},
|
||||
// xTags: {},
|
||||
allTags: {},
|
||||
files: [],
|
||||
export const TOC_TAG_PREFIX_TITLELOCALIZED = 'title-'
|
||||
export const TOC_TAG_PREFIX_NOTESLOCALIZED = 'notes-'
|
||||
export const TOC_TAG_PREFIX_DEP = 'dep'
|
||||
export const TOC_TAG_PREFIX_X = 'x-'
|
||||
|
||||
export const TOC_TAG_LIST_DELIMITER = ','
|
||||
|
||||
export const TOC_TAG_VALUE_LOADONDEMAND = '1'
|
||||
export const TOC_TAG_VALUE_DEFAULTSTATE_DISABLED = 'disabled'
|
||||
|
||||
export enum WOW_LOCALES {
|
||||
frFR = 'frFR',
|
||||
deDE = 'deDE',
|
||||
enGB = 'enGB',
|
||||
enUS = 'enUS',
|
||||
itIT = 'itIT',
|
||||
koKR = 'koKR',
|
||||
zhCN = 'zhCN',
|
||||
zhTW = 'zhTW',
|
||||
ruRU = 'ruRU',
|
||||
esES = 'esES',
|
||||
esMX = 'esMX',
|
||||
ptBR = 'ptBR',
|
||||
}
|
||||
|
||||
export class TOC {
|
||||
Interface: number | null = null
|
||||
Title: string | null = null
|
||||
TitleLocalized: Partial<Record<WOW_LOCALES,string>> = {}
|
||||
Notes: string | null = null
|
||||
NotesLocalized: Partial<Record<WOW_LOCALES,string>> = {}
|
||||
IconTexture: string | null = null
|
||||
IconAtlas: string | null = null
|
||||
AddonCompartmentFunc: string | null = null
|
||||
AddonCompartmentFuncOnEnter: string | null = null
|
||||
AddonCompartmentFuncOnLeave: string | null = null
|
||||
LoadOnDemand: boolean = false
|
||||
Dependencies: string[] = []
|
||||
OptionalDeps: string[] = []
|
||||
LoadWith: string[] = []
|
||||
LoadManagers: string[] = []
|
||||
DefaultState: boolean = true
|
||||
SavedVariables: string[] = []
|
||||
SavedVariablesPerCharacter: string[] = []
|
||||
Author: string | null = null
|
||||
Version: string | null = null
|
||||
xTags: Record<string, string> = {}
|
||||
files: string[] = []
|
||||
|
||||
/*
|
||||
toString(){
|
||||
var result: string[] = [];
|
||||
for(const tag in toc.allTags) {
|
||||
result.push(`${TOC_PREFIX_TAG}${tag}${TOC_TAG_SEPARATOR} ${toc.allTags[tag]}`)
|
||||
}
|
||||
result.concat(this.files)
|
||||
return result.join('\n');
|
||||
};
|
||||
*/
|
||||
}
|
||||
|
||||
// import { open } from 'fs/promises';
|
||||
// const file = await open('./words.txt', 'r');
|
||||
export const parse = async function(file: FileHandle, strict = true) {
|
||||
const result = new TOC();
|
||||
const allTags: Record<string, string> = {}
|
||||
for await (const line of file.readLines()) {
|
||||
if (strict && line.length > TOC_LINE_MAX_LENGTH) {
|
||||
throw new Error('Line is longer than TOC_LINE_MAX_LENGTH characters, WoW will truncate!');
|
||||
}
|
||||
|
||||
if (line.slice(0, TOC_PREFIX_TAG.length) === TOC_PREFIX_TAG) {
|
||||
const tagData = line.slice(TOC_PREFIX_TAG.length+1).split(TOC_TAG_SEPARATOR)
|
||||
const tagData = line.slice(TOC_PREFIX_TAG.length+1).split(TOC_TAG_DELIMITER)
|
||||
if(tagData.length !== 2){
|
||||
throw new Error(`Tag could not be parsed: ${tagData}`)
|
||||
if(strict){
|
||||
throw new Error(`Tag could not be parsed: ${tagData}`)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
const tagName = tagData[0].trim()
|
||||
const tagValue = tagData[1].trim()
|
||||
if(strict && result.allTags[tagName]){
|
||||
if(strict && allTags[tagName]){
|
||||
throw new Error(`Duplicate value: ${tagName}`)
|
||||
}
|
||||
|
||||
result.allTags[tagName] = tagValue;
|
||||
allTags[tagName] = tagValue;
|
||||
|
||||
// specific tags
|
||||
/*switch(tagName.toLowerCase()){
|
||||
case 'interface':
|
||||
result.interface = Number(tagValue)
|
||||
switch(tagName.toLowerCase()){
|
||||
case TOC_TAG_NAME_INTERFACE.toLowerCase():
|
||||
result.Interface = Number(tagValue)
|
||||
break;
|
||||
case 'title':
|
||||
result.title
|
||||
case TOC_TAG_NAME_TITLE.toLowerCase():
|
||||
result.Title = tagValue
|
||||
break;
|
||||
}*/
|
||||
|
||||
//
|
||||
case TOC_TAG_NAME_NOTES.toLocaleLowerCase():
|
||||
result.Notes = tagValue
|
||||
break
|
||||
case TOC_TAG_NAME_ICONTEXTURE.toLowerCase():
|
||||
result.IconTexture = tagValue
|
||||
break
|
||||
case TOC_TAG_NAME_ICONATLAS.toLowerCase():
|
||||
result.IconAtlas = tagValue
|
||||
break
|
||||
case TOC_TAG_NAME_ADDONCOMPARTMENTFUNC.toLowerCase():
|
||||
result.AddonCompartmentFunc = tagValue
|
||||
break
|
||||
case TOC_TAG_NAME_ADDONCOMPARTMENTFUNCONENTER.toLowerCase():
|
||||
result.AddonCompartmentFuncOnEnter = tagValue
|
||||
break
|
||||
case TOC_TAG_NAME_ADDONCOMPARTMENTFUNCONLEAVE.toLowerCase():
|
||||
result.AddonCompartmentFuncOnLeave = tagValue
|
||||
break
|
||||
case TOC_TAG_NAME_LOADONDEMAND.toLowerCase():
|
||||
result.LoadOnDemand = tagValue === TOC_TAG_VALUE_LOADONDEMAND
|
||||
break
|
||||
case TOC_TAG_NAME_OPTIONALDEPS.toLowerCase():
|
||||
result.OptionalDeps = tagValue.split(TOC_TAG_LIST_DELIMITER).map((s) => s.trim())
|
||||
break
|
||||
case TOC_TAG_NAME_LOADWITH.toLowerCase():
|
||||
result.LoadWith = tagValue.split(TOC_TAG_LIST_DELIMITER).map((s) => s.trim())
|
||||
break
|
||||
case TOC_TAG_NAME_LOADMANAGERS.toLowerCase():
|
||||
result.LoadManagers = tagValue.split(TOC_TAG_LIST_DELIMITER).map((s) => s.trim())
|
||||
break
|
||||
case TOC_TAG_NAME_DEFAULTSTATE.toLowerCase():
|
||||
result.DefaultState = tagValue.toLowerCase() !== TOC_TAG_VALUE_DEFAULTSTATE_DISABLED
|
||||
break
|
||||
case TOC_TAG_NAME_SAVEDVARIABLES.toLowerCase():
|
||||
result.SavedVariables = tagValue.split(TOC_TAG_LIST_DELIMITER).map((s) => s.trim())
|
||||
break
|
||||
case TOC_TAG_NAME_SAVEDVARIABESPERCHARACTER.toLowerCase():
|
||||
result.SavedVariablesPerCharacter = tagValue.split(TOC_TAG_LIST_DELIMITER).map((s) => s.trim())
|
||||
break
|
||||
case TOC_TAG_NAME_AUTHOR.toLowerCase():
|
||||
result.Author = tagValue
|
||||
break
|
||||
case TOC_TAG_NAME_VERSION.toLowerCase():
|
||||
result.Version = tagValue
|
||||
break
|
||||
default:
|
||||
if(tagName.toLowerCase().startsWith(TOC_TAG_PREFIX_TITLELOCALIZED) && tagName.length === TOC_TAG_PREFIX_TITLELOCALIZED.length+4){
|
||||
const locale = tagName.slice(TOC_TAG_PREFIX_TITLELOCALIZED.length,TOC_TAG_PREFIX_TITLELOCALIZED.length+4)
|
||||
if(Object.keys(WOW_LOCALES).includes(locale)){
|
||||
result.TitleLocalized[locale as WOW_LOCALES] = tagValue
|
||||
} else if(strict){
|
||||
throw new Error(`locale not found ${locale}`)
|
||||
}
|
||||
} else if(tagName.toLowerCase().startsWith(TOC_TAG_PREFIX_NOTESLOCALIZED) && tagName.length === TOC_TAG_PREFIX_NOTESLOCALIZED.length+4){
|
||||
const locale = tagName.slice(TOC_TAG_PREFIX_NOTESLOCALIZED.length,TOC_TAG_PREFIX_NOTESLOCALIZED.length+4)
|
||||
if(Object.keys(WOW_LOCALES).includes(locale)){
|
||||
result.NotesLocalized[locale as WOW_LOCALES] = tagValue
|
||||
} else if(strict){
|
||||
throw new Error(`locale not found ${locale}`)
|
||||
}
|
||||
} else if(tagName.toLowerCase().startsWith(TOC_TAG_PREFIX_DEP)){
|
||||
result.Dependencies = tagValue.split(TOC_TAG_LIST_DELIMITER).map((s) => s.trim())
|
||||
} else if(tagName.toLowerCase().startsWith(TOC_TAG_PREFIX_X)){
|
||||
result.xTags[tagName.slice(TOC_TAG_PREFIX_X.length)] = tagValue
|
||||
} else if(strict){
|
||||
throw new Error(`Unknown Tag name: ${tagName}`)
|
||||
}
|
||||
}
|
||||
} else if (line.slice(0, 1) !== TOC_PREFIX_COMMENT && !line.trim()) {
|
||||
result.files.push(line.trimEnd()));
|
||||
result.files.push(line.trimEnd());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
/*
|
||||
https://wowpedia.fandom.com/wiki/TOC_format
|
||||
## Interface: 100007
|
||||
## Title: Waiting for Godot
|
||||
## Title-frFR: En attendant Godot
|
||||
## Notes: This word is |cFFFF0000red|r
|
||||
## IconTexture: Interface\Icons\TEMP
|
||||
## IconAtlas: TaskPOI-Icon
|
||||
// ## AddonCompartmentFunc: MyAddon_OnAddonCompartmentClick
|
||||
// ## AddonCompartmentFuncOnEnter: MyAddon_OnAddonCompartmentEnter
|
||||
// ## AddonCompartmentFuncOnLeave: MyAddon_OnAddonCompartmentLeave
|
||||
## LoadOnDemand: 1
|
||||
## Dependencies: someAddOn, someOtherAddOn
|
||||
## OptionalDeps: someAddOn, someOtherAddOn
|
||||
## LoadWith: someAddOn, someOtherAddOn
|
||||
// ## LoadManagers: someAddOn, someOtherAddOn
|
||||
## DefaultState: disabled
|
||||
## SavedVariables: MyAddOnNameFoo, MyAddOnNameBar
|
||||
## SavedVariablesPerCharacter: MyAddOnNameAnotherVariable
|
||||
## Author
|
||||
## Version
|
||||
## X-_____
|
||||
|
||||
*/
|
||||
|
||||
export const stringify = function(toc: TOC) {
|
||||
var result: string[] = [];
|
||||
for(const tag in toc.allTags) {
|
||||
result.push(`${TOC_PREFIX_TAG}${tag}${TOC_TAG_SEPARATOR} ${toc.allTags[tag]}`)
|
||||
}
|
||||
result.concat(toc.files)
|
||||
return result.join('\n');
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user