From b5ed0438e85e1144b98001cf3a91d462cc95727a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:43:59 +0000 Subject: [PATCH 1/2] Initial plan From 1044e83f038e19d1083e361011eac7742000caa2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 23 Jan 2026 01:52:38 +0000 Subject: [PATCH 2/2] Optimize html escaping and object filtering --- .gitignore | 1 + packages/lib/src/utils/object/modify.test.ts | 5 ++ packages/lib/src/utils/object/modify.ts | 6 ++- packages/lib/src/utils/string/normalize.ts | 51 +++++++++++--------- 4 files changed, 37 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index cbb01e5..c45a8eb 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,7 @@ build/Release # Dependency directories node_modules/ +package-lock.json jspm_packages/ # Snowpack dependency directory (https://snowpack.dev/) diff --git a/packages/lib/src/utils/object/modify.test.ts b/packages/lib/src/utils/object/modify.test.ts index a8792ad..b33b94c 100644 --- a/packages/lib/src/utils/object/modify.test.ts +++ b/packages/lib/src/utils/object/modify.test.ts @@ -8,4 +8,9 @@ describe('Modifying objects', () => { test('pick keys', () => { expect(pick({ a: 1, b: 2 }, ['a'])).toEqual({ a: 1 }) }) + + test('handles duplicate keys', () => { + expect(pick({ a: 1, b: 2 }, ['a', 'a'])).toEqual({ a: 1 }) + expect(exclude({ a: 1, b: 2 }, ['a', 'a'])).toEqual({ b: 2 }) + }) }) diff --git a/packages/lib/src/utils/object/modify.ts b/packages/lib/src/utils/object/modify.ts index be55b69..02c86ce 100644 --- a/packages/lib/src/utils/object/modify.ts +++ b/packages/lib/src/utils/object/modify.ts @@ -3,8 +3,9 @@ export function pick( keys: K ): Pick export function pick(object: any, keys: string[]) { + const keySet = new Set(keys) return Object.fromEntries( - Object.entries(object).filter(([key]) => keys.includes(key)) + Object.entries(object).filter(([key]) => keySet.has(key)) ) } @@ -14,8 +15,9 @@ type ExcludeFunction = ( ) => Omit export const exclude: ExcludeFunction = (object, keys: any): any => { + const keySet = new Set(keys) return Object.fromEntries( - Object.entries(object).filter(([key]) => !keys.includes(key)) + Object.entries(object).filter(([key]) => !keySet.has(key)) ) } diff --git a/packages/lib/src/utils/string/normalize.ts b/packages/lib/src/utils/string/normalize.ts index 4c670c3..6276b0f 100644 --- a/packages/lib/src/utils/string/normalize.ts +++ b/packages/lib/src/utils/string/normalize.ts @@ -1,5 +1,28 @@ import { pipe } from '../function/pipe' +const ESCAPE_MAP: Record = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''' +} +const UNESCAPE_MAP: Record = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + ''': "'" +} +const ESCAPE_REGEX = new RegExp( + `(${Object.keys(ESCAPE_MAP).join('|')})`, + 'g' +) +const UNESCAPE_REGEX = new RegExp( + `(${Object.keys(UNESCAPE_MAP).join('|')})`, + 'g' +) + // TODO: refactor export function normalizeNewLines(string_: string) { @@ -39,35 +62,15 @@ export function normalizeNewLines(string_: string) { } export function escapeHtml(unsafeText: string): string { - const map: Record = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - } - return pipe( - Object.keys(map), - (keys) => keys.join('|'), - (match) => new RegExp(`(${match})`, 'g'), - (regex) => unsafeText.replaceAll(regex, (match) => map[match]) + unsafeText, + (text) => text.replaceAll(ESCAPE_REGEX, (match) => ESCAPE_MAP[match]) ) } export function unescapeHtml(unsafeText: string): string { - const map: Record = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - ''': "'" - } - return pipe( - Object.keys(map), - (keys) => keys.join('|'), - (match) => new RegExp(`(${match})`, 'g'), - (regex) => unsafeText.replaceAll(regex, (match) => map[match]) + unsafeText, + (text) => text.replaceAll(UNESCAPE_REGEX, (match) => UNESCAPE_MAP[match]) ) }