36 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			36 lines
		
	
	
		
			1.1 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| // utils/formatAddress.ts
 | |
| // npm i he  (for robust HTML entity decoding)
 | |
| import { decode } from "he";
 | |
| 
 | |
| export function formatAddress(raw: string) {
 | |
|   // 1) decode entities (& → &), 2) <br> → \n, 3) tidy whitespace
 | |
|   const text = decode(raw)
 | |
|     .replace(/<br\s*\/?>/gi, "\n")
 | |
|     .replace(/\u00A0/g, " ")      //  
 | |
|     .replace(/[ \t]{2,}/g, " ")   // collapse spaces
 | |
|     .replace(/\n{2,}/g, "\n")     // collapse blank lines
 | |
|     .trim();
 | |
| 
 | |
|   // split to lines, strip empties
 | |
|   const lines = text.split("\n").map(s => s.trim()).filter(Boolean);
 | |
| 
 | |
|   // If postcode is alone (e.g., "40150") before the city line, merge: "40150 Shah Alam"
 | |
|   const merged: string[] = [];
 | |
|   for (let i = 0; i < lines.length; i++) {
 | |
|     const cur = lines[i];
 | |
|     const next = lines[i + 1];
 | |
|     if (/^\d{5}$/.test(cur) && next) {
 | |
|       merged.push(`${cur} ${next}`);
 | |
|       i++; // skip the city line, already merged
 | |
|     } else {
 | |
|       merged.push(cur);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return {
 | |
|     parts: merged,                 // array of lines
 | |
|     multiLine: merged.join("\n"),  // lines with \n
 | |
|     singleLine: merged.join(", "), // one-liner
 | |
|   };
 | |
| }
 |