this repo has no description
at main 104 lines 3.3 kB view raw
1export interface Kink { 2 name: string; 3 description?: string; 4} 5 6export interface KinkCategory { 7 name: string; 8 description?: string; 9 kinks: Kink[]; 10 participants: string[]; 11} 12 13function sliceOnce(str: string, char: string): [string, string?] { 14 const index = str.indexOf(char); 15 16 if (index !== -1) { 17 const leftHalf = str.slice(0, index).trim(); 18 const rightHalf = str.slice(index + char.length).trim(); 19 return [leftHalf, rightHalf]; 20 } 21 22 return [str.trim(), undefined]; 23} 24 25function removeSymbols(str: string, symbolStart: string, symbolEnd: string | null = null): string { 26 if (str.startsWith(symbolStart)) { 27 str = str.slice(1); 28 } 29 30 if (symbolEnd !== null && str.endsWith(symbolEnd)) { 31 str = str.slice(0, -1); 32 } 33 34 return str.trim(); 35} 36 37export function unparseKinks(kinkCategories: KinkCategory[]): string { 38 let result: string[] = []; 39 for (const category of kinkCategories) { 40 result.push('# ', category.name); 41 if (category.description) { 42 result.push(' ::: ', category.description); 43 } 44 result.push('\n'); 45 if (category.participants.length > 0) { 46 result.push('(', category.participants.join(', '), ')\n'); 47 } 48 for (const kink of category.kinks) { 49 result.push('* ', kink.name); 50 if (kink.description) { 51 result.push(' ::: ', kink.description); 52 } 53 result.push('\n'); 54 } 55 result.push('\n'); 56 } 57 58 return result.join(""); 59} 60 61export function parseKinks(kinkStr: string) { 62 const kinkCode = kinkStr 63 .split("\n") 64 .map((e, i) => [e.trim(), i + 1] as const) 65 .filter((e) => e[0]); 66 67 const kinkCategories: KinkCategory[] = []; 68 69 const kinksById: Kink[] = []; 70 71 let curKinkCategory: KinkCategory | undefined; 72 let curKinkId = 0; 73 for (const [line, lineNum] of kinkCode) { 74 if (line.startsWith("#")) { 75 const [categoryName, categoryDesc] = sliceOnce(removeSymbols(line, "#"), ":::"); 76 77 curKinkCategory = { 78 name: categoryName, 79 description: categoryDesc, 80 kinks: [], 81 participants: ["Unknown"], 82 }; 83 kinkCategories.push(curKinkCategory); 84 } else if (line.startsWith("(") && line.endsWith(")")) { 85 if (curKinkCategory === undefined) { 86 throw new Error(`Encountered a participant definition before a kink type declaration (line ${lineNum})`); 87 } 88 curKinkCategory.participants = removeSymbols(line, "(", ")") 89 .split(",") 90 .map((e) => e.trim()); 91 } else if (line.startsWith("*")) { 92 if (curKinkCategory?.kinks === undefined) { 93 throw new Error(`Encountered a kink definition before a kink type declaration (line ${lineNum})`); 94 } 95 96 const [kinkName, kinkDescription] = sliceOnce(removeSymbols(line, "*"), ":::"); 97 const kink = { name: kinkName, description: kinkDescription }; 98 curKinkCategory.kinks.push(kink); 99 kinksById[curKinkId++] = kink; 100 } 101 } 102 103 return { kinkCategories, kinksById }; 104}