From 3ec70051987a74bcc3e885e59a19536fc9c77772 Mon Sep 17 00:00:00 2001 From: Yura Dupyn <2153100+omedusyo@users.noreply.github.com> Date: Sat, 25 Apr 2026 11:20:21 +0200 Subject: [PATCH] Introduce `CodePointString` --- README.md | 3 +++ src/index.ts | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/README.md b/README.md index 3d60881..5d92fc7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ TypeScript library for handling source code strings without having to deal with intricacies of JS's UTF16 encoding. +# CodePointString +A wrapper for a string that's just an array of codepoints. There's no newline or offset tracking to the original string. + # SourceText A sane, UTF-16-safe string wrapper specifically designed for parsing source code, tracking line numbers, and generating CLI error messages. Think of it as a fat wrapper for a string that understand more info about the string like line structure. diff --git a/src/index.ts b/src/index.ts index 1052ac6..2db4378 100644 --- a/src/index.ts +++ b/src/index.ts @@ -68,6 +68,44 @@ export type CodePointSpan = { end: CodePointIndex, } +// === CodePointString === +export class CodePointString { + readonly codePoints: readonly CodePoint[]; + + constructor(source: string) { + const codePointsInternal: CodePoint[] = []; + let i = 0; + while (i < source.length) { + const char = source.codePointAt(i) as CodePoint; + codePointsInternal.push(char); + + const size =(char > 0xFFFF ? 2 : 1); + i += size; + } + this.codePoints = Object.freeze(codePointsInternal); + } + + static makeFromString(s: string): CodePointString { + return new CodePointString(s); + } + + codePointAt(index: CodePointIndex): CodePoint { + return this.codePoints[index]; + } + + get length(): CodePointIndex { + return this.codePoints.length; + } + + toString(): string { + let result = ""; + for (const cp of this.codePoints) { + result += String.fromCodePoint(cp); + } + return result; + } +} + // === Source Text === // TODO: // @deprecated and say to use `SourceText.makeFromString` instead.