diff --git a/src/index.ts b/src/index.ts index 81c4377..8c0508d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,50 +1,89 @@ // TODO file handle? -export const parse = function(input: string) { - var lines = input.split(/\r*\n/); //allow Windows newlines - console.log('Got input, '+lines.length+' lines'); - var out = { - tags: {}, - files: [] +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 + +export type TOC = {/*interface: number, title: string, titleLocalized: Record, xTags: Record,*/ allTags: Record,files: string[]} + +export const parse = async function(file: FileHandle, strict = true) { + const result: TOC = { + // interface: 0, + // title: '', + // titleLocalized: {}, + // xTags: {}, + allTags: {}, + files: [], }; - lines.forEach(function(line) { - if (line.length > 1024) { - //WoW only reads the first 1024 lines - console.log('Line is longer than 1024 characters, trunicating to be like WoW'); - line = line.substr(0, 1024); + 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.substr(0, 2) === '##') { //## Title: Recount - console.log('Line is tag: '+line); - var tag = line.substr(2, line.indexOf(':')).trim().replace(':', ''); - var value = line.substr(line.indexOf(':')+1, line.length).trim(); - console.log('`'+tag+'` : `'+value+'`'); - out.tags[tag] = value; - } else if (line.substr(0, 1) === '#') { //#bug not feature - console.log('Line is comment: '+line); - } else { // recount.lua - //file loading - console.log('Line is file: '+line); - if (line.trim() !== '') { - out.files.push(line.trim()); + if (line.slice(0, TOC_PREFIX_TAG.length) === TOC_PREFIX_TAG) { + const tagData = line.slice(TOC_PREFIX_TAG.length+1).split(TOC_TAG_SEPARATOR) + if(tagData.length !== 2){ + throw new Error(`Tag could not be parsed: ${tagData}`) } - } - }); - return out; + + const tagName = tagData[0].trim() + const tagValue = tagData[1].trim() + if(strict && result.allTags[tagName]){ + throw new Error(`Duplicate value: ${tagName}`) + } + + result.allTags[tagName] = tagValue; + + // specific tags + /*switch(tagName.toLowerCase()){ + case 'interface': + result.interface = Number(tagValue) + break; + case 'title': + result.title + break; + }*/ + + // + } else if (line.slice(0, 1) !== TOC_PREFIX_COMMENT && !line.trim()) { + result.files.push(line.trimEnd())); + } + } + return result; }; -export const stringify = function(input) { - if (typeof input !== 'object') { - throw new TypeError('wowtoc.stringify input must be an object, got '+typeof input); - } +/* +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-_____ - var out = []; - for(var tag in input.tags) { - if(input.tags.hasOwnProperty(tag)) { - out.push('## '+tag+': '+input.tags[tag]); - } +*/ + +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]}`) } - (input.files || []).forEach(function(file) { - out.push(file); - }); - return out.join('\n'); -}; \ No newline at end of file + result.concat(toc.files) + return result.join('\n'); +};