From e288b073b96d87555328dffcedcaa8f55c6a2b6f Mon Sep 17 00:00:00 2001 From: Krzysztof kuhy Rudnicki Date: Sun, 4 Oct 2026 22:45:34 +0200 Subject: [PATCH] js_anki: prettier-format string.json Co-Authored-By: Claude Opus 5 (1M context) --- python_pkg/js_anki/string.json | 377 ++++++++++++++++++++++++++++++--- 1 file changed, 345 insertions(+), 32 deletions(-) diff --git a/python_pkg/js_anki/string.json b/python_pkg/js_anki/string.json index a635e55f..34e9657d 100644 --- a/python_pkg/js_anki/string.json +++ b/python_pkg/js_anki/string.json @@ -1,34 +1,347 @@ [ - {"method":"charAt / s[i]","tier":"core","task":"Get the character at index i","call":"s[i] // or s.charAt(i)","mutates":false,"returns":"1-char string; s[i] gives undefined out of range, charAt gives ''","example":"return ['abc'[1],'abc'.charAt(5),'abc'[5]];","expected":"[\"b\",\"\",null]","gotcha":"Strings are immutable: s[0] = 'x' silently does nothing."}, - {"method":"charCodeAt","tier":"core","task":"Get the char code of the character at index i","call":"s.charCodeAt(i)","mutates":false,"returns":"number (UTF-16 code unit)","example":"return ['a'.charCodeAt(0),'c'.charCodeAt(0)-'a'.charCodeAt(0)];","expected":"[97,2]","gotcha":"Alphabet index idiom: s.charCodeAt(i) - 97."}, - {"method":"String.fromCharCode","tier":"core","task":"Turn a char code into a character","call":"String.fromCharCode(code)","mutates":false,"returns":"string","example":"return String.fromCharCode(97+2);","expected":"\"c\"","gotcha":"Static method on String, not on a string value."}, - {"method":"split","tier":"core","task":"Split a string into an array by a separator","call":"s.split(sep)","mutates":false,"returns":"array of strings","signature":"s.split(separator, limit) // split('') = chars","example":"return ['a,b'.split(','),'abc'.split('')];","expected":"[[\"a\",\"b\"],[\"a\",\"b\",\"c\"]]"}, - {"method":"[...s]","tier":"core","task":"Turn a string into an array of characters","call":"[...s] // or Array.from(s)","mutates":false,"returns":"new array of characters","example":"return [...'abc'];","expected":"[\"a\",\"b\",\"c\"]","gotcha":"Unlike split(''), spread keeps emoji/surrogate pairs whole."}, - {"method":"reverse a string","tier":"core","task":"Reverse a string","call":"[...s].reverse().join('')","mutates":false,"returns":"new string","example":"return [...'abc'].reverse().join('');","expected":"\"cba\"","gotcha":"Strings have no reverse(); go via an array."}, - {"method":"slice","tier":"core","task":"Get s[i..j) as a substring","call":"s.slice(i, j)","mutates":false,"returns":"new string; end exclusive","signature":"s.slice(start, end) // end exclusive, negatives count from the end","example":"return ['abcdef'.slice(1,3),'abcdef'.slice(-2)];","expected":"[\"bc\",\"ef\"]"}, - {"method":"substring","tier":"core","task":"Substring by two indices (and how it differs from slice)","call":"s.substring(i, j)","mutates":false,"returns":"new string; end exclusive","signature":"s.substring(start, end) // swaps args if start > end, negatives → 0","example":"return ['abcdef'.substring(3,1),'abcdef'.slice(3,1),'abcdef'.substring(-2)];","expected":"[\"bc\",\"\",\"abcdef\"]","gotcha":"Prefer slice(): substring swaps arguments and treats negatives as 0."}, - {"method":"indexOf","tier":"core","task":"Find the index of a substring (-1 if absent)","call":"s.indexOf(sub)","mutates":false,"returns":"first index, or -1","signature":"s.indexOf(searchString, fromIndex)","example":"return ['hello'.indexOf('l'),'hello'.indexOf('z')];","expected":"[2,-1]"}, - {"method":"includes","tier":"core","task":"Check whether a string contains a substring","call":"s.includes(sub)","mutates":false,"returns":"boolean","example":"return 'hello'.includes('ell');","expected":"true","gotcha":"Case-sensitive; a RegExp argument throws."}, - {"method":"startsWith","tier":"core","task":"Check whether a string starts with a prefix","call":"s.startsWith(prefix)","mutates":false,"returns":"boolean","example":"return 'hello'.startsWith('he');","expected":"true"}, - {"method":"endsWith","tier":"core","task":"Check whether a string ends with a suffix","call":"s.endsWith(suffix)","mutates":false,"returns":"boolean","example":"return 'hello'.endsWith('lo');","expected":"true"}, - {"method":"toLowerCase","tier":"core","task":"Lowercase a string","call":"s.toLowerCase()","mutates":false,"returns":"new string","example":"return 'aBc'.toLowerCase();","expected":"\"abc\""}, - {"method":"toUpperCase","tier":"core","task":"Uppercase a string","call":"s.toUpperCase()","mutates":false,"returns":"new string","example":"return 'aBc'.toUpperCase();","expected":"\"ABC\""}, - {"method":"trim","tier":"core","task":"Strip whitespace from both ends","call":"s.trim()","mutates":false,"returns":"new string","example":"return ' a b '.trim();","expected":"\"a b\""}, - {"method":"repeat","tier":"core","task":"Repeat a string n times","call":"s.repeat(n)","mutates":false,"returns":"new string","example":"return 'ab'.repeat(3);","expected":"\"ababab\"","gotcha":"Negative n throws RangeError."}, - {"method":"padStart","tier":"core","task":"Left-pad a string to a length (e.g. zero-pad)","call":"s.padStart(len, '0')","mutates":false,"returns":"new string","signature":"s.padStart(targetLength, padString)","example":"return '5'.padStart(3,'0');","expected":"\"005\""}, - {"method":"padEnd","tier":"core","task":"Right-pad a string to a length","call":"s.padEnd(len, ' ')","mutates":false,"returns":"new string","signature":"s.padEnd(targetLength, padString)","example":"return 'ab'.padEnd(5,'.');","expected":"\"ab...\""}, - {"method":"replace","tier":"core","task":"Replace occurrences of a pattern (first only vs all)","call":"s.replace(pattern, replacement)","mutates":false,"returns":"new string","signature":"s.replace(patternOrString, replacementOrFn)","example":"return ['aaa'.replace('a','b'),'aaa'.replace(/a/g,'b')];","expected":"[\"baa\",\"bbb\"]","gotcha":"A string pattern replaces only the FIRST match. Use /x/g or replaceAll."}, - {"method":"replaceAll","tier":"core","task":"Replace ALL occurrences of a substring","call":"s.replaceAll(sub, replacement)","mutates":false,"returns":"new string","signature":"s.replaceAll(patternOrString, replacementOrFn)","example":"return 'aaa'.replaceAll('a','b');","expected":"\"bbb\"","gotcha":"A RegExp argument must have the g flag or it throws."}, - {"method":"at","tier":"core","task":"Get the LAST character (or nth from the end)","call":"s.at(-1)","mutates":false,"returns":"1-char string, or undefined","example":"return ['abc'.at(-1),'abc'.at(0)];","expected":"[\"c\",\"a\"]"}, - {"method":"match","tier":"core","task":"Find all regex matches in a string","call":"s.match(/\\d+/g)","mutates":false,"returns":"array of matches, or null if none","example":"return ['a1b22'.match(/\\d+/g),'abc'.match(/\\d+/g)];","expected":"[[\"1\",\"22\"],null]","gotcha":"Without the g flag you get a single match object, not all matches. null → use ?? []."}, - {"method":"matchAll","tier":"core","task":"Iterate all regex matches including capture groups","call":"[...s.matchAll(/(\\d)(\\w)/g)]","mutates":false,"returns":"iterator of match arrays","example":"return [...'1a2b'.matchAll(/(\\d)(\\w)/g)].map((m)=>m[1]+m[2]);","expected":"[\"1a\",\"2b\"]","gotcha":"The regex must have the g flag or it throws."}, - {"method":"trimStart","tier":"rare","task":"Strip whitespace from the START only","call":"s.trimStart()","mutates":false,"returns":"new string","example":"return ' a '.trimStart();","expected":"\"a \""}, - {"method":"trimEnd","tier":"rare","task":"Strip whitespace from the END only","call":"s.trimEnd()","mutates":false,"returns":"new string","example":"return ' a '.trimEnd();","expected":"\" a\""}, - {"method":"lastIndexOf","tier":"rare","task":"Find the LAST index of a substring","call":"s.lastIndexOf(sub)","mutates":false,"returns":"last index, or -1","example":"return 'hello'.lastIndexOf('l');","expected":"3"}, - {"method":"substr","tier":"rare","task":"Substring by start index and LENGTH (deprecated)","call":"s.substr(start, length)","mutates":false,"returns":"new string","signature":"s.substr(start, length) // deprecated; use slice","example":"return 'abcdef'.substr(1,3);","expected":"\"bcd\"","gotcha":"Second arg is a length, not an end index. Deprecated."}, - {"method":"concat","tier":"rare","task":"Concatenate strings with a method call","call":"s.concat(a, b)","mutates":false,"returns":"new string","example":"return 'a'.concat('b','c');","expected":"\"abc\"","gotcha":"Just use + or a template literal."}, - {"method":"search","tier":"rare","task":"Find the index of a regex match","call":"s.search(/c/)","mutates":false,"returns":"index, or -1","example":"return 'abc'.search(/c/);","expected":"2"}, - {"method":"localeCompare","tier":"rare","task":"Compare two strings for sorting","call":"a.localeCompare(b)","mutates":false,"returns":"negative / 0 / positive number","example":"return ['b','a','c'].sort((x,y)=>x.localeCompare(y));","expected":"[\"a\",\"b\",\"c\"]","gotcha":"Locale-aware and slower; for plain code-unit order use a < b ? -1 : 1."}, - {"method":"codePointAt","tier":"rare","task":"Get the full Unicode code point at index i","call":"s.codePointAt(i)","mutates":false,"returns":"number","example":"return '😀'.codePointAt(0);","expected":"128512","gotcha":"charCodeAt would return only half of the surrogate pair."}, - {"method":"normalize","tier":"rare","task":"Normalize Unicode (e.g. strip accents with NFD)","call":"s.normalize('NFD')","mutates":false,"returns":"new string","example":"return 'é'.normalize('NFD').length;","expected":"2"} + { + "method": "charAt / s[i]", + "tier": "core", + "task": "Get the character at index i", + "call": "s[i] // or s.charAt(i)", + "mutates": false, + "returns": "1-char string; s[i] gives undefined out of range, charAt gives ''", + "example": "return ['abc'[1],'abc'.charAt(5),'abc'[5]];", + "expected": "[\"b\",\"\",null]", + "gotcha": "Strings are immutable: s[0] = 'x' silently does nothing." + }, + { + "method": "charCodeAt", + "tier": "core", + "task": "Get the char code of the character at index i", + "call": "s.charCodeAt(i)", + "mutates": false, + "returns": "number (UTF-16 code unit)", + "example": "return ['a'.charCodeAt(0),'c'.charCodeAt(0)-'a'.charCodeAt(0)];", + "expected": "[97,2]", + "gotcha": "Alphabet index idiom: s.charCodeAt(i) - 97." + }, + { + "method": "String.fromCharCode", + "tier": "core", + "task": "Turn a char code into a character", + "call": "String.fromCharCode(code)", + "mutates": false, + "returns": "string", + "example": "return String.fromCharCode(97+2);", + "expected": "\"c\"", + "gotcha": "Static method on String, not on a string value." + }, + { + "method": "split", + "tier": "core", + "task": "Split a string into an array by a separator", + "call": "s.split(sep)", + "mutates": false, + "returns": "array of strings", + "signature": "s.split(separator, limit) // split('') = chars", + "example": "return ['a,b'.split(','),'abc'.split('')];", + "expected": "[[\"a\",\"b\"],[\"a\",\"b\",\"c\"]]" + }, + { + "method": "[...s]", + "tier": "core", + "task": "Turn a string into an array of characters", + "call": "[...s] // or Array.from(s)", + "mutates": false, + "returns": "new array of characters", + "example": "return [...'abc'];", + "expected": "[\"a\",\"b\",\"c\"]", + "gotcha": "Unlike split(''), spread keeps emoji/surrogate pairs whole." + }, + { + "method": "reverse a string", + "tier": "core", + "task": "Reverse a string", + "call": "[...s].reverse().join('')", + "mutates": false, + "returns": "new string", + "example": "return [...'abc'].reverse().join('');", + "expected": "\"cba\"", + "gotcha": "Strings have no reverse(); go via an array." + }, + { + "method": "slice", + "tier": "core", + "task": "Get s[i..j) as a substring", + "call": "s.slice(i, j)", + "mutates": false, + "returns": "new string; end exclusive", + "signature": "s.slice(start, end) // end exclusive, negatives count from the end", + "example": "return ['abcdef'.slice(1,3),'abcdef'.slice(-2)];", + "expected": "[\"bc\",\"ef\"]" + }, + { + "method": "substring", + "tier": "core", + "task": "Substring by two indices (and how it differs from slice)", + "call": "s.substring(i, j)", + "mutates": false, + "returns": "new string; end exclusive", + "signature": "s.substring(start, end) // swaps args if start > end, negatives → 0", + "example": "return ['abcdef'.substring(3,1),'abcdef'.slice(3,1),'abcdef'.substring(-2)];", + "expected": "[\"bc\",\"\",\"abcdef\"]", + "gotcha": "Prefer slice(): substring swaps arguments and treats negatives as 0." + }, + { + "method": "indexOf", + "tier": "core", + "task": "Find the index of a substring (-1 if absent)", + "call": "s.indexOf(sub)", + "mutates": false, + "returns": "first index, or -1", + "signature": "s.indexOf(searchString, fromIndex)", + "example": "return ['hello'.indexOf('l'),'hello'.indexOf('z')];", + "expected": "[2,-1]" + }, + { + "method": "includes", + "tier": "core", + "task": "Check whether a string contains a substring", + "call": "s.includes(sub)", + "mutates": false, + "returns": "boolean", + "example": "return 'hello'.includes('ell');", + "expected": "true", + "gotcha": "Case-sensitive; a RegExp argument throws." + }, + { + "method": "startsWith", + "tier": "core", + "task": "Check whether a string starts with a prefix", + "call": "s.startsWith(prefix)", + "mutates": false, + "returns": "boolean", + "example": "return 'hello'.startsWith('he');", + "expected": "true" + }, + { + "method": "endsWith", + "tier": "core", + "task": "Check whether a string ends with a suffix", + "call": "s.endsWith(suffix)", + "mutates": false, + "returns": "boolean", + "example": "return 'hello'.endsWith('lo');", + "expected": "true" + }, + { + "method": "toLowerCase", + "tier": "core", + "task": "Lowercase a string", + "call": "s.toLowerCase()", + "mutates": false, + "returns": "new string", + "example": "return 'aBc'.toLowerCase();", + "expected": "\"abc\"" + }, + { + "method": "toUpperCase", + "tier": "core", + "task": "Uppercase a string", + "call": "s.toUpperCase()", + "mutates": false, + "returns": "new string", + "example": "return 'aBc'.toUpperCase();", + "expected": "\"ABC\"" + }, + { + "method": "trim", + "tier": "core", + "task": "Strip whitespace from both ends", + "call": "s.trim()", + "mutates": false, + "returns": "new string", + "example": "return ' a b '.trim();", + "expected": "\"a b\"" + }, + { + "method": "repeat", + "tier": "core", + "task": "Repeat a string n times", + "call": "s.repeat(n)", + "mutates": false, + "returns": "new string", + "example": "return 'ab'.repeat(3);", + "expected": "\"ababab\"", + "gotcha": "Negative n throws RangeError." + }, + { + "method": "padStart", + "tier": "core", + "task": "Left-pad a string to a length (e.g. zero-pad)", + "call": "s.padStart(len, '0')", + "mutates": false, + "returns": "new string", + "signature": "s.padStart(targetLength, padString)", + "example": "return '5'.padStart(3,'0');", + "expected": "\"005\"" + }, + { + "method": "padEnd", + "tier": "core", + "task": "Right-pad a string to a length", + "call": "s.padEnd(len, ' ')", + "mutates": false, + "returns": "new string", + "signature": "s.padEnd(targetLength, padString)", + "example": "return 'ab'.padEnd(5,'.');", + "expected": "\"ab...\"" + }, + { + "method": "replace", + "tier": "core", + "task": "Replace occurrences of a pattern (first only vs all)", + "call": "s.replace(pattern, replacement)", + "mutates": false, + "returns": "new string", + "signature": "s.replace(patternOrString, replacementOrFn)", + "example": "return ['aaa'.replace('a','b'),'aaa'.replace(/a/g,'b')];", + "expected": "[\"baa\",\"bbb\"]", + "gotcha": "A string pattern replaces only the FIRST match. Use /x/g or replaceAll." + }, + { + "method": "replaceAll", + "tier": "core", + "task": "Replace ALL occurrences of a substring", + "call": "s.replaceAll(sub, replacement)", + "mutates": false, + "returns": "new string", + "signature": "s.replaceAll(patternOrString, replacementOrFn)", + "example": "return 'aaa'.replaceAll('a','b');", + "expected": "\"bbb\"", + "gotcha": "A RegExp argument must have the g flag or it throws." + }, + { + "method": "at", + "tier": "core", + "task": "Get the LAST character (or nth from the end)", + "call": "s.at(-1)", + "mutates": false, + "returns": "1-char string, or undefined", + "example": "return ['abc'.at(-1),'abc'.at(0)];", + "expected": "[\"c\",\"a\"]" + }, + { + "method": "match", + "tier": "core", + "task": "Find all regex matches in a string", + "call": "s.match(/\\d+/g)", + "mutates": false, + "returns": "array of matches, or null if none", + "example": "return ['a1b22'.match(/\\d+/g),'abc'.match(/\\d+/g)];", + "expected": "[[\"1\",\"22\"],null]", + "gotcha": "Without the g flag you get a single match object, not all matches. null → use ?? []." + }, + { + "method": "matchAll", + "tier": "core", + "task": "Iterate all regex matches including capture groups", + "call": "[...s.matchAll(/(\\d)(\\w)/g)]", + "mutates": false, + "returns": "iterator of match arrays", + "example": "return [...'1a2b'.matchAll(/(\\d)(\\w)/g)].map((m)=>m[1]+m[2]);", + "expected": "[\"1a\",\"2b\"]", + "gotcha": "The regex must have the g flag or it throws." + }, + { + "method": "trimStart", + "tier": "rare", + "task": "Strip whitespace from the START only", + "call": "s.trimStart()", + "mutates": false, + "returns": "new string", + "example": "return ' a '.trimStart();", + "expected": "\"a \"" + }, + { + "method": "trimEnd", + "tier": "rare", + "task": "Strip whitespace from the END only", + "call": "s.trimEnd()", + "mutates": false, + "returns": "new string", + "example": "return ' a '.trimEnd();", + "expected": "\" a\"" + }, + { + "method": "lastIndexOf", + "tier": "rare", + "task": "Find the LAST index of a substring", + "call": "s.lastIndexOf(sub)", + "mutates": false, + "returns": "last index, or -1", + "example": "return 'hello'.lastIndexOf('l');", + "expected": "3" + }, + { + "method": "substr", + "tier": "rare", + "task": "Substring by start index and LENGTH (deprecated)", + "call": "s.substr(start, length)", + "mutates": false, + "returns": "new string", + "signature": "s.substr(start, length) // deprecated; use slice", + "example": "return 'abcdef'.substr(1,3);", + "expected": "\"bcd\"", + "gotcha": "Second arg is a length, not an end index. Deprecated." + }, + { + "method": "concat", + "tier": "rare", + "task": "Concatenate strings with a method call", + "call": "s.concat(a, b)", + "mutates": false, + "returns": "new string", + "example": "return 'a'.concat('b','c');", + "expected": "\"abc\"", + "gotcha": "Just use + or a template literal." + }, + { + "method": "search", + "tier": "rare", + "task": "Find the index of a regex match", + "call": "s.search(/c/)", + "mutates": false, + "returns": "index, or -1", + "example": "return 'abc'.search(/c/);", + "expected": "2" + }, + { + "method": "localeCompare", + "tier": "rare", + "task": "Compare two strings for sorting", + "call": "a.localeCompare(b)", + "mutates": false, + "returns": "negative / 0 / positive number", + "example": "return ['b','a','c'].sort((x,y)=>x.localeCompare(y));", + "expected": "[\"a\",\"b\",\"c\"]", + "gotcha": "Locale-aware and slower; for plain code-unit order use a < b ? -1 : 1." + }, + { + "method": "codePointAt", + "tier": "rare", + "task": "Get the full Unicode code point at index i", + "call": "s.codePointAt(i)", + "mutates": false, + "returns": "number", + "example": "return '😀'.codePointAt(0);", + "expected": "128512", + "gotcha": "charCodeAt would return only half of the surrogate pair." + }, + { + "method": "normalize", + "tier": "rare", + "task": "Normalize Unicode (e.g. strip accents with NFD)", + "call": "s.normalize('NFD')", + "mutates": false, + "returns": "new string", + "example": "return 'é'.normalize('NFD').length;", + "expected": "2" + } ]