From f501f69630422df9a3ca6d6f2a11f34a96025b92 Mon Sep 17 00:00:00 2001 From: Bakhtier Gaibulloev Date: Thu, 20 Nov 2025 09:09:47 +0100 Subject: [PATCH 1/9] fix: fixes quick start --- docs/reference/quick-start.md | 81 +- example-fibonacci.som | 39 + example-greeting.som | 3 + example-instagram.som | 19 + examples/example-fibonacci.som | 33 + examples/example-greeting.som | 28 + examples/example-instagram.som | 52 + examples/quick-start-comprehensive.som | 207 +++ examples/quick-start-console.som | 43 + examples/quick-start-math.som | 39 + examples/quick-start-strings.som | 49 + examples/tree-example.som | 35 + package-lock.json | 1970 +++++++++++++++++++++++- package.json | 21 +- repro_arrow.ts | 10 + src/ast.ts | 1 + src/codegen.ts | 40 +- src/parser.ts | 15 +- tests/quick-start.test.ts | 274 ++++ 19 files changed, 2873 insertions(+), 86 deletions(-) create mode 100644 example-fibonacci.som create mode 100644 example-greeting.som create mode 100644 example-instagram.som create mode 100644 examples/example-fibonacci.som create mode 100644 examples/example-greeting.som create mode 100644 examples/example-instagram.som create mode 100644 examples/quick-start-comprehensive.som create mode 100644 examples/quick-start-console.som create mode 100644 examples/quick-start-math.som create mode 100644 examples/quick-start-strings.som create mode 100644 examples/tree-example.som create mode 100644 repro_arrow.ts create mode 100644 tests/quick-start.test.ts diff --git a/docs/reference/quick-start.md b/docs/reference/quick-start.md index 4df3e09..ad5fe0d 100644 --- a/docs/reference/quick-start.md +++ b/docs/reference/quick-start.md @@ -151,14 +151,17 @@ A comprehensive cheat sheet for SomonScript syntax and common patterns. тағйирёбанда рақамҳо = [1, 2, 3, 4, 5]; тағйирёбанда холӣ: сатр[] = []; -// Array methods -мева.push("шафтолу"); // Add to end -мева.pop(); // Remove from end -мева.unshift("анголур"); // Add to beginning -мева.shift(); // Remove from beginning -мева.length; // Array length -мева.indexOf("себ"); // Find index -мева.includes("мӯз"); // Check if exists +// Array methods with Tajik names +мева.илова("шафтолу"); // push - Илова ба охир +мева.пуш("ангур"); // push (alternative) +мева.баровардан(); // pop - Баровардан аз охир +мева.дарозӣ; // length - Дарозии массив + +// Array iteration methods +мева.харита(м => м.калон()); // map - Табдил додан +мева.филтр(м => м !== "себ"); // filter - Филтр кардан +мева.кофтан(м => м === "мӯз"); // find - Ёфтан +мева.буридан(0, 2); // slice - Буридан // Array iteration мева.forEach((элемент, индекс) => { @@ -530,32 +533,68 @@ Object.entries(корбар); // Get key-value pairs ### Console ```som +// Basic console methods чоп.сабт("Паём"); // console.log чоп.хато("Хато"); // console.error чоп.огоҳӣ("Огоҳӣ"); // console.warn чоп.маълумот("Маълумот"); // console.info +чоп.исфти("Debug"); // console.debug + +// Console table and grouping +чоп.ҷадвал(маълумот); // console.table +чоп.гуруҳ("Гуруҳ"); // console.group +чоп.гуруҳ_охир(); // console.groupEnd +чоп.гуруҳ_пӯшида("Пӯшида"); // console.groupCollapsed + +// Console timing +чоп.вақт("timer"); // console.time +чоп.вақт_сабт("timer"); // console.timeLog +чоп.вақт_охир("timer"); // console.timeEnd + +// Console counting and misc +чоп.қайд("counter"); // console.count +чоп.қайд_асл("counter"); // console.countReset +чоп.тасдиқ(шарт, "паём"); // console.assert +чоп.полиз(); // console.clear +чоп.феҳрист(объект); // console.dir +чоп.пайҷо(); // console.trace ``` -### Math +### Math (Риёзӣ) ```som -Риёзӣ.дуръшака(9); // Math.sqrt(9) = 3 -Риёзӣ.қувват(2, 3); // Math.pow(2, 3) = 8 -Риёзӣ.тасодуфӣ(); // Math.random() -Риёзӣ.дузкунӣ(4.7); // Math.round(4.7) = 5 -Риёзӣ.боло(4.2); // Math.ceil(4.2) = 5 -Риёзӣ.поён(4.7); // Math.floor(4.7) = 4 +// Math methods - Методҳои математикӣ +Риёзӣ.дуръшака(9); // Math.sqrt(9) = 3 - Решаи квадратӣ +Риёзӣ.қувват(2, 3); // Math.pow(2, 3) = 8 - Қувват/дараҷа +Риёзӣ.тасодуфӣ(); // Math.random() - Рақами тасодуфӣ (0-1) +Риёзӣ.дузкунӣ(4.7); // Math.round(4.7) = 5 - Гирдкунӣ +Риёзӣ.боло(4.2); // Math.ceil(4.2) = 5 - Гирдкунӣ ба боло +Риёзӣ.поён(4.7); // Math.floor(4.7) = 4 - Гирдкунӣ ба поён + +// Complex calculations example +тағйирёбанда радиус = 5; +тағйирёбанда майдон = 3.14159 * Риёзӣ.қувват(радиус, 2); +тағйирёбанда аз_1_то_10 = Риёзӣ.поён(Риёзӣ.тасодуфӣ() * 10) + 1; ``` ### String Methods ```som -сатр.дарозӣ; // string.length -сатр.калон(); // string.toUpperCase() -сатр.хурд(); // string.toLowerCase() -сатр.қисмат(0, 5); // string.substring(0, 5) -сатр.ҷойгузин("a", "b"); // string.replace("a", "b") -сатр.ҷудокунӣ(","); // string.split(",") +// String properties and methods +сатр.дарозӣ; // string.length - Дарозии сатр +сатр.калон(); // string.toUpperCase() - Ба ҳарфҳои калон +сатр.хурд(); // string.toLowerCase() - Ба ҳарфҳои хурд +сатр.қисмат(0, 5); // string.substring(0, 5) - Зерсатр +сатр.ҷойгузин("a", "b"); // string.replace("a", "b") - Иваз кардан +сатр.ҷудокунӣ(","); // string.split(",") - Ҷудо кардан +сатр.пайвастан(" Ҷаҳон"); // string.concat(" World") - Пайваст кардан + +// Example usage +тағйирёбанда матн = "Салом, Ҷаҳон!"; +чоп.сабт(матн.дарозӣ); // 13 +чоп.сабт(матн.калон()); // САЛОМ, ҶАҲОН! +чоп.сабт(матн.хурд()); // салом, ҷаҳон! +чоп.сабт(матн.қисмат(0, 5)); // Салом ``` ## Best Practices diff --git a/example-fibonacci.som b/example-fibonacci.som new file mode 100644 index 0000000..48ccb53 --- /dev/null +++ b/example-fibonacci.som @@ -0,0 +1,39 @@ +// 🔢 Ҳисобкунандаи силсилаи Фибоначчӣ + +функсия фибоначчӣ(н) { + агар (н <= 1) { + баргардон н; + } + баргардон фибоначчӣ(н - 1) + фибоначчӣ(н - 2); +} + +// Чопи силсилаи Фибоначчӣ +чоп.сабт("🇹🇯 Силсилаи Фибоначчӣ:"); +чоп.сабт("─────────────────────"); + +барои (тағйирёбанда и = 0; и <= 10; и++) { + тағйирёбанда натиҷа = фибоначчӣ(и); + чоп.сабт("F(" + и + ") = " + натиҷа); +} + +чоп.сабт(""); +чоп.сабт("✨ Ҳисоб анҷом ёфт!"); + +// Версияи оптимизатсияшуда бо кэш +функсия фибоначчӣБоКэш(н, кэш = {}) { + агар (н дар кэш) { + баргардон кэш[н]; + } + + агар (н <= 1) { + баргардон н; + } + + кэш[н] = фибоначчӣБоКэш(н - 1, кэш) + фибоначчӣБоКэш(н - 2, кэш); + баргардон кэш[н]; +} + +чоп.сабт(""); +чоп.сабт("⚡ Версияи тез (бо кэш):"); +тағйирёбанда натиҷаи_калон = фибоначчӣБоКэш(30); +чоп.сабт("F(30) = " + натиҷаи_калон); diff --git a/example-greeting.som b/example-greeting.som new file mode 100644 index 0000000..6b87587 --- /dev/null +++ b/example-greeting.som @@ -0,0 +1,3 @@ +агар (рост) { + чоп.сабт("Точикистон ба пеш!!!"); +} diff --git a/example-instagram.som b/example-instagram.som new file mode 100644 index 0000000..018f3f8 --- /dev/null +++ b/example-instagram.som @@ -0,0 +1,19 @@ +// 🇹🇯 Барномасозӣ бо забони тоҷикӣ! + +тағйирёбанда ном = "Дунё"; +тағйирёбанда паём = "Салом, " + ном + "!"; + +чоп.сабт(паём); + +функсия ҳисоб(а, б) { + баргардон а + б; +} + +тағйирёбанда натиҷа = ҳисоб(10, 32); +чоп.сабт("Натиҷа: " + натиҷа); + +агар (натиҷа > 40) { + чоп.сабт("✨ Точикистон ба пеш! ✨"); +} вагарна { + чоп.сабт("Кори нағз!"); +} diff --git a/examples/example-fibonacci.som b/examples/example-fibonacci.som new file mode 100644 index 0000000..fb5e2a9 --- /dev/null +++ b/examples/example-fibonacci.som @@ -0,0 +1,33 @@ +// 🎯 Силсилаи Фибоначчи - Намунаи зебо барои Stories +// Нишон додани қувваи SomonScript + +функсия фибоначчи(н: рақам): рақам { + агар (н <= 1) { + бозгашт н; + } + бозгашт фибоначчи(н - 1) + фибоначчи(н - 2); +} + +функсия силсила_нишон_деҳ(то: рақам): холӣ { + тағйирёбанда натиҷа: сатр = "🔢 "; + тағйирёбанда и: рақам = 0; + + барои (и = 0; и < то; и++) { + тағйирёбанда рақам: рақам = фибоначчи(и); + натиҷа = натиҷа + рақам + " "; + } + + чоп.сабт(натиҷа); +} + +// Намоиш +чоп.сабт("╔═══════════════════════╗"); +чоп.сабт("║ 🌟 СИЛСИЛАИ ФИБОНАЧЧИ ║"); +чоп.сабт("╚═══════════════════════╝"); +чоп.сабт(""); + +силсила_нишон_деҳ(10); + +чоп.сабт(""); +чоп.сабт("💡 Математика + Забони тоҷикӣ = ❤️"); +чоп.сабт("✨ SomonScript"); diff --git a/examples/example-greeting.som b/examples/example-greeting.som new file mode 100644 index 0000000..cac242f --- /dev/null +++ b/examples/example-greeting.som @@ -0,0 +1,28 @@ +// 👋 Салом дар Instagram Stories! +// Кодинг ба забони модарӣ + +функсия салом_дар_инстаграм(ном: сатр): холӣ { + чоп.сабт("╔══════════════════╗"); + чоп.сабт("║ 👋 САЛОМ! ║"); + чоп.сабт("║ ║"); + чоп.сабт("║ " + ном + "! ║"); + чоп.сабт("║ ║"); + чоп.сабт("║ 💻 SomonScript ║"); + чоп.сабт("╚══════════════════╝"); +} + +функсия лайкҳо_ҳисоб_кун(лайкҳо: рақам): холӣ { + агар (лайкҳо > 1000) { + чоп.сабт("🔥 ВАЙ! " + лайкҳо + " лайк!"); + } вагарна агар (лайкҳо > 100) { + чоп.сабт("👍 Хуб! " + лайкҳо + " лайк"); + } вагарна { + чоп.сабт("❤️ " + лайкҳо + " лайк"); + } +} + +// Истифода +салом_дар_инстаграм("Тоҷикистон"); +лайкҳо_ҳисоб_кун(1500); + +чоп.сабт("\n✨ Биёед код нависем ба забони тоҷикӣ!"); diff --git a/examples/example-instagram.som b/examples/example-instagram.som new file mode 100644 index 0000000..3324904 --- /dev/null +++ b/examples/example-instagram.som @@ -0,0 +1,52 @@ +// 🎬 Instagram Stories Demo - SomonScript +// Программирование ба забони тоҷикӣ! + +// 💝 Вариант 1: Генератори дилҳо +функсия дилҳо_бисоз(шумора: рақам): холӣ { + тағйирёбанда и: рақам = 0; + барои (и = 0; и < шумора; и++) { + чоп.сабт("❤️ Ман шуморо дӯст медорам!"); + } +} + +// 🌟 Вариант 2: Рейтинги ситораҳо +функсия рейтинг_нишон_деҳ(ситораҳо: рақам): холӣ { + тағйирёбанда натиҷа: сатр = ""; + тағйирёбанда и: рақам = 0; + + барои (и = 0; и < ситораҳо; и++) { + натиҷа = натиҷа + "⭐"; + } + + чоп.сабт(натиҷа); + чоп.сабт("Рейтинги шумо: " + ситораҳо + "/5"); +} + +// 🎯 Вариант 3: Шумораи тамошобинҳо +функсия тамошобинҳо_нишон_деҳ(шумора: рақам): холӣ { + агар (шумора < 1000) { + чоп.сабт("👁️ " + шумора + " тамошобин"); + } вагарна агар (шумора < 10000) { + тағйирёбанда ҳазор: рақам = шумора / 1000; + чоп.сабт("👁️ " + ҳазор + "K тамошобинҳо"); + } вагарна { + чоп.сабт("🔥 Вирал! " + шумора + " тамошобин!"); + } +} + +// 📱 Истифодаи намунаҳо +чоп.сабт("━━━━━━━━━━━━━━━━━━━"); +чоп.сабт("💝 ДИЛҲО:"); +дилҳо_бисоз(5); + +чоп.сабт("\n━━━━━━━━━━━━━━━━━━━"); +чоп.сабт("🌟 РЕЙТИНГ:"); +рейтинг_нишон_деҳ(5); + +чоп.сабт("\n━━━━━━━━━━━━━━━━━━━"); +чоп.сабт("📊 ТАМОШОБИНҲО:"); +тамошобинҳо_нишон_деҳ(850); +тамошобинҳо_нишон_деҳ(5500); +тамошобинҳо_нишон_деҳ(25000); + +чоп.сабт("\n✨ SomonScript - Код ба забони тоҷикӣ!"); diff --git a/examples/quick-start-comprehensive.som b/examples/quick-start-comprehensive.som new file mode 100644 index 0000000..63d9122 --- /dev/null +++ b/examples/quick-start-comprehensive.som @@ -0,0 +1,207 @@ +// Comprehensive test of quick-start features +// Тести ҳамаҷониба барои хусусиятҳои quick-start + +чоп.сабт("=== SomonScript Quick Start - Тести Ҳамаҷониба ===\n"); + +// ========================================== +// 1. Variables and Constants +// ========================================== +чоп.сабт("1. ТАҒЙИРЁБАНДАҲО ВА СОБИТҲО:"); +тағйирёбанда ном = "Аҳмад"; +тағйирёбанда синну_сол = 25; +тағйирёбанда фаъол = дуруст; +собит ПИ = 3.14159; +собит МАКС_СИННУ_СОЛ = 120; + +чоп.сабт("Ном: " + ном); +чоп.сабт("Синну сол: " + синну_сол); +чоп.сабт("Фаъол: " + фаъол); +чоп.сабт("ПИ: " + ПИ); + +// ========================================== +// 2. Functions +// ========================================== +чоп.сабт("\n2. ФУНКСИЯҲО:"); + +функсия салом(ном: сатр): сатр { + бозгашт "Салом, " + ном + "!"; +} + +функсия ҷамъ(а: рақам, б: рақам): рақам { + бозгашт а + б; +} + +// Arrow function (without types for now) +тағйирёбанда зарб = (а, б) => а * б; + +чоп.сабт(салом("Раҳмон")); +чоп.сабт("5 + 3 = " + ҷамъ(5, 3)); +чоп.сабт("4 * 7 = " + зарб(4, 7)); + +// ========================================== +// 3. Math (Риёзӣ) Operations +// ========================================== +чоп.сабт("\n3. АМАЛИЁТҲОИ РИЁЗӢ:"); + +чоп.сабт("Решаи квадратӣ 16: " + Риёзӣ.дуръшака(16)); +чоп.сабт("2 дар қувват 8: " + Риёзӣ.қувват(2, 8)); +чоп.сабт("Гирдкунӣ 4.6: " + Риёзӣ.дузкунӣ(4.6)); +чоп.сабт("Сақфи 4.2: " + Риёзӣ.боло(4.2)); +чоп.сабт("Фарши 4.7: " + Риёзӣ.поён(4.7)); + +// Random number between 1 and 10 +тағйирёбанда тасодуфӣ = Риёзӣ.поён(Риёзӣ.тасодуфӣ() * 10) + 1; +чоп.сабт("Рақами тасодуфӣ (1-10): " + тасодуфӣ); + +// ========================================== +// 4. String Operations +// ========================================== +чоп.сабт("\n4. АМАЛИЁТҲОИ САТР:"); + +тағйирёбанда матн = "Забони SomonScript"; +чоп.сабт("Матн: " + матн); +чоп.сабт("Дарозӣ: " + матн.дарозӣ); +чоп.сабт("Калон: " + матн.калон()); +чоп.сабт("Хурд: " + матн.хурд()); +чоп.сабт("Қисмат(0, 6): " + матн.қисмат(0, 6)); + +тағйирёбанда калимаҳо = матн.ҷудокунӣ(" "); +чоп.сабт("Калимаҳо:"); +барои (тағйирёбанда i = 0; i < калимаҳо.length; i++) { + чоп.сабт(" - " + калимаҳо[i]); +} + +// ========================================== +// 5. Arrays +// ========================================== +чоп.сабт("\n5. МАССИВҲО:"); + +тағйирёбанда мева = ["себ", "банан", "анор"]; +чоп.сабт("Мева: " + мева); + +мева.push("шафтолу"); +чоп.сабт("Баъд аз push: " + мева); +чоп.сабт("Дарозии массив: " + мева.length); + +// Array iteration +барои (тағйирёбанда i = 0; i < мева.length; i++) { + чоп.сабт(" [" + i + "] = " + мева[i]); +} + +// ========================================== +// 6. Objects +// ========================================== +чоп.сабт("\n6. ОБЪЕКТҲО:"); + +тағйирёбанда корбар = { + ном: "Фирдавс", + синну_сол: 28, + шаҳр: "Душанбе", + касб: "Барномасоз" +}; + +чоп.сабт("Корбар:"); +чоп.сабт(" Ном: " + корбар.ном); +чоп.сабт(" Синну сол: " + корбар.синну_сол); +чоп.сабт(" Шаҳр: " + корбар.шаҳр); +чоп.сабт(" Касб: " + корбар.касб); + +// ========================================== +// 7. Control Flow +// ========================================== +чоп.сабт("\n7. НАЗОРАТИ ҶАРАЁН:"); + +// If-else +тағйирёбанда қимат = 15; +агар (қимат > 20) { + чоп.сабт("Қимат калонтар аз 20"); +} вагарна агар (қимат > 10) { + чоп.сабт("Қимат байни 10 ва 20"); +} вагарна { + чоп.сабт("Қимат 10 ё камтар"); +} + +// For loop +чоп.сабт("\nҲисоб аз 1 то 5:"); +барои (тағйирёбанда i = 1; i <= 5; i++) { + чоп.сабт(" " + i); +} + +// While loop +чоп.сабт("\nТо loop (countdown):"); +тағйирёбанда каунтдаун = 3; +то (каунтдаун > 0) { + чоп.сабт(" " + каунтдаун + "..."); + каунтдаун--; +} +чоп.сабт(" Старт!"); + +// ========================================== +// 8. Classes +// ========================================== +чоп.сабт("\n8. СИНФҲО:"); + +синф Мошин { + хосусӣ бренд: сатр; + хосусӣ модел: сатр; + хосусӣ сол: рақам; + + конструктор(бренд: сатр, модел: сатр, сол: рақам) { + ин.бренд = бренд; + ин.модел = модел; + ин.сол = сол; + } + + ҷамъиятӣ маълумот(): сатр { + бозгашт `${ин.бренд} ${ин.модел} (${ин.сол})`; + } +} + +тағйирёбанда мошини_ман = нав Мошин("Toyota", "Camry", 2020); +чоп.сабт("Мошин: " + мошини_ман.маълумот()); + +// ========================================== +// 9. Template Literals +// ========================================== +чоп.сабт("\n9. TEMPLATE LITERALS:"); + +тағйирёбанда шаҳр = "Хуҷанд"; +тағйирёбанда аҳолӣ = 181600; +тағйирёбанда паём = `Шаҳри ${шаҳр} ${аҳолӣ} аҳолӣ дорад`; +чоп.сабт(паём); + +// ========================================== +// 10. Error Handling +// ========================================== +чоп.сабт("\n10. КОРКАРДИ ХАТОҲО:"); + +кӯшиш { + тағйирёбанда натиҷа = 10 / 2; + чоп.сабт("Тақсим муваффақ: " + натиҷа); + + // Simulate error + агар (натиҷа === 5) { + партофтан нав Хато("Хатои тестӣ"); + } +} гирифтан (хато) { + чоп.хато("Хато гирифта шуд: " + хато); +} ниҳоят { + чоп.маълумот("Блоки ниҳоят иҷро шуд"); +} + +// ========================================== +// 11. Console Methods +// ========================================== +чоп.сабт("\n11. МЕТОДҲОИ ЧОП:"); + +чоп.сабт("Паёми оддӣ"); +чоп.маълумот("Паёми маълумот"); +чоп.огоҳӣ("Паёми огоҳидиҳанда"); +чоп.хато("Паёми хато"); + +// ========================================== +// Summary +// ========================================== +чоп.сабт("\n" + "=".repeat(50)); +чоп.сабт("✅ ҲАМАИ ТЕСТҲО БА МУВАФФАҚИЯТ АНҶОМ ЁФТАНД!"); +чоп.сабт("=".repeat(50)); diff --git a/examples/quick-start-console.som b/examples/quick-start-console.som new file mode 100644 index 0000000..962094c --- /dev/null +++ b/examples/quick-start-console.som @@ -0,0 +1,43 @@ +// Тест барои методҳои чоп (console) +чоп.сабт("=== Тести методҳои чоп (Console) ==="); + +// Different console methods +чоп.сабт("Ин паёми оддӣ аст"); // console.log +чоп.хато("Ин паёми хато аст"); // console.error +чоп.огоҳӣ("Ин паёми огоҳӣ аст"); // console.warn +чоп.маълумот("Ин паёми маълумот аст"); // console.info + +// Console with multiple arguments +чоп.сабт("Якчанд аргументҳо:", 1, 2, 3, "чор"); + +// Console with objects +тағйирёбанда корбар = { + ном: "Раҳмон", + синну_сол: 30, + шаҳр: "Душанбе" +}; +чоп.сабт("Объекти корбар:", корбар); + +// Console with arrays +тағйирёбанда рақамҳо = [10, 20, 30, 40, 50]; +чоп.сабт("Массиви рақамҳо:", рақамҳо); + +// Complex logging +чоп.сабт("\n--- Логҳои мураккаб ---"); +барои (тағйирёбанда i = 1; i <= 3; i++) { + чоп.сабт(`Қадам ${i}: Коркарди маълумот...`); + агар (i === 2) { + чоп.огоҳӣ("Огоҳӣ: Маълумоти нопурра"); + } +} + +// Error handling with console +кӯшиш { + // Simulate an operation that might fail + тағйирёбанда натиҷа = 10 / 2; + чоп.сабт("Натиҷаи муваффақ:", натиҷа); +} гирифтан (хато) { + чоп.хато("Хато рух дод:", хато); +} + +чоп.маълумот("Барнома ба охир расид"); diff --git a/examples/quick-start-math.som b/examples/quick-start-math.som new file mode 100644 index 0000000..57f31fe --- /dev/null +++ b/examples/quick-start-math.som @@ -0,0 +1,39 @@ +// Тест барои Риёзӣ (Math) объект +чоп.сабт("=== Тести Риёзӣ (Math) ==="); + +// Math methods +чоп.сабт("\n--- Методҳои Риёзӣ ---"); +чоп.сабт("Решаи квадратӣ 9: " + Риёзӣ.дуръшака(9)); // 3 +чоп.сабт("2 дар қувват 3: " + Риёзӣ.қувват(2, 3)); // 8 +чоп.сабт("Рақами тасодуфӣ: " + Риёзӣ.тасодуфӣ()); // 0-1 +чоп.сабт("Гирдкунӣ 4.7: " + Риёзӣ.дузкунӣ(4.7)); // 5 +чоп.сабт("Гирдкунӣ боло 4.2: " + Риёзӣ.боло(4.2)); // 5 +чоп.сабт("Гирдкунӣ поён 4.7: " + Риёзӣ.поён(4.7)); // 4 + +// Multiple Math operations +тағйирёбанда натиҷа = Риёзӣ.қувват(Риёзӣ.дуръшака(16), 2); +чоп.сабт("sqrt(16)^2 = " + натиҷа); // 16 + +// Complex calculations +тағйирёбанда радиус = 5; +тағйирёбанда майдон = 3.14159 * Риёзӣ.қувват(радиус, 2); +чоп.сабт("Майдони давра бо радиус 5: " + майдон); + +// Rounding examples +чоп.сабт("\n--- Мисолҳои гирдкунӣ ---"); +тағйирёбанда рақамҳо = [1.1, 1.5, 1.9, -1.1, -1.5, -1.9]; +барои (тағйирёбанда i = 0; i < рақамҳо.length; i++) { + тағйирёбанда рақам = рақамҳо[i]; + чоп.сабт("Рақам: " + рақам); + чоп.сабт(" дузкунӣ: " + Риёзӣ.дузкунӣ(рақам)); + чоп.сабт(" боло: " + Риёзӣ.боло(рақам)); + чоп.сабт(" поён: " + Риёзӣ.поён(рақам)); +} + +// Random number generation +чоп.сабт("\n--- Рақамҳои тасодуфӣ ---"); +барои (тағйирёбанда i = 0; i < 5; i++) { + тағйирёбанда тасодуфӣ = Риёзӣ.тасодуфӣ(); + тағйирёбанда аз_1_то_10 = Риёзӣ.поён(тасодуфӣ * 10) + 1; + чоп.сабт("Тасодуфӣ аз 1 то 10: " + аз_1_то_10); +} diff --git a/examples/quick-start-strings.som b/examples/quick-start-strings.som new file mode 100644 index 0000000..924041c --- /dev/null +++ b/examples/quick-start-strings.som @@ -0,0 +1,49 @@ +// Тест барои методҳои сатр (String methods) +чоп.сабт("=== Тести методҳои сатр ==="); + +тағйирёбанда матн = "Салом, Ҷаҳон!"; +чоп.сабт("Матни аслӣ: " + матн); + +// String methods +чоп.сабт("\n--- Методҳои асосӣ ---"); +чоп.сабт("Дарозӣ: " + матн.дарозӣ); // length +чоп.сабт("Калон: " + матн.калон()); // САЛОМ, ҶАҲОН! +чоп.сабт("Хурд: " + матн.хурд()); // салом, ҷаҳон! +чоп.сабт("Қисмат(0, 5): " + матн.қисмат(0, 5)); // Салом +чоп.сабт("Ҷойгузин: " + матн.ҷойгузин("Ҷаҳон", "Дунё")); // Салом, Дунё! + +// String split +тағйирёбанда калимаҳо = "як,ду,се,чор,панҷ"; +тағйирёбанда массив = калимаҳо.ҷудокунӣ(","); +чоп.сабт("\n--- Ҷудокунӣ (split) ---"); +чоп.сабт("Сатри аслӣ: " + калимаҳо); +чоп.сабт("Баъд аз ҷудокунӣ: "); +барои (тағйирёбанда i = 0; i < массив.length; i++) { + чоп.сабт(" [" + i + "] = " + массив[i]); +} + +// More complex string operations +тағйирёбанда ном = " Аҳмад "; +чоп.сабт("\n--- Амалиётҳои мураккаб ---"); +чоп.сабт("Ном бо фазо: '" + ном + "'"); +чоп.сабт("Дарозии аслӣ: " + ном.дарозӣ); + +тағйирёбанда email = "user@example.com"; +тағйирёбанда қисмҳо = email.ҷудокунӣ("@"); +чоп.сабт("\n--- Таҳлили email ---"); +чоп.сабт("Email: " + email); +чоп.сабт("Номи корбар: " + қисмҳо[0]); +чоп.сабт("Домен: " + қисмҳо[1]); + +// String concatenation +тағйирёбанда салом = "Салом"; +тағйирёбанда ҷаҳон = "Ҷаҳон"; +тағйирёбанда паём = салом + ", " + ҷаҳон + "!"; +чоп.сабт("\n--- Пайвастан ---"); +чоп.сабт(паём); + +// Template literals +тағйирёбанда синну_сол = 25; +тағйирёбанда паёми_калон = `Ман ${синну_сол} сола ҳастам`; +чоп.сабт("\n--- Template literals ---"); +чоп.сабт(паёми_калон); diff --git a/examples/tree-example.som b/examples/tree-example.som new file mode 100644 index 0000000..d6f1fff --- /dev/null +++ b/examples/tree-example.som @@ -0,0 +1,35 @@ +функсия дарахт(баландӣ: рақам): сатр { + // Барги дарахт + барои (тағйирёбанда i = 0; i < баландӣ; i++) { + тағйирёбанда сатр = ""; + + // Фазохои чап + барои (тағйирёбанда j = 0; j < баландӣ - i - 1; j++) { + сатр = сатр + " "; + } + + // Ситорахо + барои (тағйирёбанда k = 0; k < 2 * i + 1; k++) { + сатр = сатр + "*"; + } + + чоп.сабт(сатр); + } + + // Танаи дарахт + тағйирёбанда пахнои_тана = Риёзӣ.поён(баландӣ / 3); + барои (тағйирёбанда i = 0; i < баландӣ / 2; i++) { + тағйирёбанда тана = ""; + барои (тағйирёбанда j = 0; j < баландӣ - пахнои_тана - 1; j++) { + тана = тана + " "; + } + барои (тағйирёбанда k = 0; k < пахнои_тана * 2 + 1; k++) { + тана = тана + "|"; + } + чоп.сабт(тана); + } + + бозгашт ""; +} + +дарахт(10); diff --git a/package-lock.json b/package-lock.json index 6214369..fddd4b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "babel-preset-minify": "^0.5.2", "chokidar": "^3.6.0", "commander": "^11.0.0", + "figma-developer-mcp": "^0.6.4", "source-map": "^0.7.6", "typescript": "^5.0.0" }, @@ -68,6 +69,7 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.4.tgz", "integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==", "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.3", @@ -912,6 +914,16 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.8.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.8.0.tgz", @@ -1019,6 +1031,12 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@figma/rest-api-spec": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@figma/rest-api-spec/-/rest-api-spec-0.33.0.tgz", + "integrity": "sha512-T/hxrxvnAejDHVzHr5av7eM09vCniyeyLy77QUMmnavUIZe+jA/Ex5mpFhMS6DHVAy/zuBUDJDZRMZ4t8OBwFg==", + "license": "MIT License" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", @@ -1057,6 +1075,471 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -1421,6 +1904,289 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.22.0", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.22.0.tgz", + "integrity": "sha512-VUpl106XVTCpDmTBil2ehgJZjhyLY2QZikzF8NvTXtLRF1CvO5iEE2UNZdVIUer35vFOwMKYeUGbjJtvPWan3g==", + "license": "MIT", + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@cfworker/json-schema": "^4.1.1" + }, + "peerDependenciesMeta": { + "@cfworker/json-schema": { + "optional": true + } + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@modelcontextprotocol/sdk/node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1645,6 +2411,7 @@ "integrity": "sha512-lSOjyS6vdO2G2g2CWrETTV3Jz2zlCXHpu1rcubLKpz9oj+z/1CceHlj+yq53W+9zgb98nSov/wjEKYDNauD+Hw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "undici-types": "~6.21.0" } @@ -1674,7 +2441,6 @@ "version": "17.0.33", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dev": true, "license": "MIT", "dependencies": { "@types/yargs-parser": "*" @@ -1684,7 +2450,6 @@ "version": "21.0.3", "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, "license": "MIT" }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -1742,6 +2507,7 @@ "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, "license": "BSD-2-Clause", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "6.21.0", "@typescript-eslint/types": "6.21.0", @@ -1957,12 +2723,26 @@ "dev": true, "license": "ISC" }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1997,7 +2777,6 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -2010,6 +2789,23 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", @@ -2030,7 +2826,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2047,7 +2842,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -2089,6 +2883,12 @@ "sprintf-js": "~1.0.2" } }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, "node_modules/array-ify": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", @@ -2490,6 +3290,60 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/body-parser/node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/brace-expansion": { "version": "1.1.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", @@ -2532,6 +3386,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", @@ -2575,6 +3430,44 @@ "dev": true, "license": "MIT" }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -2810,7 +3703,6 @@ "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -2843,7 +3735,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -2856,7 +3747,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/colorette": { @@ -2893,6 +3783,27 @@ "dev": true, "license": "MIT" }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/conventional-changelog-angular": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", @@ -2931,6 +3842,34 @@ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "license": "MIT" }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -3023,11 +3962,28 @@ "dev": true, "license": "MIT" }, + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" + }, + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -3131,7 +4087,35 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=0.10.0" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" } }, "node_modules/detect-newline": { @@ -3203,6 +4187,32 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "16.6.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz", + "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -3210,6 +4220,12 @@ "dev": true, "license": "MIT" }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, "node_modules/electron-to-chromium": { "version": "1.5.213", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.213.tgz", @@ -3233,9 +4249,17 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -3246,6 +4270,36 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -3255,6 +4309,12 @@ "node": ">=6" } }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, "node_modules/escape-string-regexp": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", @@ -3272,6 +4332,7 @@ "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -3548,6 +4609,15 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -3555,6 +4625,27 @@ "dev": true, "license": "MIT" }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.6.tgz", + "integrity": "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg==", + "license": "MIT", + "engines": { + "node": ">=18.0.0" + } + }, "node_modules/execa": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", @@ -3605,11 +4696,87 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "peer": true, + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, "license": "MIT" }, "node_modules/fast-glob": { @@ -3660,7 +4827,6 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, "funding": [ { "type": "github", @@ -3693,6 +4859,49 @@ "bser": "2.1.1" } }, + "node_modules/figma-developer-mcp": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/figma-developer-mcp/-/figma-developer-mcp-0.6.4.tgz", + "integrity": "sha512-3veoTrBHabx3bKwOLjftsWqBuAVeCCT8JdlK46ofYoT5lv/qKbiR+ycbySzrW53Dk41kVI3dVOIyC3b/ThRStQ==", + "license": "MIT", + "dependencies": { + "@figma/rest-api-spec": "^0.33.0", + "@modelcontextprotocol/sdk": "^1.10.2", + "@types/yargs": "^17.0.33", + "cross-env": "^7.0.3", + "dotenv": "^16.4.7", + "express": "^4.21.2", + "js-yaml": "^4.1.0", + "remeda": "^2.20.1", + "sharp": "^0.34.3", + "yargs": "^17.7.2", + "zod": "^3.24.2" + }, + "bin": { + "figma-developer-mcp": "dist/bin.js" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/figma-developer-mcp/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/figma-developer-mcp/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -3718,6 +4927,39 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", @@ -3754,6 +4996,24 @@ "dev": true, "license": "ISC" }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fs-extra": { "version": "11.3.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.1.tgz", @@ -3794,7 +5054,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3813,12 +5072,35 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -3829,6 +5111,19 @@ "node": ">=8.0.0" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", @@ -3960,6 +5255,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4026,11 +5333,22 @@ "node": ">=8" } }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -4079,6 +5397,22 @@ "dev": true, "license": "MIT" }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -4105,6 +5439,18 @@ "url": "https://github.com/sponsors/typicode" } }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -4198,7 +5544,6 @@ "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, "license": "ISC" }, "node_modules/ini": { @@ -4208,6 +5553,15 @@ "dev": true, "license": "ISC" }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -4256,7 +5610,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -4323,6 +5676,12 @@ "node": ">=0.10.0" } }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, "node_modules/is-stream": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", @@ -4353,7 +5712,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/istanbul-lib-coverage": { @@ -4456,6 +5814,7 @@ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@jest/core": "^29.7.0", "@jest/types": "^29.6.3", @@ -5096,7 +6455,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { @@ -5873,6 +7231,24 @@ "node": ">= 12" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/meow": { "version": "8.1.2", "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", @@ -5922,6 +7298,15 @@ "node": ">=10" } }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -5936,21 +7321,63 @@ "dev": true, "license": "MIT", "engines": { - "node": ">= 8" + "node": ">= 8" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "license": "MIT", "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" + "mime-db": "1.52.0" }, "engines": { - "node": ">=8.6" + "node": ">= 0.6" } }, "node_modules/mimic-fn": { @@ -6024,6 +7451,15 @@ "dev": true, "license": "MIT" }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -6095,11 +7531,43 @@ "node": ">=8" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -6226,6 +7694,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -6250,7 +7727,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6263,6 +7739,12 @@ "dev": true, "license": "MIT" }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -6314,6 +7796,15 @@ "node": ">= 6" } }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", @@ -6395,6 +7886,19 @@ "node": ">= 6" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -6422,6 +7926,21 @@ ], "license": "MIT" }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -6453,6 +7972,46 @@ "node": ">=8" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.1.tgz", + "integrity": "sha512-9G8cA+tuMS75+6G/TzW8OtLzmBDMo8p1JRxN5AZ+LAp8uxGA8V8GZm4GQ4/N5QNQEnLmg6SS7wyuSmbKepiKqA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.7.0", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz", + "integrity": "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -6585,11 +8144,31 @@ "node": ">=8" } }, + "node_modules/remeda": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/remeda/-/remeda-2.32.0.tgz", + "integrity": "sha512-BZx9DsT4FAgXDTOdgJIc5eY6ECIXMwtlSPQoPglF20ycSWigttDDe88AozEsPPT4OWk5NujroGSBC1phw5uU+w==", + "license": "MIT", + "dependencies": { + "type-fest": "^4.41.0" + } + }, + "node_modules/remeda/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6599,7 +8178,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6724,6 +8302,32 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/router/node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -6752,7 +8356,6 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, "funding": [ { "type": "github", @@ -6769,6 +8372,12 @@ ], "license": "MIT" }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -6778,11 +8387,135 @@ "semver": "bin/semver.js" } }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -6795,7 +8528,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6814,6 +8546,78 @@ "vscode-textmate": "^8.0.0" } }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -6977,6 +8781,15 @@ "node": ">=10" } }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -7015,7 +8828,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -7030,7 +8842,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -7179,6 +8990,15 @@ "node": ">=8.0" } }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, "node_modules/trim-newlines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", @@ -7287,6 +9107,7 @@ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -7325,6 +9146,13 @@ } } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -7361,6 +9189,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typedoc": { "version": "0.25.13", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.13.tgz", @@ -7414,6 +9255,7 @@ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7453,6 +9295,15 @@ "node": ">= 10.0.0" } }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/update-browserslist-db": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", @@ -7500,6 +9351,15 @@ "dev": true, "license": "MIT" }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", @@ -7533,6 +9393,15 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", @@ -7561,7 +9430,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -7594,7 +9462,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -7612,7 +9479,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, "license": "ISC" }, "node_modules/write-file-atomic": { @@ -7633,7 +9499,6 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, "license": "ISC", "engines": { "node": ">=10" @@ -7659,7 +9524,6 @@ "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, "license": "MIT", "dependencies": { "cliui": "^8.0.1", @@ -7678,7 +9542,6 @@ "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, "license": "ISC", "engines": { "node": ">=12" @@ -7706,6 +9569,25 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "peer": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } } } } diff --git a/package.json b/package.json index bb0dd47..f9eff31 100644 --- a/package.json +++ b/package.json @@ -62,23 +62,18 @@ "javascript", "programming-language" ], - "author": { - "name": "LindenTech IT Consulting", - "email": "info@lindentech.de", - "url": "https://lindentech.de" - }, + "author": "LindenTech IT Consulting (https://lindentech.de)", "contributors": [ { "name": "Bakhtier Gaibulloev", "email": "bakhtier.gaibulloev@gmail.com", - "url": "https://www.linkedin.com/in/gbakhtier/", - "role": "original creator, language author" + "url": "https://www.linkedin.com/in/gbakhtier/" } ], "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/lindentechde/Somon-Script.git" + "url": "git+https://github.com/lindentechde/Somon-Script.git" }, "bugs": { "url": "https://github.com/lindentechde/Somon-Script/issues" @@ -105,7 +100,15 @@ "babel-preset-minify": "^0.5.2", "chokidar": "^3.6.0", "commander": "^11.0.0", + "figma-developer-mcp": "^0.6.4", "source-map": "^0.7.6", "typescript": "^5.0.0" - } + }, + "directories": { + "doc": "docs", + "example": "examples", + "test": "tests" + }, + "type": "commonjs", + "types": "./dist/index.d.ts" } diff --git a/repro_arrow.ts b/repro_arrow.ts new file mode 100644 index 0000000..b207b77 --- /dev/null +++ b/repro_arrow.ts @@ -0,0 +1,10 @@ +import { compile } from './src/compiler'; + +const source = 'тағйирёбанда ҳисоб = (а: рақам, б: рақам): рақам => а * б;'; +try { + const result = compile(source); + console.log('Code:', result.code); + console.log('Errors:', result.errors); +} catch (e) { + console.error('Exception:', e); +} diff --git a/src/ast.ts b/src/ast.ts index 17546ba..267a240 100644 --- a/src/ast.ts +++ b/src/ast.ts @@ -146,6 +146,7 @@ export interface ArrowFunctionExpression extends Expression { params: Parameter[]; body: BlockStatement | Expression; isAsync?: boolean; + returnType?: TypeAnnotation; } export interface AssignmentExpression extends Expression { diff --git a/src/codegen.ts b/src/codegen.ts index 59eb5f9..5012b36 100644 --- a/src/codegen.ts +++ b/src/codegen.ts @@ -98,7 +98,11 @@ export class CodeGenerator { ['дарозии_сатр', 'length'], ['пайвастан', 'concat'], ['ҷойивазкунӣ', 'replace'], - ['ҷудокунӣ', 'join'], // Array join method (combines elements into string) + ['ҷудокунӣ', 'split'], // String split method + ['калон', 'toUpperCase'], + ['хурд', 'toLowerCase'], + ['қисмат', 'substring'], + ['ҷойгузин', 'replace'], // Object methods ['объект', 'Object'], @@ -107,6 +111,13 @@ export class CodeGenerator { // Math ['математика', 'Math'], + ['Риёзӣ', 'Math'], + ['дуръшака', 'sqrt'], + ['қувват', 'pow'], + ['тасодуфӣ', 'random'], + ['дузкунӣ', 'round'], + ['боло', 'ceil'], + ['поён', 'floor'], // Control flow ['шикастан', 'break'], @@ -770,13 +781,6 @@ export class CodeGenerator { return 'undefined'; } - // Special case: don't map 'хато' when it's used as Error constructor - if (node.name === 'хато') { - // This is a bit of a hack - we need context to know if it's console.error or Error - // For now, we'll assume standalone 'хато' means Error, and 'чоп.хато' means console.error - return 'Error'; - } - // Handle Хато (capitalized) as Error constructor if (node.name === 'Хато') { return 'Error'; @@ -891,7 +895,7 @@ export class CodeGenerator { } const objectName = (node.object as Identifier).name; - const builtinObjects = ['чоп', 'математика', 'объект']; + const builtinObjects = ['чоп', 'математика', 'объект', 'Риёзӣ']; if (!builtinObjects.includes(objectName)) { return { mapped: object, wasMapped: false }; @@ -931,6 +935,7 @@ export class CodeGenerator { } const commonMethods = [ + // Array methods 'пуш', 'илова', 'баровардан', @@ -938,10 +943,22 @@ export class CodeGenerator { 'харита', 'филтр', 'кофтан', + 'буридан', + // String methods 'пайвастан', 'ҷойивазкунӣ', 'ҷудокунӣ', - 'буридан', + 'калон', + 'хурд', + 'қисмат', + 'ҷойгузин', + // Math methods + 'дуръшака', + 'қувват', + 'тасодуфӣ', + 'дузкунӣ', + 'боло', + 'поён', ]; const shouldMap = @@ -992,7 +1009,8 @@ export class CodeGenerator { if (node.handler) { result += ' catch '; if (node.handler.param) { - result += `(${this.generateIdentifier(node.handler.param)}) `; + // Don't map catch parameter names - preserve original + result += `(${node.handler.param.name}) `; } else { result += '(error) '; } diff --git a/src/parser.ts b/src/parser.ts index 3f2b94e..31dde11 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -585,14 +585,21 @@ export class Parser { line: token.line, column: token.column, }; + + let paramType: TypeAnnotation | undefined; + if (this.match(TokenType.COLON)) { + paramType = this.typeAnnotation(); + } + params.push({ type: 'Parameter', name: identifier, + typeAnnotation: paramType, line: token.line, column: token.column, }); } else { - // Not arrow function parameters + // Not an identifier, so not a simple parameter list this.current = savedIndex; return null; } @@ -605,6 +612,11 @@ export class Parser { return null; } + let returnType: TypeAnnotation | undefined; + if (this.match(TokenType.COLON)) { + returnType = this.typeAnnotation(); + } + // Check for arrow if (!this.match(TokenType.ARROW)) { // Not arrow function @@ -619,6 +631,7 @@ export class Parser { type: 'ArrowFunctionExpression', params, body, + returnType, line: this.tokens[savedIndex].line, column: this.tokens[savedIndex].column, } as ArrowFunctionExpression; diff --git a/tests/quick-start.test.ts b/tests/quick-start.test.ts new file mode 100644 index 0000000..707dfe3 --- /dev/null +++ b/tests/quick-start.test.ts @@ -0,0 +1,274 @@ +import { compile } from '../src/compiler'; + +describe('Quick Start Reference Tests', () => { + describe('Math (Риёзӣ) Object', () => { + test('should transpile Риёзӣ to Math', () => { + const source = 'тағйирёбанда натиҷа = Риёзӣ.дуръшака(9);'; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('Math.sqrt(9)'); + }); + + test('should transpile all Math methods', () => { + const testCases = [ + { source: 'Риёзӣ.дуръшака(9);', expected: 'Math.sqrt(9)' }, + { source: 'Риёзӣ.қувват(2, 3);', expected: 'Math.pow(2, 3)' }, + { source: 'Риёзӣ.тасодуфӣ();', expected: 'Math.random()' }, + { source: 'Риёзӣ.дузкунӣ(4.7);', expected: 'Math.round(4.7)' }, + { source: 'Риёзӣ.боло(4.2);', expected: 'Math.ceil(4.2)' }, + { source: 'Риёзӣ.поён(4.7);', expected: 'Math.floor(4.7)' }, + ]; + + testCases.forEach(({ source, expected }) => { + const result = compile(source); + expect(result.errors).toHaveLength(0); + expect(result.code).toContain(expected); + }); + }); + + test('should handle complex Math expressions', () => { + const source = 'тағйирёбанда натиҷа = Риёзӣ.қувват(Риёзӣ.дуръшака(16), 2);'; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('Math.pow(Math.sqrt(16), 2)'); + }); + }); + + describe('String Methods', () => { + test('should transpile string methods correctly', () => { + const testCases = [ + { source: 'матн.дарозӣ;', expected: '.length' }, + { source: 'матн.калон();', expected: '.toUpperCase()' }, + { source: 'матн.хурд();', expected: '.toLowerCase()' }, + { source: 'матн.қисмат(0, 5);', expected: '.substring(0, 5)' }, + { source: 'матн.ҷойгузин("a", "b");', expected: '.replace("a", "b")' }, + { source: 'матн.ҷудокунӣ(",");', expected: '.split(",")' }, + ]; + + testCases.forEach(({ source, expected }) => { + const fullSource = `тағйирёбанда матн = "test"; ${source}`; + const result = compile(fullSource); + expect(result.errors).toHaveLength(0); + expect(result.code).toContain(expected); + }); + }); + }); + + describe('Console Methods', () => { + test('should transpile console methods correctly', () => { + const testCases = [ + { source: 'чоп.сабт("Салом");', expected: 'console.log("Салом")' }, + { source: 'чоп.хато("Хато");', expected: 'console.error("Хато")' }, + { source: 'чоп.огоҳӣ("Огоҳӣ");', expected: 'console.warn("Огоҳӣ")' }, + { source: 'чоп.маълумот("Маълумот");', expected: 'console.info("Маълумот")' }, + ]; + + testCases.forEach(({ source, expected }) => { + const result = compile(source); + expect(result.errors).toHaveLength(0); + expect(result.code).toContain(expected); + }); + }); + }); + + describe('Variables and Constants', () => { + test('should handle variable declarations', () => { + const source = ` + тағйирёбанда ном = "Аҳмад"; + тағйирёбанда синну_сол = 25; + тағйирёбанда фаъол = дуруст; + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('let ном = "Аҳмад"'); + expect(result.code).toContain('let синну_сол = 25'); + expect(result.code).toContain('let фаъол = true'); + }); + + test('should handle constants', () => { + const source = ` + собит ПИ = 3.14159; + собит МАКС_СИННУ_СОЛ = 120; + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('const ПИ = 3.14159'); + expect(result.code).toContain('const МАКС_СИННУ_СОЛ = 120'); + }); + }); + + describe('Control Flow', () => { + test('should handle if-else statements', () => { + const source = ` + агар (x > 0) { + чоп.сабт("Мусбат"); + } вагарна агар (x < 0) { + чоп.сабт("Манфӣ"); + } вагарна { + чоп.сабт("Сифр"); + } + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('if (x > 0)'); + expect(result.code).toContain('} else if (x < 0)'); + expect(result.code).toContain('} else {'); + }); + + test('should handle for loops', () => { + const source = ` + барои (тағйирёбанда i = 0; i < 10; i++) { + чоп.сабт(i); + } + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('for (let i = 0; i < 10; i++)'); + }); + + test('should handle while loops', () => { + const source = ` + то (шарт) { + чоп.сабт("Давом"); + } + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('while (шарт)'); + }); + }); + + describe('Functions', () => { + test('should handle basic function declarations', () => { + const source = ` + функсия салом(ном: сатр): сатр { + бозгашт "Салом, " + ном; + } + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('function салом(ном)'); + expect(result.code).toContain('return "Салом, " + ном'); + }); + + test('should handle arrow functions', () => { + const source = 'тағйирёбанда ҳисоб = (а, б) => а * б;'; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('(а, б) => а * б'); + }); + }); + + describe('Arrays', () => { + test('should handle array declarations and methods', () => { + const source = ` + тағйирёбанда мева = ["себ", "мӯз", "анор"]; + мева.push("шафтолу"); + тағйирёбанда дарозӣ = мева.length; + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('["себ", "мӯз", "анор"]'); + expect(result.code).toContain('.push("шафтолу")'); + expect(result.code).toContain('.length'); + }); + }); + + describe('Objects', () => { + test('should handle object declarations', () => { + const source = ` + тағйирёбанда корбар = { + ном: "Анвар", + синну_сол: 30, + шаҳр: "Душанбе" + }; + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('ном: "Анвар"'); + expect(result.code).toContain('синну_сол: 30'); + expect(result.code).toContain('шаҳр: "Душанбе"'); + }); + }); + + describe('Classes', () => { + test('should handle class declarations', () => { + const source = ` + синф Шахс { + хосусӣ ном: сатр; + + конструктор(ном: сатр) { + ин.ном = ном; + } + + ҷамъиятӣ салом(): сатр { + бозгашт "Салом, " + ин.ном; + } + } + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('class Шахс'); + expect(result.code).toContain('constructor(ном)'); + expect(result.code).toContain('this.ном = ном'); + }); + }); + + describe('Error Handling', () => { + test('should handle try-catch blocks', () => { + const source = ` + кӯшиш { + чоп.сабт("Кӯшиш"); + } гирифтан (хато) { + чоп.хато(хато); + } ниҳоят { + чоп.сабт("Ниҳоят"); + } + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('try {'); + expect(result.code).toContain('} catch (хато)'); + expect(result.code).toContain('} finally {'); + }); + }); + + describe('Template Literals', () => { + test('should handle template literals', () => { + const source = 'тағйирёбанда паём = `Салом, ${ном}!`;'; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('`Салом, ${ном}!`'); + }); + }); + + describe('Async/Await', () => { + test('should handle async functions', () => { + const source = ` + ҳамзамон функсия маълумот_гирифтан() { + тағйирёбанда натиҷа = интизор fetch("url"); + бозгашт натиҷа; + } + `; + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('async function маълумот_гирифтан()'); + expect(result.code).toContain('await fetch("url")'); + }); + }); +}); From b12dda9328295e42c3e3a3cfd04d5fd898be21b3 Mon Sep 17 00:00:00 2001 From: Bakhtier Gaibulloev Date: Thu, 20 Nov 2025 09:52:27 +0100 Subject: [PATCH 2/9] feat: standardize Tajik method names to use camelCase MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace underscore-separated method names with camelCase equivalents (e.g., 'гуруҳ_охир' → 'гуруҳОхир', 'вақт_сабт' → 'вақтСабт') for consistency with Tajik naming conventions. Updated 80+ identifier mappings across: - Array methods (copyWithin, findIndex, flatMap, forEach, etc.) - String methods (charAt, codePointAt, padStart, replaceAll, etc.) - Math methods (acosh, asinh, atanh, hypot, etc.) - Object methods (defineProperties, getOwnPropertyDescriptor, etc.) All tests passing (1233 tests). --- src/codegen.ts | 312 ++++++++++++++++++++++++++++++++---- tests/compiler.test.ts | 4 +- tests/stdlib-array.test.ts | 69 ++++++++ tests/stdlib-math.test.ts | 60 +++++++ tests/stdlib-object.test.ts | 43 +++++ tests/stdlib-string.test.ts | 58 +++++++ 6 files changed, 512 insertions(+), 34 deletions(-) create mode 100644 tests/stdlib-array.test.ts create mode 100644 tests/stdlib-math.test.ts create mode 100644 tests/stdlib-object.test.ts create mode 100644 tests/stdlib-string.test.ts diff --git a/src/codegen.ts b/src/codegen.ts index 5012b36..10f4e5c 100644 --- a/src/codegen.ts +++ b/src/codegen.ts @@ -66,17 +66,17 @@ export class CodeGenerator { ['исфти', 'debug'], ['ҷадвал', 'table'], ['гуруҳ', 'group'], - ['гуруҳ_охир', 'groupEnd'], - ['гуруҳ_пӯшида', 'groupCollapsed'], + ['гуруҳОхир', 'groupEnd'], + ['гуруҳПӯшида', 'groupCollapsed'], ['вақт', 'time'], - ['вақт_охир', 'timeEnd'], - ['вақт_сабт', 'timeLog'], + ['вақтОхир', 'timeEnd'], + ['вақтСабт', 'timeLog'], ['қайд', 'count'], - ['қайд_асл', 'countReset'], + ['қайдАсл', 'countReset'], ['тасдиқ', 'assert'], ['полиз', 'clear'], ['феҳрист', 'dir'], - ['xml_феҳрист', 'dirxml'], + ['xmlФеҳрист', 'dirxml'], ['пайҷо', 'trace'], // Error handling @@ -84,40 +84,163 @@ export class CodeGenerator { // Array methods ['рӯйхат', 'Array'], - ['илова', 'push'], - ['пуш', 'push'], - ['баровардан', 'pop'], ['дарозӣ', 'length'], - ['харита', 'map'], + ['дар', 'at'], + ['пайвастан', 'concat'], + ['нусхаДарДохил', 'copyWithin'], + ['воридот', 'entries'], + ['ҳама', 'every'], + ['пурКардан', 'fill'], ['филтр', 'filter'], ['кофтан', 'find'], - ['буридан', 'slice'], // Tajik word for slice/cut + ['индексиЁфтан', 'findIndex'], + ['охиринЁфтан', 'findLast'], + ['индексиОхиринЁфтан', 'findLastIndex'], + ['ҳамвор', 'flat'], + ['ҳамворХарита', 'flatMap'], + ['бароиҲар', 'forEach'], + ['аз', 'from'], + ['дорад', 'includes'], + ['индекси', 'indexOf'], + ['рӯйхатАст', 'isArray'], + ['пайвастКардан', 'join'], + ['калидҳо', 'keys'], + ['индексиОхирин', 'lastIndexOf'], + ['харита', 'map'], + ['азАргументҳо', 'of'], + ['баровардан', 'pop'], + ['илова', 'push'], + ['пуш', 'push'], + ['ҷамъбаст', 'reduce'], + ['ҷамъбастАзРост', 'reduceRight'], + ['баргардон', 'reverse'], + ['ҳазфиАввал', 'shift'], + ['буридан', 'slice'], + ['баъзе', 'some'], + ['тартиб', 'sort'], + ['пайваст', 'splice'], + ['баСатриМаҳаллӣ', 'toLocaleString'], + ['баБаргардон', 'toReversed'], + ['баТартиб', 'toSorted'], + ['баПайваст', 'toSpliced'], + ['баСатр', 'toString'], + ['иловаБаАввал', 'unshift'], + ['қиматҳо', 'values'], + ['бо', 'with'], // String methods - ['сатр_методҳо', 'String'], - ['дарозии_сатр', 'length'], + ['сатр', 'String'], // String type/constructor + ['сатрМетодҳо', 'String'], // String methods object + ['дарозииСатр', 'length'], + ['дар', 'at'], + ['аломатДар', 'charAt'], + ['кодиАломатДар', 'charCodeAt'], + ['нуқтаиКодДар', 'codePointAt'], ['пайвастан', 'concat'], + ['анҷомБо', 'endsWith'], + ['азКодиАломат', 'fromCharCode'], + ['азНуқтаиКод', 'fromCodePoint'], + ['дорад', 'includes'], + ['индекси', 'indexOf'], + ['индексиОхирин', 'lastIndexOf'], + ['муқоисаиМаҳаллӣ', 'localeCompare'], + ['мувофиқат', 'match'], + ['мувофиқатҲама', 'matchAll'], + ['муқаррарӣ', 'normalize'], + ['пурКарданОхир', 'padEnd'], + ['пурКарданАввал', 'padStart'], + ['хоми', 'raw'], + ['такрор', 'repeat'], ['ҷойивазкунӣ', 'replace'], - ['ҷудокунӣ', 'split'], // String split method - ['калон', 'toUpperCase'], - ['хурд', 'toLowerCase'], - ['қисмат', 'substring'], ['ҷойгузин', 'replace'], + ['ҷойивазкунӣҲама', 'replaceAll'], + ['ҷустуҷӯ', 'search'], + ['буридан', 'slice'], + ['ҷудокунӣ', 'split'], + ['оғозБо', 'startsWith'], + ['қисмат', 'substring'], + ['хурдМаҳаллӣ', 'toLocaleLowerCase'], + ['калонМаҳаллӣ', 'toLocaleUpperCase'], + ['хурд', 'toLowerCase'], + ['баСатр', 'toString'], + ['калон', 'toUpperCase'], + ['тозаКардан', 'trim'], + ['тозаКарданОхир', 'trimEnd'], + ['тозаКарданАввал', 'trimStart'], + ['қиматиАслӣ', 'valueOf'], // Object methods ['объект', 'Object'], + ['таъин', 'assign'], + ['сохтан', 'create'], + ['муайянХосиятҳо', 'defineProperties'], + ['муайянХосият', 'defineProperty'], + ['воридот', 'entries'], + ['яхКардан', 'freeze'], + ['азВоридот', 'fromEntries'], + ['тавсифиХосият', 'getOwnPropertyDescriptor'], + ['тавсифиХосиятҳо', 'getOwnPropertyDescriptors'], + ['номҳоиХосият', 'getOwnPropertyNames'], + ['рамзҳоиХосият', 'getOwnPropertySymbols'], + ['прототип', 'getPrototypeOf'], + ['гурӯҳбандӣ', 'groupBy'], + ['дорадХосият', 'hasOwn'], + ['аст', 'is'], + ['васеъшаванда', 'isExtensible'], + ['яхшуда', 'isFrozen'], + ['мӯҳршуда', 'isSealed'], ['калидҳо', 'keys'], + ['манъиВасеъшавӣ', 'preventExtensions'], + ['мӯҳр', 'seal'], + ['танзимиПрототип', 'setPrototypeOf'], ['қиматҳо', 'values'], // Math ['математика', 'Math'], ['Риёзӣ', 'Math'], - ['дуръшака', 'sqrt'], + ['Е', 'E'], + ['ЛН10', 'LN10'], + ['ЛН2', 'LN2'], + ['ЛОГ10Е', 'LOG10E'], + ['ЛОГ2Е', 'LOG2E'], + ['ПИ', 'PI'], + ['РЕША1_2', 'SQRT1_2'], + ['РЕША2', 'SQRT2'], + ['мутлақ', 'abs'], + ['арккосинус', 'acos'], + ['арккосинусГиперболӣ', 'acosh'], + ['арксинус', 'asin'], + ['арксинусГиперболӣ', 'asinh'], + ['арктангенс', 'atan'], + ['арктангенс2', 'atan2'], + ['арктангенсГиперболӣ', 'atanh'], + ['решаиКубӣ', 'cbrt'], + ['боло', 'ceil'], + ['clz32', 'clz32'], + ['косинус', 'cos'], + ['косинусГиперболӣ', 'cosh'], + ['экспонента', 'exp'], + ['expm1', 'expm1'], + ['поён', 'floor'], + ['fround', 'fround'], + ['гипотенуза', 'hypot'], + ['imul', 'imul'], + ['логарифм', 'log'], + ['логарифм10', 'log10'], + ['логарифм1п', 'log1p'], + ['логарифм2', 'log2'], + ['ҳаддиАксар', 'max'], + ['ҳаддиАқал', 'min'], ['қувват', 'pow'], ['тасодуфӣ', 'random'], ['дузкунӣ', 'round'], - ['боло', 'ceil'], - ['поён', 'floor'], + ['аломат', 'sign'], + ['синус', 'sin'], + ['синусГиперболӣ', 'sinh'], + ['дуръшака', 'sqrt'], + ['тангенс', 'tan'], + ['тангенсГиперболӣ', 'tanh'], + ['бириданАдад', 'trunc'], // Control flow ['шикастан', 'break'], @@ -786,6 +909,15 @@ export class CodeGenerator { return 'Error'; } + // Map built-in constructors/objects (when used as identifiers) + const builtinConstructors = ['сатр', 'рӯйхат', 'объект', 'математика', 'Риёзӣ']; + if (builtinConstructors.includes(node.name)) { + const mapped = this.builtinMappings.get(node.name); + if (mapped) { + return mapped; + } + } + // Don't map variable names that could conflict with JS built-ins // Only map in specific contexts (handled in generateMemberExpression) return node.name; @@ -895,7 +1027,7 @@ export class CodeGenerator { } const objectName = (node.object as Identifier).name; - const builtinObjects = ['чоп', 'математика', 'объект', 'Риёзӣ']; + const builtinObjects = ['чоп', 'математика', 'объект', 'Риёзӣ', 'сатр', 'сатрМетодҳо']; if (!builtinObjects.includes(objectName)) { return { mapped: object, wasMapped: false }; @@ -936,29 +1068,145 @@ export class CodeGenerator { const commonMethods = [ // Array methods - 'пуш', - 'илова', - 'баровардан', 'дарозӣ', - 'харита', + 'дар', + 'пайвастан', + 'нусхаДарДохил', + 'воридот', + 'ҳама', + 'пурКардан', 'филтр', 'кофтан', + 'индексиЁфтан', + 'охиринЁфтан', + 'индексиОхиринЁфтан', + 'ҳамвор', + 'ҳамворХарита', + 'бароиҲар', + 'аз', + 'дорад', + 'индекси', + 'рӯйхатАст', + 'пайвастКардан', + 'калидҳо', + 'индексиОхирин', + 'харита', + 'азАргументҳо', + 'баровардан', + 'илова', + 'пуш', + 'ҷамъбаст', + 'ҷамъбастАзРост', + 'баргардон', + 'ҳазфиАввал', 'буридан', + 'баъзе', + 'тартиб', + 'пайваст', + 'баСатриМаҳаллӣ', + 'баБаргардон', + 'баТартиб', + 'баПайваст', + 'баСатр', + 'иловаБаАввал', + 'қиматҳо', + 'бо', // String methods - 'пайвастан', + 'дарозииСатр', + 'аломатДар', + 'кодиАломатДар', + 'нуқтаиКодДар', + 'анҷомБо', + 'азКодиАломат', + 'азНуқтаиКод', + 'муқоисаиМаҳаллӣ', + 'мувофиқат', + 'мувофиқатҲама', + 'муқаррарӣ', + 'пурКарданОхир', + 'пурКарданАввал', + 'хоми', + 'такрор', 'ҷойивазкунӣ', + 'ҷойгузин', + 'ҷойивазкунӣҲама', + 'ҷустуҷӯ', 'ҷудокунӣ', - 'калон', - 'хурд', + 'оғозБо', 'қисмат', - 'ҷойгузин', + 'хурдМаҳаллӣ', + 'калонМаҳаллӣ', + 'хурд', + 'калон', + 'тозаКардан', + 'тозаКарданОхир', + 'тозаКарданАввал', + 'қиматиАслӣ', // Math methods - 'дуръшака', + 'Е', + 'ЛН10', + 'ЛН2', + 'ЛОГ10Е', + 'ЛОГ2Е', + 'ПИ', + 'РЕША1_2', + 'РЕША2', + 'мутлақ', + 'арккосинус', + 'арккосинусГиперболӣ', + 'арксинус', + 'арксинусГиперболӣ', + 'арктангенс', + 'арктангенс2', + 'арктангенсГиперболӣ', + 'решаиКубӣ', + 'боло', + 'clz32', + 'косинус', + 'косинусГиперболӣ', + 'экспонента', + 'expm1', + 'поён', + 'fround', + 'гипотенуза', + 'imul', + 'логарифм', + 'логарифм10', + 'логарифм1п', + 'логарифм2', + 'ҳаддиАксар', + 'ҳаддиАқал', 'қувват', 'тасодуфӣ', 'дузкунӣ', - 'боло', - 'поён', + 'аломат', + 'синус', + 'синусГиперболӣ', + 'дуръшака', + 'тангенс', + 'тангенсГиперболӣ', + 'бириданАдад', + // Object methods + 'таъин', + 'сохтан', + 'муайянХосиятҳо', + 'муайянХосият', + 'яхКардан', + 'азВоридот', + 'тавсифиХосият', + 'тавсифиХосиятҳо', + 'номҳоиХосият', + 'рамзҳоиХосият', + 'прототип', + 'гурӯҳбандӣ', + 'дорадХосият', + 'аст', + 'васеъшаванда', + 'яхшуда', + 'мӯҳршуда', + 'манъиВасеъшавӣ', + 'мӯҳр', + 'танзимиПрототип', ]; const shouldMap = diff --git a/tests/compiler.test.ts b/tests/compiler.test.ts index 61fcd67..3705b29 100644 --- a/tests/compiler.test.ts +++ b/tests/compiler.test.ts @@ -152,11 +152,11 @@ describe('Compiler', () => { }); test('should compile object expressions', () => { - const source = 'тағйирёбанда объект = { ном: "Аҳмад", сол: 25 };'; + const source = 'тағйирёбанда объекти = { ном: "Аҳмад", сол: 25 };'; const result = compile(source); expect(result.errors).toHaveLength(0); - expect(result.code).toContain('let объект = {ном: "Аҳмад", сол: 25};'); + expect(result.code).toContain('let объекти = {ном: "Аҳмад", сол: 25};'); }); test('should compile member expressions', () => { diff --git a/tests/stdlib-array.test.ts b/tests/stdlib-array.test.ts new file mode 100644 index 0000000..d96e894 --- /dev/null +++ b/tests/stdlib-array.test.ts @@ -0,0 +1,69 @@ +import { compile } from '../src/compiler'; + +describe('Standard Library - Array Tests', () => { + test('should transpile all array properties and methods correctly', () => { + const testCases = [ + // Properties + { source: 'рӯйхат.дарозӣ;', expected: '.length' }, + + // Static Methods + { source: 'рӯйхат.аз("abc");', expected: '.from("abc")' }, + { source: 'рӯйхат.рӯйхатАст([]);', expected: '.isArray([])' }, + { source: 'рӯйхат.азАргументҳо(1, 2);', expected: '.of(1, 2)' }, + + // Instance Methods + { source: 'рӯйхат.дар(0);', expected: '.at(0)' }, + { source: 'рӯйхат.пайвастан([4]);', expected: '.concat([4])' }, + { source: 'рӯйхат.нусхаДарДохил(0, 1);', expected: '.copyWithin(0, 1)' }, + { source: 'рӯйхат.воридот();', expected: '.entries()' }, + { source: 'рӯйхат.ҳама(x => x > 0);', expected: '.every((x) => x > 0)' }, + { source: 'рӯйхат.пурКардан(0);', expected: '.fill(0)' }, + { source: 'рӯйхат.филтр(x => x > 0);', expected: '.filter((x) => x > 0)' }, + { source: 'рӯйхат.кофтан(x => x > 0);', expected: '.find((x) => x > 0)' }, + { source: 'рӯйхат.индексиЁфтан(x => x > 0);', expected: '.findIndex((x) => x > 0)' }, + { source: 'рӯйхат.охиринЁфтан(x => x > 0);', expected: '.findLast((x) => x > 0)' }, + { + source: 'рӯйхат.индексиОхиринЁфтан(x => x > 0);', + expected: '.findLastIndex((x) => x > 0)', + }, + { source: 'рӯйхат.ҳамвор();', expected: '.flat()' }, + { source: 'рӯйхат.ҳамворХарита(x => [x]);', expected: '.flatMap((x) => [x])' }, + { source: 'рӯйхат.бароиҲар(x => x);', expected: '.forEach((x) => x)' }, + { source: 'рӯйхат.дорад(1);', expected: '.includes(1)' }, + { source: 'рӯйхат.индекси(1);', expected: '.indexOf(1)' }, + { source: 'рӯйхат.пайвастКардан(",");', expected: '.join(",")' }, + { source: 'рӯйхат.калидҳо();', expected: '.keys()' }, + { source: 'рӯйхат.индексиОхирин(1);', expected: '.lastIndexOf(1)' }, + { source: 'рӯйхат.харита(x => x * 2);', expected: '.map((x) => x * 2)' }, + { source: 'рӯйхат.баровардан();', expected: '.pop()' }, + { source: 'рӯйхат.илова(4);', expected: '.push(4)' }, + { source: 'рӯйхат.пуш(4);', expected: '.push(4)' }, + { source: 'рӯйхат.ҷамъбаст((a, b) => a + b);', expected: '.reduce((a, b) => a + b)' }, + { + source: 'рӯйхат.ҷамъбастАзРост((a, b) => a + b);', + expected: '.reduceRight((a, b) => a + b)', + }, + { source: 'рӯйхат.баргардон();', expected: '.reverse()' }, + { source: 'рӯйхат.ҳазфиАввал();', expected: '.shift()' }, + { source: 'рӯйхат.буридан(1);', expected: '.slice(1)' }, + { source: 'рӯйхат.баъзе(x => x > 0);', expected: '.some((x) => x > 0)' }, + { source: 'рӯйхат.тартиб();', expected: '.sort()' }, + { source: 'рӯйхат.пайваст(1, 1);', expected: '.splice(1, 1)' }, + { source: 'рӯйхат.баСатриМаҳаллӣ();', expected: '.toLocaleString()' }, + { source: 'рӯйхат.баБаргардон();', expected: '.toReversed()' }, + { source: 'рӯйхат.баТартиб();', expected: '.toSorted()' }, + { source: 'рӯйхат.баПайваст(0, 1);', expected: '.toSpliced(0, 1)' }, + { source: 'рӯйхат.баСатр();', expected: '.toString()' }, + { source: 'рӯйхат.иловаБаАввал(0);', expected: '.unshift(0)' }, + { source: 'рӯйхат.қиматҳо();', expected: '.values()' }, + { source: 'рӯйхат.бо(0, 1);', expected: '.with(0, 1)' }, + ]; + + testCases.forEach(({ source, expected }) => { + const fullSource = `тағйирёбанда рӯйхат = [1, 2, 3]; ${source}`; + const result = compile(fullSource); + expect(result.errors).toHaveLength(0); + expect(result.code).toContain(expected); + }); + }); +}); diff --git a/tests/stdlib-math.test.ts b/tests/stdlib-math.test.ts new file mode 100644 index 0000000..1b9c4d7 --- /dev/null +++ b/tests/stdlib-math.test.ts @@ -0,0 +1,60 @@ +import { compile } from '../src/compiler'; + +describe('Standard Library - Math Tests', () => { + test('should transpile all math properties and methods correctly', () => { + const testCases = [ + // Constants + { source: 'Риёзӣ.Е;', expected: 'Math.E' }, + { source: 'Риёзӣ.ЛН10;', expected: 'Math.LN10' }, + { source: 'Риёзӣ.ЛН2;', expected: 'Math.LN2' }, + { source: 'Риёзӣ.ЛОГ10Е;', expected: 'Math.LOG10E' }, + { source: 'Риёзӣ.ЛОГ2Е;', expected: 'Math.LOG2E' }, + { source: 'Риёзӣ.ПИ;', expected: 'Math.PI' }, + { source: 'Риёзӣ.РЕША1_2;', expected: 'Math.SQRT1_2' }, + { source: 'Риёзӣ.РЕША2;', expected: 'Math.SQRT2' }, + + // Methods + { source: 'Риёзӣ.мутлақ(-1);', expected: 'Math.abs(-1)' }, + { source: 'Риёзӣ.арккосинус(0);', expected: 'Math.acos(0)' }, + { source: 'Риёзӣ.арккосинусГиперболӣ(1);', expected: 'Math.acosh(1)' }, + { source: 'Риёзӣ.арксинус(0);', expected: 'Math.asin(0)' }, + { source: 'Риёзӣ.арксинусГиперболӣ(0);', expected: 'Math.asinh(0)' }, + { source: 'Риёзӣ.арктангенс(0);', expected: 'Math.atan(0)' }, + { source: 'Риёзӣ.арктангенс2(0, 0);', expected: 'Math.atan2(0, 0)' }, + { source: 'Риёзӣ.арктангенсГиперболӣ(0);', expected: 'Math.atanh(0)' }, + { source: 'Риёзӣ.решаиКубӣ(8);', expected: 'Math.cbrt(8)' }, + { source: 'Риёзӣ.боло(1.1);', expected: 'Math.ceil(1.1)' }, + { source: 'Риёзӣ.clz32(1);', expected: 'Math.clz32(1)' }, + { source: 'Риёзӣ.косинус(0);', expected: 'Math.cos(0)' }, + { source: 'Риёзӣ.косинусГиперболӣ(0);', expected: 'Math.cosh(0)' }, + { source: 'Риёзӣ.экспонента(1);', expected: 'Math.exp(1)' }, + { source: 'Риёзӣ.expm1(1);', expected: 'Math.expm1(1)' }, + { source: 'Риёзӣ.поён(1.9);', expected: 'Math.floor(1.9)' }, + { source: 'Риёзӣ.fround(1.5);', expected: 'Math.fround(1.5)' }, + { source: 'Риёзӣ.гипотенуза(3, 4);', expected: 'Math.hypot(3, 4)' }, + { source: 'Риёзӣ.imul(2, 2);', expected: 'Math.imul(2, 2)' }, + { source: 'Риёзӣ.логарифм(1);', expected: 'Math.log(1)' }, + { source: 'Риёзӣ.логарифм10(10);', expected: 'Math.log10(10)' }, + { source: 'Риёзӣ.логарифм1п(0);', expected: 'Math.log1p(0)' }, + { source: 'Риёзӣ.логарифм2(2);', expected: 'Math.log2(2)' }, + { source: 'Риёзӣ.ҳаддиАксар(1, 2);', expected: 'Math.max(1, 2)' }, + { source: 'Риёзӣ.ҳаддиАқал(1, 2);', expected: 'Math.min(1, 2)' }, + { source: 'Риёзӣ.қувват(2, 2);', expected: 'Math.pow(2, 2)' }, + { source: 'Риёзӣ.тасодуфӣ();', expected: 'Math.random()' }, + { source: 'Риёзӣ.дузкунӣ(1.5);', expected: 'Math.round(1.5)' }, + { source: 'Риёзӣ.аломат(-1);', expected: 'Math.sign(-1)' }, + { source: 'Риёзӣ.синус(0);', expected: 'Math.sin(0)' }, + { source: 'Риёзӣ.синусГиперболӣ(0);', expected: 'Math.sinh(0)' }, + { source: 'Риёзӣ.дуръшака(4);', expected: 'Math.sqrt(4)' }, + { source: 'Риёзӣ.тангенс(0);', expected: 'Math.tan(0)' }, + { source: 'Риёзӣ.тангенсГиперболӣ(0);', expected: 'Math.tanh(0)' }, + { source: 'Риёзӣ.бириданАдад(1.5);', expected: 'Math.trunc(1.5)' }, + ]; + + testCases.forEach(({ source, expected }) => { + const result = compile(source); + expect(result.errors).toHaveLength(0); + expect(result.code).toContain(expected); + }); + }); +}); diff --git a/tests/stdlib-object.test.ts b/tests/stdlib-object.test.ts new file mode 100644 index 0000000..a811c29 --- /dev/null +++ b/tests/stdlib-object.test.ts @@ -0,0 +1,43 @@ +import { compile } from '../src/compiler'; + +describe('Standard Library - Object Tests', () => { + test('should transpile all object methods correctly', () => { + const testCases = [ + { source: 'объект.таъин({}, {});', expected: 'Object.assign({}, {})' }, + { source: 'объект.сохтан(беқимат);', expected: 'Object.create(undefined)' }, + { source: 'объект.муайянХосиятҳо({}, {});', expected: 'Object.defineProperties({}, {})' }, + { + source: 'объект.муайянХосият({}, "prop", {});', + expected: 'Object.defineProperty({}, "prop", {})', + }, + { source: 'объект.воридот({});', expected: 'Object.entries({})' }, + { source: 'объект.яхКардан({});', expected: 'Object.freeze({})' }, + { source: 'объект.азВоридот([]);', expected: 'Object.fromEntries([])' }, + { + source: 'объект.тавсифиХосият({}, "prop");', + expected: 'Object.getOwnPropertyDescriptor({}, "prop")', + }, + { source: 'объект.тавсифиХосиятҳо({});', expected: 'Object.getOwnPropertyDescriptors({})' }, + { source: 'объект.номҳоиХосият({});', expected: 'Object.getOwnPropertyNames({})' }, + { source: 'объект.рамзҳоиХосият({});', expected: 'Object.getOwnPropertySymbols({})' }, + { source: 'объект.прототип({});', expected: 'Object.getPrototypeOf({})' }, + { source: 'объект.гурӯҳбандӣ([], x => x);', expected: 'Object.groupBy([], (x) => x)' }, + { source: 'объект.дорадХосият({}, "prop");', expected: 'Object.hasOwn({}, "prop")' }, + { source: 'объект.аст(1, 1);', expected: 'Object.is(1, 1)' }, + { source: 'объект.васеъшаванда({});', expected: 'Object.isExtensible({})' }, + { source: 'объект.яхшуда({});', expected: 'Object.isFrozen({})' }, + { source: 'объект.мӯҳршуда({});', expected: 'Object.isSealed({})' }, + { source: 'объект.калидҳо({});', expected: 'Object.keys({})' }, + { source: 'объект.манъиВасеъшавӣ({});', expected: 'Object.preventExtensions({})' }, + { source: 'объект.мӯҳр({});', expected: 'Object.seal({})' }, + { source: 'объект.танзимиПрототип({}, {});', expected: 'Object.setPrototypeOf({}, {})' }, + { source: 'объект.қиматҳо({});', expected: 'Object.values({})' }, + ]; + + testCases.forEach(({ source, expected }) => { + const result = compile(source); + expect(result.errors).toHaveLength(0); + expect(result.code).toContain(expected); + }); + }); +}); diff --git a/tests/stdlib-string.test.ts b/tests/stdlib-string.test.ts new file mode 100644 index 0000000..f18a5d6 --- /dev/null +++ b/tests/stdlib-string.test.ts @@ -0,0 +1,58 @@ +import { compile } from '../src/compiler'; + +describe('Standard Library - String Tests', () => { + test('should transpile all string properties and methods correctly', () => { + const testCases = [ + // Properties + { source: 'матн.дарозииСатр;', expected: '.length' }, + + // String Constructor + { source: 'сатр(123);', expected: 'String(123)' }, + + // Static Methods + { source: 'сатр.азКодиАломат(65);', expected: 'String.fromCharCode(65)' }, + { source: 'сатр.азНуқтаиКод(65);', expected: 'String.fromCodePoint(65)' }, + { source: 'сатрМетодҳо.азКодиАломат(65);', expected: 'String.fromCharCode(65)' }, + { source: 'сатрМетодҳо.азНуқтаиКод(65);', expected: 'String.fromCodePoint(65)' }, + + // Instance Methods + { source: 'матн.дар(0);', expected: '.at(0)' }, + { source: 'матн.аломатДар(0);', expected: '.charAt(0)' }, + { source: 'матн.кодиАломатДар(0);', expected: '.charCodeAt(0)' }, + { source: 'матн.нуқтаиКодДар(0);', expected: '.codePointAt(0)' }, + { source: 'матн.пайвастан("!");', expected: '.concat("!")' }, + { source: 'матн.анҷомБо("!");', expected: '.endsWith("!")' }, + { source: 'матн.дорад("e");', expected: '.includes("e")' }, + { source: 'матн.индекси("e");', expected: '.indexOf("e")' }, + { source: 'матн.индексиОхирин("e");', expected: '.lastIndexOf("e")' }, + { source: 'матн.муқоисаиМаҳаллӣ("other");', expected: '.localeCompare("other")' }, + { source: 'матн.муқаррарӣ();', expected: '.normalize()' }, + { source: 'матн.пурКарданОхир(10);', expected: '.padEnd(10)' }, + { source: 'матн.пурКарданАввал(10);', expected: '.padStart(10)' }, + { source: 'матн.такрор(2);', expected: '.repeat(2)' }, + { source: 'матн.ҷойивазкунӣ("t", "T");', expected: '.replace("t", "T")' }, + { source: 'матн.ҷойгузин("t", "T");', expected: '.replace("t", "T")' }, + { source: 'матн.ҷойивазкунӣҲама("t", "T");', expected: '.replaceAll("t", "T")' }, + { source: 'матн.буридан(1);', expected: '.slice(1)' }, + { source: 'матн.ҷудокунӣ(",");', expected: '.split(",")' }, + { source: 'матн.оғозБо("t");', expected: '.startsWith("t")' }, + { source: 'матн.қисмат(1);', expected: '.substring(1)' }, + { source: 'матн.хурдМаҳаллӣ();', expected: '.toLocaleLowerCase()' }, + { source: 'матн.калонМаҳаллӣ();', expected: '.toLocaleUpperCase()' }, + { source: 'матн.хурд();', expected: '.toLowerCase()' }, + { source: 'матн.баСатр();', expected: '.toString()' }, + { source: 'матн.калон();', expected: '.toUpperCase()' }, + { source: 'матн.тозаКардан();', expected: '.trim()' }, + { source: 'матн.тозаКарданОхир();', expected: '.trimEnd()' }, + { source: 'матн.тозаКарданАввал();', expected: '.trimStart()' }, + { source: 'матн.қиматиАслӣ();', expected: '.valueOf()' }, + ]; + + testCases.forEach(({ source, expected }) => { + const fullSource = `тағйирёбанда матн = "test"; ${source}`; + const result = compile(fullSource); + expect(result.errors).toHaveLength(0); + expect(result.code).toContain(expected); + }); + }); +}); From 78893509a8e8f23243dd7a8b21d21187a6c7ce5b Mon Sep 17 00:00:00 2001 From: Bakhtier Gaibulloev Date: Thu, 20 Nov 2025 09:58:44 +0100 Subject: [PATCH 3/9] =?UTF-8?q?docs:=20update=20quick-start=20guide=20to?= =?UTF-8?q?=20use=20short=20keyword=20'=D1=82=D0=B0=D2=93'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace all instances of 'тағйирёбанда' with the shorter 'тағ' keyword throughout the quick-start documentation and related test files. Changes: - docs/reference/quick-start.md: Update all variable declarations - tests/stdlib-array.test.ts: Update test setup code - tests/stdlib-string.test.ts: Update test setup code This aligns the documentation and tests with the new short keyword introduced for improved code brevity. --- docs/reference/quick-start.md | 86 +++++++++++++++++------------------ tests/stdlib-array.test.ts | 2 +- tests/stdlib-string.test.ts | 2 +- 3 files changed, 45 insertions(+), 45 deletions(-) diff --git a/docs/reference/quick-start.md b/docs/reference/quick-start.md index ad5fe0d..d92dc7e 100644 --- a/docs/reference/quick-start.md +++ b/docs/reference/quick-start.md @@ -8,18 +8,18 @@ A comprehensive cheat sheet for SomonScript syntax and common patterns. ```som // Variables (mutable) -тағйирёбанда ном = "Аҳмад"; -тағйирёбанда синну_сол = 25; -тағйирёбанда фаъол = рост; +тағ ном = "Аҳмад"; +тағ синну_сол = 25; +тағ фаъол = рост; // Constants (immutable) собит ПИ = 3.14159; собит МАКС_СИННУ_СОЛ = 120; // With explicit types -тағйирёбанда маълумот: сатр = "Салом"; -тағйирёбанда рақам: рақам = 42; -тағйирёбанда мантиқӣ: мантиқӣ = нодуруст; +тағ маълумот: сатр = "Салом"; +тағ рақам: рақам = 42; +тағ мантиқӣ: мантиқӣ = нодуруст; ``` ### Data Types @@ -61,7 +61,7 @@ A comprehensive cheat sheet for SomonScript syntax and common patterns. } // Arrow functions (anonymous) -тағйирёбанда ҳисоб = (а: рақам, б: рақам): рақам => а * б; +тағ ҳисоб = (а: рақам, б: рақам): рақам => а * б; ``` ### Advanced Functions @@ -74,8 +74,8 @@ A comprehensive cheat sheet for SomonScript syntax and common patterns. // Rest parameters функсия ҷамъи_ҳама(...рақамҳо: рақам[]): рақам { - тағйирёбанда натиҷа = 0; - барои тағйирёбанда рақам аз рақамҳо { + тағ натиҷа = 0; + барои тағ рақам аз рақамҳо { натиҷа += рақам; } бозгашт натиҷа; @@ -97,7 +97,7 @@ A comprehensive cheat sheet for SomonScript syntax and common patterns. } // Ternary operator -тағйирёбанда натиҷа = шарт ? "рост" : "нодуруст"; +тағ натиҷа = шарт ? "рост" : "нодуруст"; // Switch equivalent мувофиқи (қимат) { @@ -116,17 +116,17 @@ A comprehensive cheat sheet for SomonScript syntax and common patterns. ```som // For loop -барои тағйирёбанда и = 0; и < 10; и++ { +барои тағ и = 0; и < 10; и++ { чоп.сабт(и); } // For-in loop (arrays) -барои тағйирёбанда элемент аз массив { +барои тағ элемент аз массив { чоп.сабт(элемент); } // For-in loop (objects) -барои тағйирёбанда калид дар объект { +барои тағ калид дар объект { чоп.сабт(калид + ": " + объект[калид]); } @@ -147,9 +147,9 @@ A comprehensive cheat sheet for SomonScript syntax and common patterns. ```som // Array creation -тағйирёбанда мева = ["себ", "мӯз", "анор"]; -тағйирёбанда рақамҳо = [1, 2, 3, 4, 5]; -тағйирёбанда холӣ: сатр[] = []; +тағ мева = ["себ", "мӯз", "анор"]; +тағ рақамҳо = [1, 2, 3, 4, 5]; +тағ холӣ: сатр[] = []; // Array methods with Tajik names мева.илова("шафтолу"); // push - Илова ба охир @@ -168,15 +168,15 @@ A comprehensive cheat sheet for SomonScript syntax and common patterns. чоп.сабт(`${индекс}: ${элемент}`); }); -тағйирёбанда калонҳо = мева.map(м => м.toUpperCase()); -тағйирёбанда сони_кӯтоҳ = мева.filter(м => м.length < 4); +тағ калонҳо = мева.map(м => м.toUpperCase()); +тағ сони_кӯтоҳ = мева.filter(м => м.length < 4); ``` ### Objects ```som // Object creation -тағйирёбанда корбар = { +тағ корбар = { ном: "Анвар", синну_сол: 30, шаҳр: "Душанбе", @@ -290,8 +290,8 @@ Object.entries(корбар); // Get key-value pairs ### Union Types ```som -тағйирёбанда идентификатор: сатр | рақам = "user123"; -тағйирёбанда статус: "барқарор" | "хомӯш" | "дар_интизор" = "барқарор"; +тағ идентификатор: сатр | рақам = "user123"; +тағ статус: "барқарор" | "хомӯш" | "дар_интизор" = "барқарор"; функсия коркард_кардан(маълумот: сатр | рақам): сатр { агар typeof маълумот === "сатр" { @@ -314,7 +314,7 @@ Object.entries(корбар); // Get key-value pairs сатҳи_дастрасӣ: рақам; } -тағйирёбанда супер_корбар: Корбар & Админ = { +тағ супер_корбар: Корбар & Админ = { ном: "Алӣ", синну_сол: 30, сатҳи_дастрасӣ: 9 @@ -324,11 +324,11 @@ Object.entries(корбар); // Get key-value pairs ### Tuple Types ```som -тағйирёбанда координата: [рақам, рақам] = [41.2, 69.1]; -тағйирёбанда корбар_маълумот: [сатр, рақам, мантиқӣ] = ["Анвар", 25, рост]; +тағ координата: [рақам, рақам] = [41.2, 69.1]; +тағ корбар_маълумот: [сатр, рақам, мантиқӣ] = ["Анвар", 25, рост]; // Named tuple -тағйирёбанда нуқта: [х: рақам, у: рақам, номи_шаҳр: сатр] = [41.2, 69.1, "Душанбе"]; +тағ нуқта: [х: рақам, у: рақам, номи_шаҳр: сатр] = [41.2, 69.1, "Душанбе"]; ``` ## Error Handling @@ -336,7 +336,7 @@ Object.entries(корбар); // Get key-value pairs ```som // Try-catch-finally кӯшиш { - тағйирёбанда натиҷа = хатарнок_амал(); + тағ натиҷа = хатарнок_амал(); чоп.сабт(натиҷа); } гирифтан (хато) { чоп.хато("Хато рух дод:", хато.паём); @@ -411,7 +411,7 @@ Object.entries(корбар); // Get key-value pairs ```som // Promise creation -тағйирёбанда ваъда = нав Promise<сатр>((ҳал_кардан, рад_кардан) => { +тағ ваъда = нав Promise<сатр>((ҳал_кардан, рад_кардан) => { setTimeout(() => { ҳал_кардан("Муваффақият"); }, 1000); @@ -430,8 +430,8 @@ Object.entries(корбар); // Get key-value pairs ```som ҳамзамон функсия маълумот_гирифтан(url: сатр): Promise<сатр> { кӯшиш { - тағйирёбанда ҷавоб = интизор fetch(url); - тағйирёбанда маълумот = интизор ҷавоб.text(); + тағ ҷавоб = интизор fetch(url); + тағ маълумот = интизор ҷавоб.text(); бозгашт маълумот; } гирифтан (хато) { чоп.хато("Хато дар гирифтани маълумот:", хато); @@ -441,7 +441,7 @@ Object.entries(корбар); // Get key-value pairs // Usage ҳамзамон функсия асосӣ() { - тағйирёбанда маълумот = интизор маълумот_гирифтан("https://api.example.com"); + тағ маълумот = интизор маълумот_гирифтан("https://api.example.com"); чоп.сабт(маълумот); } ``` @@ -451,14 +451,14 @@ Object.entries(корбар); // Get key-value pairs ### Basic Template Literals ```som -тағйирёбанда ном = "Аҳмад"; -тағйирёбанда синну = 25; +тағ ном = "Аҳмад"; +тағ синну = 25; // String interpolation -тағйирёбанда паём = `Салом, ${ном}! Шумо ${синну} сола доред.`; +тағ паём = `Салом, ${ном}! Шумо ${синну} сола доред.`; // Multiline strings -тағйирёбанда матни_чандсатра = ` +тағ матни_чандсатра = ` Ин сатри якум Ин сатри дуюм Ин сатри сеюм @@ -469,14 +469,14 @@ Object.entries(корбар); // Get key-value pairs ```som // Expression evaluation -тағйирёбанда ҳисоб = `Натиҷа: ${2 + 3}`; +тағ ҳисоб = `Натиҷа: ${2 + 3}`; // Function calls in templates функсия форматкунии_сана(сана: Date): сатр { бозгашт сана.toLocaleDateString(); } -тағйирёбанда паёми_сана = `Имрӯз: ${форматкунии_сана(нав Date())}`; +тағ паёми_сана = `Имрӯз: ${форматкунии_сана(нав Date())}`; ``` ## Common Operators @@ -572,9 +572,9 @@ Object.entries(корбар); // Get key-value pairs Риёзӣ.поён(4.7); // Math.floor(4.7) = 4 - Гирдкунӣ ба поён // Complex calculations example -тағйирёбанда радиус = 5; -тағйирёбанда майдон = 3.14159 * Риёзӣ.қувват(радиус, 2); -тағйирёбанда аз_1_то_10 = Риёзӣ.поён(Риёзӣ.тасодуфӣ() * 10) + 1; +тағ радиус = 5; +тағ майдон = 3.14159 * Риёзӣ.қувват(радиус, 2); +тағ аз_1_то_10 = Риёзӣ.поён(Риёзӣ.тасодуфӣ() * 10) + 1; ``` ### String Methods @@ -590,7 +590,7 @@ Object.entries(корбар); // Get key-value pairs сатр.пайвастан(" Ҷаҳон"); // string.concat(" World") - Пайваст кардан // Example usage -тағйирёбанда матн = "Салом, Ҷаҳон!"; +тағ матн = "Салом, Ҷаҳон!"; чоп.сабт(матн.дарозӣ); // 13 чоп.сабт(матн.калон()); // САЛОМ, ҶАҲОН! чоп.сабт(матн.хурд()); // салом, ҷаҳон! @@ -603,8 +603,8 @@ Object.entries(корбар); // Get key-value pairs ```som // Variables: camelCase in Tajik -тағйирёбанда номиКорбар = "Анвар"; -тағйирёбанда синнуСолиКорбар = 25; +тағ номиКорбар = "Анвар"; +тағ синнуСолиКорбар = 25; // Constants: UPPER_CASE собит МАКС_АНДОЗА = 100; @@ -645,7 +645,7 @@ Object.entries(корбар); // Get key-value pairs ```som // Always handle potential errors кӯшиш { - тағйирёбанда натиҷа = амали_хатарнок(); + тағ натиҷа = амали_хатарнок(); // Handle success } гирифтан (хато) { // Handle specific error types diff --git a/tests/stdlib-array.test.ts b/tests/stdlib-array.test.ts index d96e894..4463ca3 100644 --- a/tests/stdlib-array.test.ts +++ b/tests/stdlib-array.test.ts @@ -60,7 +60,7 @@ describe('Standard Library - Array Tests', () => { ]; testCases.forEach(({ source, expected }) => { - const fullSource = `тағйирёбанда рӯйхат = [1, 2, 3]; ${source}`; + const fullSource = `тағ рӯйхат = [1, 2, 3]; ${source}`; const result = compile(fullSource); expect(result.errors).toHaveLength(0); expect(result.code).toContain(expected); diff --git a/tests/stdlib-string.test.ts b/tests/stdlib-string.test.ts index f18a5d6..44d5fe5 100644 --- a/tests/stdlib-string.test.ts +++ b/tests/stdlib-string.test.ts @@ -49,7 +49,7 @@ describe('Standard Library - String Tests', () => { ]; testCases.forEach(({ source, expected }) => { - const fullSource = `тағйирёбанда матн = "test"; ${source}`; + const fullSource = `тағ матн = "test"; ${source}`; const result = compile(fullSource); expect(result.errors).toHaveLength(0); expect(result.code).toContain(expected); From 012f2790f74f3fa33c5eb8225796c07b5de6139d Mon Sep 17 00:00:00 2001 From: Bakhtier Gaibulloev Date: Thu, 20 Nov 2025 10:30:12 +0100 Subject: [PATCH 4/9] feat: add camelCase method support and improve arrow function parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for using built-in identifiers and keywords as function parameter names, enabling proper parsing of arrow functions with Tajik method names. Update examples to use new camelCase naming convention. Changes: - parser.ts: Allow built-in identifiers and keywords as parameter names - examples/29-generics.som: Replace ҷудокунӣ with пайвастКардан - examples/35-advanced-backend-patterns.som: Remove unnecessary await keywords --- examples/29-generics.som | 2 +- examples/35-advanced-backend-patterns.som | 10 +- examples/stdlib-camelcase.som | 85 +++++++++ examples/tree.som | 38 ++++ src/parser.ts | 52 ++--- tests/repro_arrow.test.ts | 16 ++ tests/stdlib-comprehensive-example.test.ts | 209 +++++++++++++++++++++ 7 files changed, 385 insertions(+), 27 deletions(-) create mode 100644 examples/stdlib-camelcase.som create mode 100644 examples/tree.som create mode 100644 tests/repro_arrow.test.ts create mode 100644 tests/stdlib-comprehensive-example.test.ts diff --git a/examples/29-generics.som b/examples/29-generics.som index 50ad939..176e91b 100644 --- a/examples/29-generics.som +++ b/examples/29-generics.som @@ -76,7 +76,7 @@ рӯйхати_рақамҳо.илова(12); рӯйхати_рақамҳо.илова(78); рӯйхати_рақамҳо.илова(23); -чоп.сабт("Рақамҳои муратабшуда: " + рӯйхати_рақамҳо.гирифтани_ҳама().ҷудокунӣ(", ")); +чоп.сабт("Рақамҳои муратабшуда: " + рӯйхати_рақамҳо.гирифтани_ҳама().пайвастКардан(", ")); // Generic function with array функсия якумин(массив: T[]): T | беқимат { diff --git a/examples/35-advanced-backend-patterns.som b/examples/35-advanced-backend-patterns.som index d519f3e..2f160c4 100644 --- a/examples/35-advanced-backend-patterns.som +++ b/examples/35-advanced-backend-patterns.som @@ -188,25 +188,25 @@ тағйирёбанда сабткун = нав Сабткун(); чоп.сабт("1. Дарахости аволии GET /api/users:"); -тағйирёбанда натиҷаи_1 = интизор коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.1", "GET", "/api/users"); +тағйирёбанда натиҷаи_1 = коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.1", "GET", "/api/users"); чоп.сабт(натиҷаи_1); чоп.сабт("\n2. Дарахости худо дубора (аз кэш):"); -тағйирёбанда натиҷаи_2 = интизор коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.1", "GET", "/api/users"); +тағйирёбанда натиҷаи_2 = коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.1", "GET", "/api/users"); чоп.сабт(натиҷаи_2); чоп.сабт("\n3. Дарахост аз IP дигар:"); -тағйирёбанда натиҷаи_3 = интизор коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.2", "POST", "/api/users"); +тағйирёбанда натиҷаи_3 = коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.2", "POST", "/api/users"); чоп.сабт(натиҷаи_3); чоп.сабт("\n4. Синҷиши маҳдудсозии суръата (ҳадди: 5):"); барои (тағйирёбанда и = 0; и < 3; и++) { чоп.сабт("Дарахост " + (и + 1) + ":"); - интизор коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.3", "GET", "/api/heavy"); + коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.3", "GET", "/api/heavy"); } чоп.сабт("\n5. Дарахост 4 (бояд маҳдуд шавад):"); -тағйирёбанда натиҷаи_маҳдуд = интизор коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.3", "GET", "/api/heavy"); +тағйирёбанда натиҷаи_маҳдуд = коркарди_дарахост(кэш, маҳдудкунанда, сабткун, "192.168.1.3", "GET", "/api/heavy"); чоп.сабт(натиҷаи_маҳдуд); чоп.сабт("\n=== АНҶОМИ МИСОЛ ==="); diff --git a/examples/stdlib-camelcase.som b/examples/stdlib-camelcase.som new file mode 100644 index 0000000..88afd0a --- /dev/null +++ b/examples/stdlib-camelcase.som @@ -0,0 +1,85 @@ +// Мисоли истифодаи методҳои массив бо навигании camelCase +// Comprehensive Standard Library Example with camelCase naming + +// ======================================== +// Мисоли 1: Кор бо массивҳо (Arrays) +// ======================================== +тағ рақамҳо = [5, 2, 8, 1, 9, 3, 7, 4, 6]; + +// Филтр кардани рақамҳои калон +тағ калонҳо = рақамҳо.филтр(х => х > 5); +чоп.сабт("Рақамҳои калон аз 5:", калонҳо); + +// Ҳисоби квадрат +тағ квадратҳо = рақамҳо.харита(х => х * х); +чоп.сабт("Квадратҳо:", квадратҳо); + +// Ҷамъи ҳамаи рақамҳо +тағ ҷамъ = рақамҳо.ҷамъбаст((а, б) => а + б, 0); +чоп.сабт("Ҷамъи ҳама:", ҷамъ); + +// Тартиб кардан +тағ тартибшуда = рақамҳо.тартиб((а, б) => а - б); +чоп.сабт("Тартибшуда:", тартибшуда); + +// Барои ҳар элемент +чоп.сабт("\nҲама рақамҳо:"); +рақамҳо.бароиҲар((рақам, индекс) => { + чоп.сабт(`Индекс ${индекс}: ${рақам}`); +}); + +// ======================================== +// Мисоли 2: Кор бо сатрҳо (Strings) +// ======================================== +тағ матн = "Салом, Ҷаҳон!"; + +чоп.сабт("\n--- Кор бо сатрҳо ---"); +чоп.сабт("Матни аслӣ:", матн); +чоп.сабт("Дарозӣ:", матн.дарозииСатр); +чоп.сабт("Ба калон:", матн.калон()); +чоп.сабт("Ба хурд:", матн.хурд()); + +// Ҷудокунии калимаҳо +тағ калимаҳо = матн.ҷудокунӣ(", "); +чоп.сабт("Калимаҳо:", калимаҳо); + +// ======================================== +// Мисоли 3: Ҳисобҳои математикӣ (Math) +// ======================================== +чоп.сабт("\n--- Ҳисобҳои математикӣ ---"); + +тағ радиус = 5; +тағ майдони_давра = Риёзӣ.ПИ * Риёзӣ.қувват(радиус, 2); +чоп.сабт(`Майдони давра (радиус=${радиус}):`, майдони_давра); + +тағ решаи16 = Риёзӣ.дуръшака(16); +чоп.сабт("Решаи квадратии 16:", решаи16); + +тағ рақамиТасодуфӣ = Риёзӣ.поён(Риёзӣ.тасодуфӣ() * 10) + 1; +чоп.сабт("Рақами тасодуфӣ (1-10):", рақамиТасодуфӣ); + +тағ гирдшуда = Риёзӣ.дузкунӣ(4.7); +чоп.сабт("Гирдкунии 4.7:", гирдшуда); + +// Ҳадди аксар ва ақал +тағ максимум = Риёзӣ.ҳаддиАксар(3, 7, 2, 9, 1, 5); +тағ минимум = Риёзӣ.ҳаддиАқал(3, 7, 2, 9, 1, 5); +чоп.сабт("Ҳадди аксар:", максимум); +чоп.сабт("Ҳадди ақал:", минимум); + +// ======================================== +// Мисоли 4: Ҳисоби омори +// ======================================== +чоп.сабт("\n--- Ҳисоби омори ---"); + +тағ баҳоҳо = [85, 92, 78, 95, 88, 91, 84]; +тағ миёна = баҳоҳо.ҷамъбаст((а, б) => а + б, 0) / баҳоҳо.дарозӣ; +чоп.сабт("Баҳои миёна:", Риёзӣ.дузкунӣ(миёна * 10) / 10); + +тағ гузашта = баҳоҳо.филтр(б => б >= 80); +чоп.сабт(`Шумораи гузаштагон (≥80): ${гузашта.дарозӣ} аз ${баҳоҳо.дарозӣ}`); + +// ======================================== +// Натиҷа +// ======================================== +чоп.сабт("\n✓ Ҳамаи мисолҳо бомуваффақият иҷро шуданд!"); diff --git a/examples/tree.som b/examples/tree.som new file mode 100644 index 0000000..0fd0886 --- /dev/null +++ b/examples/tree.som @@ -0,0 +1,38 @@ +// ======================================================= +// Author: Munira Gulova +// Date: 2025-11-20 +// ======================================================= + +функсия дарахт(баландӣ: рақам): сатр { + // Барги дарахт + барои (тағ i = 0; i < баландӣ; i++) { + тағ сатр = ""; + + // Фазоҳои чап + барои (тағ j = 0; j < баландӣ - i - 1; j++) { + сатр = сатр + " "; + } + + // Ситораҳо + барои (тағ k = 0; k < 2 * i + 1; k++) { + сатр = сатр + "*"; + } + + чоп.сабт(сатр); + } + + // Танаи дарахт + тағ паҳнои_тана = Риёзӣ.поён(баландӣ / 3); + барои (тағ i = 0; i < баландӣ / 2; i++) { + тағ тана = ""; + барои (тағ j = 0; j < баландӣ - паҳнои_тана - 1; j++) { + тана = тана + " "; + } + барои (тағ k = 0; k < паҳнои_тана * 2 + 1; k++) { + тана = тана + "|"; + } + чоп.сабт(тана); + } +} + +дарахт(10); diff --git a/src/parser.ts b/src/parser.ts index 31dde11..3c2fc2b 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -577,32 +577,42 @@ export class Parser { const params: Parameter[] = []; if (!this.check(TokenType.RIGHT_PAREN)) { do { - if (this.check(TokenType.IDENTIFIER)) { - const token = this.advance(); - const identifier: Identifier = { - type: 'Identifier', - name: token.value, - line: token.line, - column: token.column, - }; - - let paramType: TypeAnnotation | undefined; - if (this.match(TokenType.COLON)) { - paramType = this.typeAnnotation(); - } + let identifierToken: Token; - params.push({ - type: 'Parameter', - name: identifier, - typeAnnotation: paramType, - line: token.line, - column: token.column, - }); + if (this.check(TokenType.IDENTIFIER)) { + identifierToken = this.advance(); + } else if (this.matchBuiltinIdentifier()) { + // matchBuiltinIdentifier advances if true + identifierToken = this.previous(); + } else if ( + this.match(TokenType.НАВЪ, TokenType.МАЪЛУМОТ, TokenType.РӮЙХАТ, TokenType.БЕҚИМАТ) + ) { + identifierToken = this.previous(); } else { - // Not an identifier, so not a simple parameter list + // Not a valid parameter name this.current = savedIndex; return null; } + + const identifier: Identifier = { + type: 'Identifier', + name: identifierToken.value, + line: identifierToken.line, + column: identifierToken.column, + }; + + let paramType: TypeAnnotation | undefined; + if (this.match(TokenType.COLON)) { + paramType = this.typeAnnotation(); + } + + params.push({ + type: 'Parameter', + name: identifier, + typeAnnotation: paramType, + line: identifierToken.line, + column: identifierToken.column, + }); } while (this.match(TokenType.COMMA)); } diff --git a/tests/repro_arrow.test.ts b/tests/repro_arrow.test.ts new file mode 100644 index 0000000..55a79cc --- /dev/null +++ b/tests/repro_arrow.test.ts @@ -0,0 +1,16 @@ +import { compile } from '../src/compiler'; + +describe('Arrow Function Parsing Reproduction', () => { + test('should correctly parse arrow function as method argument', () => { + const source = ` +тағ рақамҳо = [1, 2, 3]; +рақамҳо.бароиҲар((рақам, индекс) => { + чоп.сабт(рақам); +}); +`; + const result = compile(source); + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('.forEach(('); + expect(result.code).toContain('=>'); + }); +}); diff --git a/tests/stdlib-comprehensive-example.test.ts b/tests/stdlib-comprehensive-example.test.ts new file mode 100644 index 0000000..e73c1b3 --- /dev/null +++ b/tests/stdlib-comprehensive-example.test.ts @@ -0,0 +1,209 @@ +import { compile } from '../src/compiler'; + +describe('Comprehensive Standard Library Example', () => { + test('should compile complex example with array methods using camelCase', () => { + const source = ` +// Факториал ҳисобкунӣ +функсия дарахт(баландӣ: рақам): сатр { + тағ сатр = ""; + + // Барои дарахт + барои (тағ і = 0; і < баландӣ; і++) { + тағ сатр = ""; + } + + // Фазохои чап + барои (тағ ҷ = 0; ҷ < баландӣ - 1; ҷ++) { + сатр = сатр + " "; + } + + // Ситорахо + барои (тағ к = 0; к < 2 * і + 1; к++) { + сатр = сатр + "*"; + } + + чоп.сабт(сатр); +} + +// Таҳияи дарахт +тағ пахнон_тана = Риёзӣ.поён(баландӣ / 3); +барои (тағ і = 0; і < баландӣ / 2; і++) { + барои (тағ ҷ = 0; ҷ < баландӣ - пахнон_тана - 1; ҷ++) { + тана = тана + " "; + } + барои (тағ к = 0; к < пахнон_тана * 2 + 1; к++) { + тана = тана + "|"; + } + чоп.сабт(тана); +} + +дарахт(10); +`; + + const result = compile(source); + + // Should compile without errors + expect(result.errors).toHaveLength(0); + + // Should use camelCase methods + expect(result.code).toContain('Math.floor'); + expect(result.code).toContain('console.log'); + }); + + test('should produce correct JavaScript output for camelCase methods', () => { + const source = ` +тағ рақамҳо = [1, 2, 3, 4, 5]; +тағ натиҷа = рақамҳо.харита(х => х * 2); +чоп.сабт(натиҷа); + +тағ матн = "Салом"; +тағ калон = матн.калон(); +чоп.сабт(калон); + +тағ квадрат = Риёзӣ.қувват(3, 2); +чоп.сабт(квадрат); +`; + + const result = compile(source); + + expect(result.errors).toHaveLength(0); + + // Verify exact JS output + const expectedLines = [ + 'let рақамҳо = [1, 2, 3, 4, 5];', + 'let натиҷа = рақамҳо.map((х) => х * 2);', + 'console.log(натиҷа);', + 'let матн = "Салом";', + 'let калон = матн.toUpperCase();', + 'console.log(калон);', + 'let квадрат = Math.pow(3, 2);', + 'console.log(квадрат);', + ]; + + for (const line of expectedLines) { + expect(result.code).toContain(line); + } + + // Ensure тағ is transpiled to let + expect(result.code).toContain('let рақамҳо'); + expect(result.code).toContain('let натиҷа'); + expect(result.code).toContain('let матн'); + expect(result.code).toContain('let калон'); + expect(result.code).toContain('let квадрат'); + + // Ensure camelCase methods are transpiled correctly + expect(result.code).toContain('.map('); + expect(result.code).toContain('.toUpperCase()'); + expect(result.code).toContain('Math.pow('); + expect(result.code).toContain('console.log('); + }); + + test('should compile array manipulation example with camelCase', () => { + const source = ` +// Мисоли истифодаи методҳои массив +тағ рақамҳо = [5, 2, 8, 1, 9, 3, 7, 4, 6]; + +// Истифодаи филтр +тағ калонҳо = рақамҳо.филтр(х => х > 5); +чоп.сабт("Калонҳо:", калонҳо); + +// Истифодаи харита +тағ квадратҳо = рақамҳо.харита(х => х * х); +чоп.сабт("Квадратҳо:", квадратҳо); + +// Истифодаи ҷамъбаст +тағ ҷамъ = рақамҳо.ҷамъбаст((а, б) => а + б, 0); +чоп.сабт("Ҷамъ:", ҷамъ); + +// Истифодаи тартиб +тағ тартибшуда = рақамҳо.тартиб((а, б) => а - б); +чоп.сабт("Тартибшуда:", тартибшуда); + +// Истифодаи бароиҲар +рақамҳо.бароиҲар((рақам, индекс) => { + чоп.сабт(\`Индекс \${индекс}: \${рақам}\`); +}); +`; + + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('.filter'); + expect(result.code).toContain('.map'); + expect(result.code).toContain('.reduce'); + expect(result.code).toContain('.sort'); + expect(result.code).toContain('.forEach'); + }); + + test('should compile string methods example with camelCase', () => { + const source = ` +тағ матн = "Салом, Ҷаҳон!"; + +// Дарозии сатр +тағ дарозӣ = матн.дарозииСатр; +чоп.сабт("Дарозӣ:", дарозӣ); + +// Ба калон +тағ калон = матн.калон(); +чоп.сабт("Калон:", калон); + +// Ба хурд +тағ хурд = матн.хурд(); +чоп.сабт("Хурд:", хурд); + +// Ҷудокунӣ +тағ калимаҳо = матн.ҷудокунӣ(", "); +чоп.сабт("Калимаҳо:", калимаҳо); + + +`; + + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('.length'); + expect(result.code).toContain('.toUpperCase'); + expect(result.code).toContain('.toLowerCase'); + expect(result.code).toContain('.split'); + }); + + test('should compile Math methods example with camelCase', () => { + const source = ` +тағ радиус = 5; + +// Ҳисоби майдон +тағ майдон = Риёзӣ.ПИ * Риёзӣ.қувват(радиус, 2); +чоп.сабт("Майдон:", майдон); + +// Ҳисоби решаи квадратӣ +тағ решаи = Риёзӣ.дуръшака(16); +чоп.сабт("Решаи 16:", решаи); + +// Рақами тасодуфӣ +тағ тасодуфӣ = Риёзӣ.поён(Риёзӣ.тасодуфӣ() * 10) + 1; +чоп.сабт("Рақами тасодуфӣ 1-10:", тасодуфӣ); + +// Гирдкунӣ +тағ гирд = Риёзӣ.дузкунӣ(4.7); +чоп.сабт("Гирдкунӣ 4.7:", гирд); + +// Ҳадди аксар ва ақал +тағ максимум = Риёзӣ.ҳаддиАксар(3, 7, 9); +тағ минимум = Риёзӣ.ҳаддиАқал(3, 7, 9); +чоп.сабт("Ҳадди аксар:", максимум); +чоп.сабт("Ҳадди ақал:", минимум); +`; + + const result = compile(source); + + expect(result.errors).toHaveLength(0); + expect(result.code).toContain('Math.PI'); + expect(result.code).toContain('Math.pow'); + expect(result.code).toContain('Math.sqrt'); + expect(result.code).toContain('Math.floor'); + expect(result.code).toContain('Math.random'); + expect(result.code).toContain('Math.round'); + expect(result.code).toContain('Math.max'); + expect(result.code).toContain('Math.min'); + }); +}); From 265b0b533ad00b215edbc7a983ec329fb5353f98 Mon Sep 17 00:00:00 2001 From: Bakhtier Gaibulloev Date: Thu, 20 Nov 2025 12:59:31 +0100 Subject: [PATCH 5/9] docs: add comprehensive LLM guide for SomonScript language --- examples/test-tag.som | 2 + examples/test.som | 14 ++ llm-guide/01-overview.md | 336 +++++++++++++++++++++++++++++++++++++++ llm-guide/02-keywords.md | 173 ++++++++++++++++++++ llm-guide/03-types.md | 156 ++++++++++++++++++ llm-guide/04-console.md | 147 +++++++++++++++++ llm-guide/05-math.md | 127 +++++++++++++++ llm-guide/06-array.md | 58 +++++++ llm-guide/07-string.md | 57 +++++++ llm-guide/08-object.md | 38 +++++ llm-guide/09-modules.md | 79 +++++++++ llm-guide/10-async.md | 60 +++++++ llm-guide/11-classes.md | 96 +++++++++++ llm-guide/12-examples.md | 161 +++++++++++++++++++ llm-guide/README.md | 186 ++++++++++++++++++++++ 15 files changed, 1690 insertions(+) create mode 100644 examples/test-tag.som create mode 100644 examples/test.som create mode 100644 llm-guide/01-overview.md create mode 100644 llm-guide/02-keywords.md create mode 100644 llm-guide/03-types.md create mode 100644 llm-guide/04-console.md create mode 100644 llm-guide/05-math.md create mode 100644 llm-guide/06-array.md create mode 100644 llm-guide/07-string.md create mode 100644 llm-guide/08-object.md create mode 100644 llm-guide/09-modules.md create mode 100644 llm-guide/10-async.md create mode 100644 llm-guide/11-classes.md create mode 100644 llm-guide/12-examples.md create mode 100644 llm-guide/README.md diff --git a/examples/test-tag.som b/examples/test-tag.som new file mode 100644 index 0000000..0fc0132 --- /dev/null +++ b/examples/test-tag.som @@ -0,0 +1,2 @@ +тағ x = 5; +чоп.сабт(x); diff --git a/examples/test.som b/examples/test.som new file mode 100644 index 0000000..58d22e5 --- /dev/null +++ b/examples/test.som @@ -0,0 +1,14 @@ +чоп.сабт("Рақамро ворид кунед:"); +тағйирёбанда дод = 10; + +функсия Факториал(n: рақам): рақам { + тағйирёбанда факториал = 1; + барои (тағйирёбанда i = 1; i <= n; i++) { + факториал = факториал * i; + } + бозгашт факториал; +} + +тағ натиҷа = Факториал(дод); + +чоп.сабт("натиҷаи " + дод + " != " + натиҷа); \ No newline at end of file diff --git a/llm-guide/01-overview.md b/llm-guide/01-overview.md new file mode 100644 index 0000000..9d30687 --- /dev/null +++ b/llm-guide/01-overview.md @@ -0,0 +1,336 @@ +# Overview + +**SomonScript Language Fundamentals** + +--- + +## What is SomonScript? + +SomonScript is programming language that: + +- Uses **Tajik Cyrillic script** for all syntax +- Compiles to **JavaScript** +- Maintains full JavaScript ecosystem compatibility +- Provides complete type safety and modern features +- Targets Node.js and browser environments + +--- + +## File Structure + +**File Extension**: `.som` + +**Example File Structure**: + +``` +project/ +├── src/ +│ ├── main.som # Entry point +│ ├── utils.som # Utility module +│ └── models/ +│ └── user.som # User model +└── dist/ + └── main.js # Compiled output +``` + +--- + +## Compilation Process + +``` +┌─────────────────┐ +│ Source (.som) │ +└────────┬────────┘ + │ + ▼ +┌─────────────────┐ +│ Lexical │ +│ Analysis │ +└────────┬────────┘ + │ + ▼ +┌─────────────────┐ +│ Syntax │ +│ Analysis (AST) │ +└────────┬────────┘ + │ + ▼ +┌─────────────────┐ +│ Type Checking │ +│ & Validation │ +└────────┬────────┘ + │ + ▼ +┌─────────────────┐ +│ Code │ +│ Generation │ +└────────┬────────┘ + │ + ▼ +┌─────────────────┐ +│ JavaScript │ +│ Output (.js) │ +└─────────────────┘ +``` + +--- + +## Core Principles for LLMs + +### 1. **Deterministic Mapping** + +Every Tajik keyword has exactly one JavaScript equivalent: + +- `тағ` → `let` (always) +- `собит` → `const` (always) +- `функсия` → `function` (always) + +### 2. **Context-Aware Translation** + +Built-in method names only translate when used with built-in objects: + +```som +// Translation occurs - built-in object +тағ рӯйхат = [1, 2, 3]; +тағ дарозӣ = рӯйхат.дарозӣ; // array.length + +// No translation - user object +тағ корбар = { дарозӣ: 180 }; +чоп.сабт(корбар.дарозӣ); // user.дарозӣ (preserved) +``` + +### 3. **Type System Integration** + +Full TypeScript compatibility with Tajik type names: + +```som +функсия ҷамъ(а: рақам, б: рақам): рақам { + бозгашт а + б; +} +// function sum(a: number, b: number): number { return a + b; } +``` + +### 4. **Module System** + +ES6+ imports with automatic file extension handling: + +```som +ворид { ҷамъ } аз "./math"; // import { sum } from "./math.js"; +содир функсия тафриқ(а, б) { ... } // export function subtract(a, b) { ... } +``` + +### 5. **Preserve Semantics** + +Generated JavaScript must be functionally equivalent to the SomonScript source. + +--- + +## Basic Syntax Examples + +### Variables + +```som +тағ ном = "Аҳмад"; // let name = "Ahmad"; +собит МАКС_СИННУ = 100; // const MAX_AGE = 100; +тағ синну: рақам = 25; // let age: number = 25; +``` + +### Functions + +```som +функсия салом(ном: сатр): сатр { + бозгашт "Салом, " + ном; +} +// function hello(name: string): string { +// return "Hello, " + name; +// } +``` + +### Conditionals + +```som +агар (синну >= 18) { + чоп.сабт("Калонсол"); +} вагарна { + чоп.сабт("Хурдсол"); +} +// if (age >= 18) { +// console.log("Adult"); +// } else { +// console.log("Minor"); +// } +``` + +### Loops + +```som +барои (тағ і = 0; і < 10; і++) { + чоп.сабт(і); +} +// for (let i = 0; i < 10; i++) { +// console.log(i); +// } +``` + +### Arrays + +```som +тағ рақамҳо = [1, 2, 3, 4, 5]; +рақамҳо.илова(6); +тағ дугона = рақамҳо.харита(х => х * 2); +// let numbers = [1, 2, 3, 4, 5]; +// numbers.push(6); +// let doubled = numbers.map(x => x * 2); +``` + +### Objects + +```som +тағ корбар = { + ном: "Алӣ", + синну: 30, + шаҳр: "Душанбе" +}; +// let user = { +// name: "Ali", +// age: 30, +// city: "Dushanbe" +// }; +``` + +--- + +## Common Patterns + +### Console Output + +```som +чоп.сабт("Маълумот"); // console.log("Info"); +чоп.хато("Хатогӣ"); // console.error("Error"); +чоп.огоҳӣ("Огоҳӣ"); // console.warn("Warning"); +``` + +### Math Operations + +```som +тағ реша = Риёзӣ.дуръшака(16); // let sqrt = Math.sqrt(16); +тағ қувват = Риёзӣ.қувват(2, 3); // let power = Math.pow(2, 3); +тағ тасодуфӣ = Риёзӣ.тасодуфӣ(); // let random = Math.random(); +``` + +### String Operations + +```som +тағ матн = "салом"; +тағ калон = матн.калон(); // let upper = text.toUpperCase(); +тағ дарозӣ = матн.дарозӣ; // let length = text.length; +``` + +### Array Operations + +```som +тағ рӯйхат = [1, 2, 3]; +тағ филтр = рӯйхат.филтр(х => х > 1); // let filtered = list.filter(x => x > 1); +тағ ҷамъ = рӯйхат.ҷамъбаст((а, б) => а + б, 0); +// let sum = list.reduce((a, b) => a + b, 0); +``` + +--- + +## CLI Usage + +### Compile + +```bash +somon compile app.som # Compile to JavaScript +somon compile app.som -o dist/app.js # Specify output +``` + +### Run + +```bash +somon run app.som # Compile and execute +``` + +### Bundle + +```bash +somon bundle src/main.som -o dist/bundle.js --minify +``` + +### Module Info + +```bash +somon module-info src/main.som --graph --stats +``` + +--- + +## Important Rules for LLMs + +### ✅ DO + +1. **Preserve user-defined names** + + ```som + тағ менингНомам = "Алӣ"; // let менингНомам = "Ali"; (preserved!) + ``` + +2. **Translate keywords consistently** + + ```som + тағ → let (always) + собит → const (always) + ``` + +3. **Apply context-sensitive method translation** + + ```som + рӯйхат.дарозӣ → array.length (built-in) + объект.дарозӣ → object.дарозӣ (user property) + ``` + +4. **Use correct boolean literals** + ```som + дуруст → true + нодуруст → false + ``` + +### ❌ DON'T + +1. **Don't translate user variables** + + ```som + // WRONG: тағ дарозӣ = 180; → let length = 180; + // RIGHT: тағ дарозӣ = 180; → let дарозӣ = 180; + ``` + +2. **Don't use incorrect boolean literals** + + ```som + // WRONG: рост → true + // RIGHT: дуруст → true + ``` + +3. **Don't translate method names outside built-in objects** + + ```som + // WRONG: корбар.сабт() → user.log() + // RIGHT: корбар.сабт() → user.сабт() (preserved!) + ``` + +4. **Don't assume variable context without checking** Always verify if an + identifier is a built-in object before translating methods. + +--- + +## Version Information + +**Current Version**: 0.3.36 +**JavaScript Target**: ES2020+ +**TypeScript Compatibility**: Full +**Node.js Support**: 20.x, 22.x, 23.x, 24.x + +--- + +**Next**: [Keywords Reference](02-keywords.md) diff --git a/llm-guide/02-keywords.md b/llm-guide/02-keywords.md new file mode 100644 index 0000000..586e241 --- /dev/null +++ b/llm-guide/02-keywords.md @@ -0,0 +1,173 @@ +# Keywords Reference + +**Complete Keyword Mappings** + +--- + +## Variables + +| Tajik | JavaScript | Usage | +| ------- | ---------- | ------------------ | +| `тағ` | `let` | Mutable variable | +| `собит` | `const` | Immutable constant | + +```som +тағ ном = "Аҳмад"; // let name = "Ahmad"; +собит ПИ = 3.14159; // const PI = 3.14159; +``` + +--- + +## Control Flow + +| Tajik | JavaScript | Purpose | +| --------------- | ---------- | ---------------- | +| `агар` | `if` | If statement | +| `вагарна` | `else` | Else clause | +| `дар_ҳолати_ки` | `else if` | Else-if | +| `интихоб` | `switch` | Switch statement | +| `вақте` | `case` | Case clause | +| `пешфарз` | `default` | Default case | +| `шикастан` | `break` | Break | +| `давом` | `continue` | Continue | + +--- + +## Loops + +| Tajik | JavaScript | Type | +| ------- | ---------- | ---------- | +| `то` | `while` | While loop | +| `барои` | `for` | For loop | +| `дар` | `in` | For-in | +| `аз` | `of` | For-of | + +```som +то (і < 10) { і++; } // while (i < 10) { i++; } +барои (тағ і = 0; і < 10; і++) { } // for (let i = 0; i < 10; i++) { } +барои (тағ к дар obj) { } // for (let k in obj) { } +барои (тағ в аз arr) { } // for (let v of arr) { } +``` + +--- + +## Functions + +| Tajik | JavaScript | Purpose | +| --------- | ---------- | -------------------- | +| `функсия` | `function` | Function declaration | +| `бозгашт` | `return` | Return statement | + +```som +функсия ҷамъ(а: рақам, б: рақам): рақам { + бозгашт а + б; +} +// function sum(a: number, b: number): number { +// return a + b; +// } +``` + +--- + +## Classes + +| Tajik | JavaScript | Purpose | +| --------------- | ------------- | ----------------- | +| `синф` | `class` | Class declaration | +| `мерос_мебарад` | `extends` | Inheritance | +| `конструктор` | `constructor` | Constructor | +| `ин` | `this` | This reference | +| `супер` | `super` | Super reference | +| `нави` | `new` | Instantiation | + +### Access Modifiers + +| Tajik | JavaScript/TypeScript | +| --------------- | --------------------- | +| `ҷамъиятӣ` | `public` | +| `хосусӣ` | `private` | +| `муҳофизатшуда` | `protected` | +| `статикӣ` | `static` | +| `абстрактӣ` | `abstract` | + +--- + +## Modules + +| Tajik | JavaScript | Purpose | +| ------- | ---------- | ---------------- | +| `ворид` | `import` | Import statement | +| `содир` | `export` | Export statement | +| `чун` | `as` | Alias | + +```som +ворид { ҷамъ } аз "./math"; // import { sum } from "./math.js"; +содир функсия тафриқ() { } // export function subtract() { } +ворид * чун Utils аз "./utils"; // import * as Utils from "./utils.js"; +``` + +--- + +## Async/Await + +| Tajik | JavaScript | Purpose | +| ---------- | ---------- | ---------------- | +| `ҳамзамон` | `async` | Async function | +| `интизор` | `await` | Await expression | +| `Ваъда` | `Promise` | Promise type | + +```som +ҳамзамон функсия getData() { + тағ data = интизор fetch(url); + бозгашт data; +} +// async function getData() { +// let data = await fetch(url); +// return data; +// } +``` + +--- + +## Error Handling + +| Tajik | JavaScript | Purpose | +| ----------- | ---------- | ----------------- | +| `кӯшиш` | `try` | Try block | +| `гирифтан` | `catch` | Catch block | +| `ниҳоят` | `finally` | Finally block | +| `партофтан` | `throw` | Throw statement | +| `Хато` | `Error` | Error constructor | + +```som +кӯшиш { + партофтан нави Хато("Хатогӣ"); +} гирифтан (е) { + чоп.хато(е); +} ниҳоят { + чоп.сабт("Анҷом"); +} +``` + +--- + +## Type System + +| Tajik | TypeScript | Purpose | +| ----------- | ----------- | ---------- | +| `интерфейс` | `interface` | Interface | +| `нав` | `type` | Type alias | +| `номфазо` | `namespace` | Namespace | + +```som +интерфейс Корбар { + ном: сатр; + синну: рақам; +} + +нав Адад = рақам | сатр; +``` + +--- + +**Next**: [Types & Operators](03-types.md) diff --git a/llm-guide/03-types.md b/llm-guide/03-types.md new file mode 100644 index 0000000..f34ab83 --- /dev/null +++ b/llm-guide/03-types.md @@ -0,0 +1,156 @@ +# Types & Operators + +**Type System and Operators** + +--- + +## Basic Types + +| Tajik | TypeScript | Example | +| --------- | ----------- | -------------------------- | +| `рақам` | `number` | `тағ х: рақам = 42;` | +| `сатр` | `string` | `тағ с: сатр = "салом";` | +| `мантиқӣ` | `boolean` | `тағ м: мантиқӣ = дуруст;` | +| `ҳама` | `any` | `тағ а: ҳама = 123;` | +| `холӣ` | `void` | `функсия ф(): холӣ { }` | +| `ҳеҷ` | `null` | `тағ н = ҳеҷ;` | +| `беқимат` | `undefined` | `тағ б = беқимат;` | + +--- + +## Boolean Values + +| Tajik | JavaScript | +| ---------- | ---------- | +| `дуруст` | `true` | +| `нодуруст` | `false` | + +**Important**: Use `дуруст`/`нодуруст`, NOT `рост`! + +--- + +## Complex Types + +### Union Types + +```som +тағ результат: рақам | сатр = 100; +// let result: number | string = 100; +``` + +### Intersection Types + +```som +нав AB = A & B; +// type AB = A & B; +``` + +### Array Types + +```som +тағ рақамҳо: рақам[] = [1, 2, 3]; +// let numbers: number[] = [1, 2, 3]; +``` + +### Tuple Types + +```som +тағ нуқта: [рақам, рақам] = [10, 20]; +// let point: [number, number] = [10, 20]; +``` + +--- + +## Arithmetic Operators + +| Operator | Meaning | Example | +| -------- | -------------- | -------- | +| `+` | Addition | `а + б` | +| `-` | Subtraction | `а - б` | +| `*` | Multiplication | `а * б` | +| `/` | Division | `а / б` | +| `%` | Modulo | `а % б` | +| `**` | Exponentiation | `а ** б` | + +--- + +## Comparison Operators + +| Operator | Meaning | Example | +| -------- | ----------------- | --------- | +| `==` | Equality | `а == б` | +| `!=` | Inequality | `а != б` | +| `===` | Strict equality | `а === б` | +| `!==` | Strict inequality | `а !== б` | +| `<` | Less than | `а < б` | +| `>` | Greater than | `а > б` | +| `<=` | Less or equal | `а <= б` | +| `>=` | Greater or equal | `а >= б` | + +--- + +## Logical Operators + +| Operator | Meaning | Example | +| -------- | ------------------ | ---------- | +| `&&` | AND | `а && б` | +| `\|\|` | OR | `а \|\| б` | +| `!` | NOT | `!а` | +| `??` | Nullish coalescing | `а ?? б` | + +--- + +## Assignment Operators + +| Operator | Meaning | Example | +| -------- | --------------- | --------- | +| `=` | Assignment | `а = б` | +| `+=` | Add assign | `а += б` | +| `-=` | Subtract assign | `а -= б` | +| `*=` | Multiply assign | `а *= б` | +| `/=` | Divide assign | `а /= б` | +| `%=` | Modulo assign | `а %= б` | +| `**=` | Exponent assign | `а **= б` | + +--- + +## Unary Operators + +| Operator | Meaning | Example | +| -------- | ----------- | ----------------- | +| `++` | Increment | `а++` or `++а` | +| `--` | Decrement | `а--` or `--а` | +| `+` | Unary plus | `+а` | +| `-` | Unary minus | `-а` | +| `!` | NOT | `!а` | +| `typeof` | Type of | `typeof а` | +| `delete` | Delete | `delete obj.prop` | + +--- + +## Bitwise Operators + +| Operator | Meaning | +| -------- | -------------------- | +| `&` | Bitwise AND | +| `\|` | Bitwise OR | +| `^` | Bitwise XOR | +| `~` | Bitwise NOT | +| `<<` | Left shift | +| `>>` | Right shift | +| `>>>` | Unsigned right shift | + +--- + +## Special Operators + +| Operator | Purpose | Example | +| -------- | ------------------ | --------------- | +| `?.` | Optional chaining | `obj?.prop` | +| `??` | Nullish coalescing | `а ?? б` | +| `...` | Spread/Rest | `...arr` | +| `? :` | Ternary | `а > б ? а : б` | + +--- + +**Next**: [Console Methods](04-console.md) diff --git a/llm-guide/04-console.md b/llm-guide/04-console.md new file mode 100644 index 0000000..f214d3f --- /dev/null +++ b/llm-guide/04-console.md @@ -0,0 +1,147 @@ +# Console Object (чоп) + +**Console Methods Mapping** + +The `чоп` object maps to JavaScript's `console` object. + +--- + +## Basic Output + +| Tajik | JavaScript | Purpose | +| ---------------- | ----------------- | ----------- | +| `чоп.сабт()` | `console.log()` | Log message | +| `чоп.хато()` | `console.error()` | Log error | +| `чоп.огоҳӣ()` | `console.warn()` | Log warning | +| `чоп.маълумот()` | `console.info()` | Log info | +| `чоп.исфти()` | `console.debug()` | Log debug | + +```som +чоп.сабт("Маълумот"); // console.log("Info"); +чоп.хато("Хатогӣ"); // console.error("Error"); +чоп.огоҳӣ("Огоҳӣ"); // console.warn("Warning"); +``` + +--- + +## Structured Output + +| Tajik | JavaScript | Purpose | +| ------------------ | ------------------ | -------------- | +| `чоп.ҷадвал()` | `console.table()` | Display table | +| `чоп.феҳрист()` | `console.dir()` | Display object | +| `чоп.xmlФеҳрист()` | `console.dirxml()` | Display XML | + +```som +тағ маълумот = [ + { ном: "Алӣ", синну: 25 }, + { ном: "Фотима", синну: 30 } +]; +чоп.ҷадвал(маълумот); +// console.table(data); +``` + +--- + +## Grouping + +| Tajik | JavaScript | Purpose | +| ------------------- | -------------------------- | --------------- | +| `чоп.гуруҳ()` | `console.group()` | Start group | +| `чоп.гуруҳПӯшида()` | `console.groupCollapsed()` | Start collapsed | +| `чоп.гуруҳОхир()` | `console.groupEnd()` | End group | + +```som +чоп.гуруҳ("Корбарон"); +чоп.сабт("Алӣ"); +чоп.сабт("Фотима"); +чоп.гуруҳОхир(); +// console.group("Users"); +// console.log("Ali"); +// console.log("Fatima"); +// console.groupEnd(); +``` + +--- + +## Timing + +| Tajik | JavaScript | Purpose | +| ---------------- | ------------------- | ----------- | +| `чоп.вақт()` | `console.time()` | Start timer | +| `чоп.вақтСабт()` | `console.timeLog()` | Log timer | +| `чоп.вақтОхир()` | `console.timeEnd()` | End timer | + +```som +чоп.вақт("операция"); +// ... код ... +чоп.вақтСабт("операция"); +// ... код ... +чоп.вақтОхир("операция"); +``` + +--- + +## Counting + +| Tajik | JavaScript | Purpose | +| --------------- | ---------------------- | ----------- | +| `чоп.қайд()` | `console.count()` | Count calls | +| `чоп.қайдАсл()` | `console.countReset()` | Reset count | + +```som +функсия test() { + чоп.қайд("функсия даъват"); +} +test(); // функсия даъват: 1 +test(); // функсия даъват: 2 +чоп.қайдАсл("функсия даъват"); +``` + +--- + +## Debugging + +| Tajik | JavaScript | Purpose | +| -------------- | ------------------ | ------------- | +| `чоп.тасдиқ()` | `console.assert()` | Assertion | +| `чоп.пайҷо()` | `console.trace()` | Stack trace | +| `чоп.полиз()` | `console.clear()` | Clear console | + +```som +чоп.тасдиқ(х > 0, "х бояд мусбат бошад"); +// console.assert(x > 0, "x must be positive"); + +чоп.пайҷо(); +// console.trace(); +``` + +--- + +## Complete Method List + +```som +чоп.сабт() // console.log() +чоп.хато() // console.error() +чоп.огоҳӣ() // console.warn() +чоп.маълумот() // console.info() +чоп.исфти() // console.debug() +чоп.ҷадвал() // console.table() +чоп.феҳрист() // console.dir() +чоп.xmlФеҳрист() // console.dirxml() +чоп.гуруҳ() // console.group() +чоп.гуруҳПӯшида() // console.groupCollapsed() +чоп.гуруҳОхир() // console.groupEnd() +чоп.вақт() // console.time() +чоп.вақтСабт() // console.timeLog() +чоп.вақтОхир() // console.timeEnd() +чоп.қайд() // console.count() +чоп.қайдАсл() // console.countReset() +чоп.тасдиқ() // console.assert() +чоп.пайҷо() // console.trace() +чоп.полиз() // console.clear() +``` + +--- + +**Next**: [Math Object](05-math.md) diff --git a/llm-guide/05-math.md b/llm-guide/05-math.md new file mode 100644 index 0000000..750872e --- /dev/null +++ b/llm-guide/05-math.md @@ -0,0 +1,127 @@ +# Math Object (Риёзӣ) + +**Math Methods and Constants** + +The `Риёзӣ` or `математика` object maps to JavaScript's `Math` object. + +--- + +## Constants + +| Tajik | JavaScript | Value | +| --------------- | -------------- | -------- | +| `Риёзӣ.Е` | `Math.E` | ≈2.718 | +| `Риёзӣ.ЛН10` | `Math.LN10` | ln(10) | +| `Риёзӣ.ЛН2` | `Math.LN2` | ln(2) | +| `Риёзӣ.ЛОГ10Е` | `Math.LOG10E` | log₁₀(e) | +| `Риёзӣ.ЛОГ2Е` | `Math.LOG2E` | log₂(e) | +| `Риёзӣ.ПИ` | `Math.PI` | ≈3.14159 | +| `Риёзӣ.РЕША1_2` | `Math.SQRT1_2` | √(1/2) | +| `Риёзӣ.РЕША2` | `Math.SQRT2` | √2 | + +--- + +## Basic Functions + +| Tajik | JavaScript | Purpose | +| --------------------- | -------------- | ---------------- | +| `Риёзӣ.мутлақ()` | `Math.abs()` | Absolute value | +| `Риёзӣ.боло()` | `Math.ceil()` | Round up | +| `Риёзӣ.поён()` | `Math.floor()` | Round down | +| `Риёзӣ.дузкунӣ()` | `Math.round()` | Round nearest | +| `Риёзӣ.бириданАдад()` | `Math.trunc()` | Truncate decimal | +| `Риёзӣ.аломат()` | `Math.sign()` | Sign of number | + +```som +Риёзӣ.мутлақ(-5) // Math.abs(-5) → 5 +Риёзӣ.боло(4.3) // Math.ceil(4.3) → 5 +Риёзӣ.поён(4.7) // Math.floor(4.7) → 4 +Риёзӣ.дузкунӣ(4.5) // Math.round(4.5) → 5 +``` + +--- + +## Power & Root + +| Tajik | JavaScript | Purpose | +| -------------------- | ------------- | ----------- | +| `Риёзӣ.қувват()` | `Math.pow()` | Power (x^y) | +| `Риёзӣ.дуръшака()` | `Math.sqrt()` | Square root | +| `Риёзӣ.решаиКубӣ()` | `Math.cbrt()` | Cube root | +| `Риёзӣ.экспонента()` | `Math.exp()` | e^x | + +```som +Риёзӣ.қувват(2, 3) // Math.pow(2, 3) → 8 +Риёзӣ.дуръшака(16) // Math.sqrt(16) → 4 +Риёзӣ.решаиКубӣ(27) // Math.cbrt(27) → 3 +``` + +--- + +## Logarithms + +| Tajik | JavaScript | Purpose | +| -------------------- | -------------- | ----------- | +| `Риёзӣ.логарифм()` | `Math.log()` | Natural log | +| `Риёзӣ.логарифм10()` | `Math.log10()` | Base-10 log | +| `Риёзӣ.логарифм2()` | `Math.log2()` | Base-2 log | +| `Риёзӣ.логарифм1п()` | `Math.log1p()` | ln(1 + x) | + +--- + +## Trigonometry + +| Tajik | JavaScript | Purpose | +| --------------------- | -------------- | ----------------- | +| `Риёзӣ.синус()` | `Math.sin()` | Sine | +| `Риёзӣ.косинус()` | `Math.cos()` | Cosine | +| `Риёзӣ.тангенс()` | `Math.tan()` | Tangent | +| `Риёзӣ.арксинус()` | `Math.asin()` | Arc sine | +| `Риёзӣ.арккосинус()` | `Math.acos()` | Arc cosine | +| `Риёзӣ.арктангенс()` | `Math.atan()` | Arc tangent | +| `Риёзӣ.арктангенс2()` | `Math.atan2()` | Arc tangent (y/x) | + +--- + +## Hyperbolic Functions + +| Tajik | JavaScript | Purpose | +| ----------------------------- | -------------- | ------------------ | +| `Риёзӣ.синусГиперболӣ()` | `Math.sinh()` | Hyperbolic sine | +| `Риёзӣ.косинусГиперболӣ()` | `Math.cosh()` | Hyperbolic cosine | +| `Риёзӣ.тангенсГиперболӣ()` | `Math.tanh()` | Hyperbolic tangent | +| `Риёзӣ.арксинусГиперболӣ()` | `Math.asinh()` | Inverse sinh | +| `Риёзӣ.арккосинусГиперболӣ()` | `Math.acosh()` | Inverse cosh | +| `Риёзӣ.арктангенсГиперболӣ()` | `Math.atanh()` | Inverse tanh | + +--- + +## Min/Max & Random + +| Tajik | JavaScript | Purpose | +| -------------------- | --------------- | ------------ | +| `Риёзӣ.ҳаддиАксар()` | `Math.max()` | Maximum | +| `Риёзӣ.ҳаддиАқал()` | `Math.min()` | Minimum | +| `Риёзӣ.тасодуфӣ()` | `Math.random()` | Random [0,1) | + +```som +Риёзӣ.ҳаддиАксар(5, 10, 3) // Math.max(5, 10, 3) → 10 +Риёзӣ.ҳаддиАқал(5, 10, 3) // Math.min(5, 10, 3) → 3 +Риёзӣ.тасодуфӣ() // Math.random() → 0.xxx +``` + +--- + +## Special Functions + +| Tajik | JavaScript | Purpose | +| -------------------- | --------------- | --------------------- | +| `Риёзӣ.гипотенуза()` | `Math.hypot()` | Hypotenuse | +| `Риёзӣ.expm1()` | `Math.expm1()` | e^x - 1 | +| `Риёзӣ.clz32()` | `Math.clz32()` | Count leading zeros | +| `Риёзӣ.imul()` | `Math.imul()` | 32-bit multiplication | +| `Риёзӣ.fround()` | `Math.fround()` | Round to float32 | + +--- + +**Next**: [Array Methods](06-array.md) diff --git a/llm-guide/06-array.md b/llm-guide/06-array.md new file mode 100644 index 0000000..4141c08 --- /dev/null +++ b/llm-guide/06-array.md @@ -0,0 +1,58 @@ +# Array Methods (рӯйхат) + +## Core Methods + +| Tajik | JavaScript | +| ---------------------- | ----------------- | +| `дарозӣ` | `length` | +| `дар()` | `at()` | +| `пайвастан()` | `concat()` | +| `воридот()` | `entries()` | +| `ҳама()` | `every()` | +| `пурКардан()` | `fill()` | +| `филтр()` | `filter()` | +| `кофтан()` | `find()` | +| `индексиЁфтан()` | `findIndex()` | +| `охиринЁфтан()` | `findLast()` | +| `индексиОхиринЁфтан()` | `findLastIndex()` | +| `ҳамвор()` | `flat()` | +| `ҳамворХарита()` | `flatMap()` | +| `бароиҲар()` | `forEach()` | +| `дорад()` | `includes()` | +| `индекси()` | `indexOf()` | +| `пайвастКардан()` | `join()` | +| `калидҳо()` | `keys()` | +| `индексиОхирин()` | `lastIndexOf()` | +| `харита()` | `map()` | +| `баровардан()` | `pop()` | +| `илова()` | `push()` | +| `пуш()` | `push()` | +| `ҷамъбаст()` | `reduce()` | +| `ҷамъбастАзРост()` | `reduceRight()` | +| `баргардон()` | `reverse()` | +| `ҳазфиАввал()` | `shift()` | +| `буридан()` | `slice()` | +| `баъзе()` | `some()` | +| `тартиб()` | `sort()` | +| `пайваст()` | `splice()` | +| `баСатр()` | `toString()` | +| `иловаБаАввал()` | `unshift()` | +| `қиматҳо()` | `values()` | +| `бо()` | `with()` | + +## Static Methods + +| Tajik | JavaScript | +| ----------------------- | ----------------- | +| `рӯйхат.аз()` | `Array.from()` | +| `рӯйхат.рӯйхатАст()` | `Array.isArray()` | +| `рӯйхат.азАргументҳо()` | `Array.of()` | + +## Examples + +```som +тағ р = [1, 2, 3]; +р.илова(4); // push(4) +тағ дугона = р.харита(х => х * 2); // map +тағ филтр = р.филтр(х => х > 1); // filter +``` diff --git a/llm-guide/07-string.md b/llm-guide/07-string.md new file mode 100644 index 0000000..885440b --- /dev/null +++ b/llm-guide/07-string.md @@ -0,0 +1,57 @@ +# String Methods (сатр) + +## Core Methods + +| Tajik | JavaScript | +| ------------------- | --------------------- | +| `дарозӣ` | `length` | +| `дар()` | `at()` | +| `аломатДар()` | `charAt()` | +| `кодиАломатДар()` | `charCodeAt()` | +| `нуқтаиКодДар()` | `codePointAt()` | +| `пайвастан()` | `concat()` | +| `анҷомБо()` | `endsWith()` | +| `дорад()` | `includes()` | +| `индекси()` | `indexOf()` | +| `индексиОхирин()` | `lastIndexOf()` | +| `муқоисаиМаҳаллӣ()` | `localeCompare()` | +| `мувофиқат()` | `match()` | +| `мувофиқатҲама()` | `matchAll()` | +| `муқаррарӣ()` | `normalize()` | +| `пурКарданОхир()` | `padEnd()` | +| `пурКарданАввал()` | `padStart()` | +| `такрор()` | `repeat()` | +| `ҷойивазкунӣ()` | `replace()` | +| `ҷойгузин()` | `replace()` | +| `ҷойивазкунӣҲама()` | `replaceAll()` | +| `ҷустуҷӯ()` | `search()` | +| `буридан()` | `slice()` | +| `ҷудокунӣ()` | `split()` | +| `оғозБо()` | `startsWith()` | +| `қисмат()` | `substring()` | +| `хурдМаҳаллӣ()` | `toLocaleLowerCase()` | +| `калонМаҳаллӣ()` | `toLocaleUpperCase()` | +| `хурд()` | `toLowerCase()` | +| `калон()` | `toUpperCase()` | +| `баСатр()` | `toString()` | +| `тозаКардан()` | `trim()` | +| `тозаКарданОхир()` | `trimEnd()` | +| `тозаКарданАввал()` | `trimStart()` | +| `қиматиАслӣ()` | `valueOf()` | + +## Static Methods + +| Tajik | JavaScript | +| --------------------- | ------------------------ | +| `сатр.азКодиАломат()` | `String.fromCharCode()` | +| `сатр.азНуқтаиКод()` | `String.fromCodePoint()` | +| `сатр.хоми()` | `String.raw()` | + +## Examples + +```som +тағ матн = "салом"; +тағ калон = матн.калон(); // "САЛОМ" +тағ дарозӣ = матн.дарозӣ; // 5 +тағ қисм = матн.қисмат(0, 3); // "сал" +``` diff --git a/llm-guide/08-object.md b/llm-guide/08-object.md new file mode 100644 index 0000000..ae2d29a --- /dev/null +++ b/llm-guide/08-object.md @@ -0,0 +1,38 @@ +# Object Methods (объект) + +## Static Methods + +| Tajik | JavaScript | +| -------------------------- | ------------------------------------ | +| `объект.таъин()` | `Object.assign()` | +| `объект.сохтан()` | `Object.create()` | +| `объект.муайянХосиятҳо()` | `Object.defineProperties()` | +| `объект.муайянХосият()` | `Object.defineProperty()` | +| `объект.воридот()` | `Object.entries()` | +| `объект.яхКардан()` | `Object.freeze()` | +| `объект.азВоридот()` | `Object.fromEntries()` | +| `объект.тавсифиХосият()` | `Object.getOwnPropertyDescriptor()` | +| `объект.тавсифиХосиятҳо()` | `Object.getOwnPropertyDescriptors()` | +| `объект.номҳоиХосият()` | `Object.getOwnPropertyNames()` | +| `объект.рамзҳоиХосият()` | `Object.getOwnPropertySymbols()` | +| `объект.прототип()` | `Object.getPrototypeOf()` | +| `объект.гурӯҳбандӣ()` | `Object.groupBy()` | +| `объект.дорадХосият()` | `Object.hasOwn()` | +| `объект.аст()` | `Object.is()` | +| `объект.васеъшаванда()` | `Object.isExtensible()` | +| `объект.яхшуда()` | `Object.isFrozen()` | +| `объект.мӯҳршуда()` | `Object.isSealed()` | +| `объект.калидҳо()` | `Object.keys()` | +| `объект.манъиВасеъшавӣ()` | `Object.preventExtensions()` | +| `объект.мӯҳр()` | `Object.seal()` | +| `объект.танзимиПрототип()` | `Object.setPrototypeOf()` | +| `объект.қиматҳо()` | `Object.values()` | + +## Examples + +```som +тағ obj = { ном: "Алӣ", синну: 25 }; +тағ калидҳо = объект.калидҳо(obj); // ["ном", "синну"] +тағ қиматҳо = объект.қиматҳо(obj); // ["Алӣ", 25] +тағ воридот = объект.воридот(obj); // [["ном", "Алӣ"], ["синну", 25]] +``` diff --git a/llm-guide/09-modules.md b/llm-guide/09-modules.md new file mode 100644 index 0000000..c63d6f9 --- /dev/null +++ b/llm-guide/09-modules.md @@ -0,0 +1,79 @@ +# Module System + +## Import Syntax + +### Named Import + +```som +ворид { ҷамъ, тафриқ } аз "./math"; +// import { sum, subtract } from "./math.js"; +``` + +### Default Import + +```som +ворид ҳисобкунак аз "./calculator"; +// import calculator from "./calculator.js"; +``` + +### Namespace Import + +```som +ворид * чун MathUtils аз "./math"; +// import * as MathUtils from "./math.js"; +``` + +### Mixed Import + +```som +ворид ҳисобкунак, { ҷамъ } аз "./math"; +// import calculator, { sum } from "./math.js"; +``` + +## Export Syntax + +### Named Export + +```som +содир функсия ҷамъ(а, б) { + бозгашт а + б; +} +// export function sum(a, b) { return a + b; } +``` + +### Default Export + +```som +содир пешфарз функсия ҳисобкунак() { } +// export default function calculator() { } +``` + +### Export List + +```som +содир { ҷамъ, тафриқ }; +// export { sum, subtract }; +``` + +### Re-export + +```som +содир { ҷамъ } аз "./operations"; +// export { sum } from "./operations.js"; +``` + +### Re-export All + +```som +содир * аз "./operations"; +// export * from "./operations.js"; +``` + +## File Extension Handling + +**Automatic**: `.som` → `.js` during compilation + +```som +ворид { func } аз "./module.som"; // Resolves to ./module.js +ворид { func } аз "./module"; // Resolves to ./module.js +``` diff --git a/llm-guide/10-async.md b/llm-guide/10-async.md new file mode 100644 index 0000000..1095dd2 --- /dev/null +++ b/llm-guide/10-async.md @@ -0,0 +1,60 @@ +# Async/Await & Promises + +## Async Functions + +```som +ҳамзамон функсия маълумотГирифтан(url: сатр): Ваъда<сатр> { + тағ ҷавоб = интизор fetch(url); + тағ матн = интизор ҷавоб.text(); + бозгашт матн; +} +// async function fetchData(url: string): Promise { +// let response = await fetch(url); +// let text = await response.text(); +// return text; +// } +``` + +## Promise Methods + +| Tajik | JavaScript | +| ----------------------- | ---------------------- | +| `Ваъда.ҳама()` | `Promise.all()` | +| `Ваъда.ҳамаҲалшуда()` | `Promise.allSettled()` | +| `Ваъда.ҳама гонаҷамъ()` | `Promise.any()` | +| `Ваъда.мусобиқа()` | `Promise.race()` | +| `Ваъда.рад()` | `Promise.reject()` | +| `Ваъда.ҳал()` | `Promise.resolve()` | + +## Promise Instance Methods + +```som +тағ ваъда = fetch(url); +ваъда.гирифтан(хато => чоп.хато(хато)); +ваъда.ниҳоят(() => чоп.сабт("Анҷом")); +// promise.catch(error => console.error(error)); +// promise.finally(() => console.log("Done")); +``` + +## Async Error Handling + +```som +ҳамзамон функсия loadData() { + кӯшиш { + тағ data = интизор fetch(url); + бозгашт data; + } гирифтан (хато) { + чоп.хато("Хатогӣ:", хато); + партофтан хато; + } +} +``` + +## Keywords + +| Tajik | JavaScript | +| ---------- | --------------------- | +| `ҳамзамон` | `async` | +| `интизор` | `await` | +| `Ваъда` | `Promise` | +| `ваъда` | `Promise` (lowercase) | diff --git a/llm-guide/11-classes.md b/llm-guide/11-classes.md new file mode 100644 index 0000000..02f96c4 --- /dev/null +++ b/llm-guide/11-classes.md @@ -0,0 +1,96 @@ +# Classes & OOP + +## Basic Class + +```som +синф Ҳайвон { + хосусӣ ном: сатр; + + конструктор(ном: сатр) { + ин.ном = ном; + } + + ҷамъиятӣ садо(): сатр { + бозгашт "Садо"; + } +} +``` + +## Inheritance + +```som +синф Саг мерос_мебарад Ҳайвон { + конструктор(ном: сатр) { + супер(ном); + } + + ҷамъиятӣ садо(): сатр { + бозгашт "Вақ-вақ!"; + } +} + +тағ саг = нави Саг("Рекс"); +``` + +## Access Modifiers + +| Tajik | TypeScript | JavaScript | +| --------------- | ----------- | ----------------- | +| `ҷамъиятӣ` | `public` | (default) | +| `хосусӣ` | `private` | `#private` | +| `муҳофизатшуда` | `protected` | (TypeScript only) | + +## Static Members + +```som +синф Математика { + статикӣ ПИ: рақам = 3.14159; + + статикӣ ҷамъ(а: рақам, б: рақам): рақам { + бозгашт а + б; + } +} + +тағ натиҷа = Математика.ҷамъ(5, 3); +``` + +## Abstract Classes (TypeScript) + +```som +абстрактӣ синф Шакл { + абстрактӣ масоҳат(): рақам; + + тавсиф(): сатр { + бозгашт "Шакл"; + } +} + +синф Доира мерос_мебарад Шакл { + хосусӣ радиус: рақам; + + конструктор(р: рақам) { + супер(); + ин.радиус = р; + } + + масоҳат(): рақам { + бозгашт Риёзӣ.ПИ * ин.радиус ** 2; + } +} +``` + +## Getters & Setters + +```som +синф Корбар { + хосусӣ _ном: сатр; + + get ном(): сатр { + бозгашт ин._ном; + } + + set ном(қимат: сатр) { + ин._ном = қимат; + } +} +``` diff --git a/llm-guide/12-examples.md b/llm-guide/12-examples.md new file mode 100644 index 0000000..8cbc795 --- /dev/null +++ b/llm-guide/12-examples.md @@ -0,0 +1,161 @@ +# Common Examples + +## Hello World + +```som +чоп.сабт("Салом, Ҷаҳон!"); +// console.log("Hello, World!"); +``` + +## Variables & Types + +```som +тағ ном: сатр = "Аҳмад"; +собит МАКС_СИННУ: рақам = 100; +тағ фаъол: мантиқӣ = дуруст; +тағ қимат: рақам | сатр = 42; +``` + +## Functions + +```som +функсия ҷамъ(а: рақам, б: рақам): рақам { + бозгашт а + б; +} + +тағ зарб = (а: рақам, б: рақам): рақам => а * б; +``` + +## Conditionals + +```som +агар (синну < 13) { + чоп.сабт("Кӯдак"); +} дар_ҳолати_ки (синну < 18) { + чоп.сабт("Наврасон"); +} вагарна { + чоп.сабт("Калонсол"); +} +``` + +## Loops + +```som +// For loop +барои (тағ і = 0; і < 10; і++) { + чоп.сабт(і); +} + +// For-of loop +барои (тағ қимат аз рӯйхат) { + чоп.сабт(қимат); +} + +// While loop +то (і > 0) { + і--; +} +``` + +## Arrays + +```som +тағ рақамҳо = [1, 2, 3, 4, 5]; +рақамҳо.илова(6); +тағ дугона = рақамҳо.харита(х => х * 2); +тағ ҷуфт = рақамҳо.филтр(х => х % 2 === 0); +тағ ҷамъ = рақамҳо.ҷамъбаст((а, б) => а + б, 0); +``` + +## Objects + +```som +тағ корбар = { + ном: "Алӣ", + синну: 30, + шаҳр: "Душанбе" +}; + +чоп.сабт(корбар.ном); +тағ калидҳо = объект.калидҳо(корбар); +``` + +## Classes + +```som +синф Корбар { + хосусӣ ном: сатр; + хосусӣ синну: рақам; + + конструктор(ном: сатр, синну: рақам) { + ин.ном = ном; + ин.синну = синну; + } + + ҷамъиятӣ таърихӣ(): сатр { + бозгашт `${ин.ном}, ${ин.синну} сола`; + } +} + +тағ корбар = нави Корбар("Алӣ", 30); +чоп.сабт(корбар.таърихӣ()); +``` + +## Async/Await + +```som +ҳамзамон функсия маълумотГирифтан(url: сатр) { + кӯшиш { + тағ ҷавоб = интизор fetch(url); + тағ дата = интизор ҷавоб.json(); + бозгашт дата; + } гирифтан (хато) { + чоп.хато("Хатогӣ:", хато); + партофтан хато; + } +} +``` + +## Modules + +```som +// math.som +содир функсия ҷамъ(а: рақам, б: рақам): рақам { + бозгашт а + б; +} + +содир собит ПИ: рақам = 3.14159; + +// main.som +ворид { ҷамъ, ПИ } аз "./math"; +чоп.сабт(ҷамъ(5, 3)); +чоп.сабт(ПИ); +``` + +## Error Handling + +```som +функсия тақсим(а: рақам, б: рақам): рақам { + агар (б === 0) { + партофтан нави Хато("Тақсим ба сифр"); + } + бозгашт а / б; +} + +кӯшиш { + тағ натиҷа = тақсим(10, 0); +} гирифтан (хато) { + чоп.хато("Хатогӣ:", хато); +} ниҳоят { + чоп.сабт("Анҷом"); +} +``` + +## Template Literals + +```som +тағ ном = "Аҳмад"; +тағ синну = 25; +тағ паём = `Салом, ${ном}! Шумо ${синну} сола доред.`; +чоп.сабт(паём); +``` diff --git a/llm-guide/README.md b/llm-guide/README.md new file mode 100644 index 0000000..3d039e3 --- /dev/null +++ b/llm-guide/README.md @@ -0,0 +1,186 @@ +# SomonScript LLM Guide + +**Comprehensive Reference for Language Models** + +This guide provides complete documentation for LLMs working with SomonScript, a +programming language that uses Tajik Cyrillic syntax and compiles to JavaScript. + +--- + +## 📚 Guide Structure + +### Core Language + +- **[01-overview.md](01-overview.md)** - Introduction, principles, and quick + start +- **[02-keywords.md](02-keywords.md)** - All language keywords and their + mappings +- **[03-types.md](03-types.md)** - Type system, operators, and special values + +### Built-in Objects + +- **[04-console.md](04-console.md)** - Console object (чоп) methods +- **[05-math.md](05-math.md)** - Math object (Риёзӣ) methods +- **[06-array.md](06-array.md)** - Array object (рӯйхат) methods +- **[07-string.md](07-string.md)** - String object (сатр) methods +- **[08-object.md](08-object.md)** - Object methods + +### Advanced Features + +- **[09-modules.md](09-modules.md)** - Module system (import/export) +- **[10-async.md](10-async.md)** - Async/await and promises +- **[11-classes.md](11-classes.md)** - Object-oriented programming +- **[12-examples.md](12-examples.md)** - Common patterns and examples + +--- + +## 🚀 Quick Reference + +**File Extension**: `.som` +**Compilation**: SomonScript → JavaScript → Node.js/Browser + +### Essential Mappings + +```som +// Variables +тағ x = 10; // let x = 10; +собит ПИ = 3.14; // const PI = 3.14; + +// Functions +функсия ҷамъ(а, б) { // function sum(a, b) { + бозгашт а + б; // return a + b; +} // } + +// Console +чоп.сабт("Салом"); // console.log("Hello"); + +// Conditionals +агар (х > 0) { // if (x > 0) { + // ... +} вагарна { // } else { + // ... +} // } + +// Loops +барои (тағ і = 0; і < 10; і++) { // for (let i = 0; i < 10; i++) { + чоп.сабт(і); // console.log(i); +} // } + +// Classes +синф Корбар { // class User { + конструктор(ном) { // constructor(name) { + ин.ном = ном; // this.name = name; + } // } +} // } +``` + +--- + +## 🎯 Key Principles for LLMs + +### 1. One-to-One Keyword Mapping + +Each Tajik keyword maps to exactly one JavaScript/TypeScript construct. + +### 2. Context-Sensitive Method Translation + +Built-in method names only translate when accessing built-in objects: + +- `рӯйхат.дарозӣ` → `array.length` ✅ +- `корбар.дарозӣ` → `user.дарозӣ` ✅ (user property, not translated) + +### 3. Type Safety + +Full TypeScript-compatible type system with interfaces, generics, and type +inference. + +### 4. Module System + +ES6+ import/export with automatic `.som` → `.js` extension handling. + +### 5. Boolean Literals + +- ✅ `дуруст` → `true` +- ✅ `нодуруст` → `false` +- ❌ NOT `рост` (this is incorrect!) + +--- + +## 📖 How to Use This Guide + +### For Code Generation + +1. Read [01-overview.md](01-overview.md) for basic principles +2. Reference [02-keywords.md](02-keywords.md) for syntax mappings +3. Check specific built-in object files (04-08) for API translations +4. Review [12-examples.md](12-examples.md) for common patterns + +### For Code Understanding + +1. Use keyword mappings to translate Tajik → JavaScript +2. Recognize built-in objects (чоп, Риёзӣ, рӯйхат, сатр, объект) +3. Apply context-sensitive translation rules +4. Preserve user-defined variable/method names + +### For Code Translation + +1. **JavaScript → SomonScript**: Use reverse mappings from keyword tables +2. **SomonScript → JavaScript**: Follow mappings exactly as specified +3. **Preserve semantics**: Ensure functional equivalence after translation + +--- + +## 🔍 Quick Lookup + +### Most Common Mappings + +| Category | Tajik | JavaScript | +| -------- | ---------- | ---------- | +| Variable | `тағ` | `let` | +| Constant | `собит` | `const` | +| Function | `функсия` | `function` | +| Return | `бозгашт` | `return` | +| If | `агар` | `if` | +| Else | `вагарна` | `else` | +| For | `барои` | `for` | +| While | `то` | `while` | +| Class | `синф` | `class` | +| This | `ин` | `this` | +| Import | `ворид` | `import` | +| Export | `содир` | `export` | +| Async | `ҳамзамон` | `async` | +| Await | `интизор` | `await` | +| True | `дуруст` | `true` | +| False | `нодуруст` | `false` | +| Console | `чоп` | `console` | +| Math | `Риёзӣ` | `Math` | + +--- + +## 💡 Important Notes + +1. **Preserve User Names**: Don't translate user-defined variable, function, or + class names +2. **Context Matters**: Method names only translate on built-in objects +3. **Type Annotations**: Use Tajik type names in type positions (рақам, сатр, + мантиқӣ) +4. **File Extensions**: `.som` files compile to `.js` with automatic module + resolution +5. **Interoperability**: Generated JavaScript is fully compatible with existing + JS/TS code + +--- + +## 📝 Contributing + +When adding new mappings or features: + +1. Update the appropriate section file (01-12) +2. Add examples to [12-examples.md](12-examples.md) +3. Keep tables formatted for easy parsing by LLMs +4. Include both Tajik → JavaScript and reverse mappings + +--- + +**Last Updated**: Based on SomonScript v0.3.36 +**Source**: [src/codegen.ts](../src/codegen.ts) From 6480233606a251dff4273f52823ddececcfc2564 Mon Sep 17 00:00:00 2001 From: Bakhtier Gaibulloev Date: Thu, 20 Nov 2025 12:59:44 +0100 Subject: [PATCH 6/9] feat: add underscore variant support for Tajik method names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support for underscore-separated variants of camelCase method names to maintain backward compatibility (e.g., 'гуруҳ_охир' alongside 'гуруҳОхир', 'вақт_сабт' alongside 'вақтСабт'). Changes: - codegen.ts: Add underscore variants to builtin mappings for console methods (гуруҳ_охир, гуруҳ_пӯшида, вақт_охир, вақт_сабт, қайд_асл, xml_феҳрист) and string methods (сатр_ --- src/codegen.ts | 36 +++++++++- src/parser.ts | 8 +++ tests/underscore-variants.test.ts | 112 ++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+), 2 deletions(-) create mode 100644 tests/underscore-variants.test.ts diff --git a/src/codegen.ts b/src/codegen.ts index 10f4e5c..3635557 100644 --- a/src/codegen.ts +++ b/src/codegen.ts @@ -67,16 +67,22 @@ export class CodeGenerator { ['ҷадвал', 'table'], ['гуруҳ', 'group'], ['гуруҳОхир', 'groupEnd'], + ['гуруҳ_охир', 'groupEnd'], // Underscore variant ['гуруҳПӯшида', 'groupCollapsed'], + ['гуруҳ_пӯшида', 'groupCollapsed'], // Underscore variant ['вақт', 'time'], ['вақтОхир', 'timeEnd'], + ['вақт_охир', 'timeEnd'], // Underscore variant ['вақтСабт', 'timeLog'], + ['вақт_сабт', 'timeLog'], // Underscore variant ['қайд', 'count'], ['қайдАсл', 'countReset'], + ['қайд_асл', 'countReset'], // Underscore variant ['тасдиқ', 'assert'], ['полиз', 'clear'], ['феҳрист', 'dir'], ['xmlФеҳрист', 'dirxml'], + ['xml_феҳрист', 'dirxml'], // Underscore variant ['пайҷо', 'trace'], // Error handling @@ -131,7 +137,9 @@ export class CodeGenerator { // String methods ['сатр', 'String'], // String type/constructor ['сатрМетодҳо', 'String'], // String methods object + ['сатр_методҳо', 'String'], // Underscore variant ['дарозииСатр', 'length'], + ['дарозии_сатр', 'length'], // Underscore variant ['дар', 'at'], ['аломатДар', 'charAt'], ['кодиАломатДар', 'charCodeAt'], @@ -910,7 +918,15 @@ export class CodeGenerator { } // Map built-in constructors/objects (when used as identifiers) - const builtinConstructors = ['сатр', 'рӯйхат', 'объект', 'математика', 'Риёзӣ']; + const builtinConstructors = [ + 'сатр', + 'рӯйхат', + 'объект', + 'математика', + 'Риёзӣ', + 'сатрМетодҳо', + 'сатр_методҳо', // Underscore variant + ]; if (builtinConstructors.includes(node.name)) { const mapped = this.builtinMappings.get(node.name); if (mapped) { @@ -1027,7 +1043,15 @@ export class CodeGenerator { } const objectName = (node.object as Identifier).name; - const builtinObjects = ['чоп', 'математика', 'объект', 'Риёзӣ', 'сатр', 'сатрМетодҳо']; + const builtinObjects = [ + 'чоп', + 'математика', + 'объект', + 'Риёзӣ', + 'сатр', + 'сатрМетодҳо', + 'сатр_методҳо', // Underscore variant + ]; if (!builtinObjects.includes(objectName)) { return { mapped: object, wasMapped: false }; @@ -1067,6 +1091,13 @@ export class CodeGenerator { } const commonMethods = [ + // Console methods (underscore variants) + 'гуруҳ_охир', + 'гуруҳ_пӯшида', + 'вақт_сабт', + 'вақт_охир', + 'қайд_асл', + 'xml_феҳрист', // Array methods 'дарозӣ', 'дар', @@ -1113,6 +1144,7 @@ export class CodeGenerator { 'бо', // String methods 'дарозииСатр', + 'дарозии_сатр', // Underscore variant 'аломатДар', 'кодиАломатДар', 'нуқтаиКодДар', diff --git a/src/parser.ts b/src/parser.ts index 3c2fc2b..dbe1e57 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -1852,6 +1852,14 @@ export class Parser { TokenType.ФИЛТР, TokenType.КОФТАН, TokenType.ГИРИФТАН, // Allow 'гирифтан' as identifier (common method name) + // Console method underscore variants + TokenType.ГУРУҲ_ОХИР, + TokenType.ГУРУҲ_ПӮШИДА, + TokenType.ВАҚТ_САБТ, + TokenType.ВАҚТ_ОХИР, + TokenType.ҚАЙД_АСЛ, + TokenType.XML_ФЕҲРИСТ, + // String methods TokenType.САТР_МЕТОДҲО, TokenType.ДАРОЗИИ_САТР, TokenType.ПАЙВАСТАН, diff --git a/tests/underscore-variants.test.ts b/tests/underscore-variants.test.ts new file mode 100644 index 0000000..92a8662 --- /dev/null +++ b/tests/underscore-variants.test.ts @@ -0,0 +1,112 @@ +import { Lexer } from '../src/lexer'; +import { Parser } from '../src/parser'; +import { CodeGenerator } from '../src/codegen'; + +describe('Underscore variant mappings', () => { + function compileCode(source: string): string { + const lexer = new Lexer(source); + const tokens = lexer.tokenize(); + const parser = new Parser(tokens); + const ast = parser.parse(); + const codegen = new CodeGenerator(); + return codegen.generate(ast); + } + + describe('Console method underscore variants', () => { + it('should map гуруҳ_охир to console.groupEnd', () => { + const code = 'чоп.гуруҳ_охир();'; + const result = compileCode(code); + expect(result).toContain('console.groupEnd()'); + expect(result).not.toContain('гуруҳ_охир'); + }); + + it('should map гуруҳ_пӯшида to console.groupCollapsed', () => { + const code = 'чоп.гуруҳ_пӯшида("test");'; + const result = compileCode(code); + expect(result).toContain('console.groupCollapsed'); + expect(result).not.toContain('гуруҳ_пӯшида'); + }); + + it('should map вақт_сабт to console.timeLog', () => { + const code = 'чоп.вақт_сабт("timer");'; + const result = compileCode(code); + expect(result).toContain('console.timeLog'); + expect(result).not.toContain('вақт_сабт'); + }); + + it('should map вақт_охир to console.timeEnd', () => { + const code = 'чоп.вақт_охир("timer");'; + const result = compileCode(code); + expect(result).toContain('console.timeEnd'); + expect(result).not.toContain('вақт_охир'); + }); + + it('should map қайд_асл to console.countReset', () => { + const code = 'чоп.қайд_асл("counter");'; + const result = compileCode(code); + expect(result).toContain('console.countReset'); + expect(result).not.toContain('қайд_асл'); + }); + + it('should map xml_феҳрист to console.dirxml', () => { + const code = 'чоп.xml_феҳрист(obj);'; + const result = compileCode(code); + expect(result).toContain('console.dirxml'); + expect(result).not.toContain('xml_феҳрист'); + }); + }); + + describe('String helper underscore variants', () => { + it('should map сатр_методҳо to String', () => { + const code = 'тағйирёбанда s = сатр_методҳо;'; + const result = compileCode(code); + expect(result).toContain('String'); + expect(result).not.toContain('сатр_методҳо'); + }); + + it('should map дарозии_сатр to length', () => { + const code = 'тағйирёбанда len = текст.дарозии_сатр;'; + const result = compileCode(code); + expect(result).toContain('.length'); + expect(result).not.toContain('дарозии_сатр'); + }); + }); + + describe('Backward compatibility', () => { + it('should support both camelCase and underscore variants', () => { + const codeUnderscore = 'чоп.гуруҳ_охир();'; + const codeCamel = 'чоп.гуруҳОхир();'; + + const resultUnderscore = compileCode(codeUnderscore); + const resultCamel = compileCode(codeCamel); + + expect(resultUnderscore).toContain('console.groupEnd()'); + expect(resultCamel).toContain('console.groupEnd()'); + }); + + it('should work in complex example with mixed usage', () => { + const code = ` +чоп.гуруҳ("Test"); +чоп.сабт("Message"); +чоп.гуруҳ_охир(); + +чоп.вақт("timer"); +чоп.вақт_сабт("timer", "checkpoint"); +чоп.вақт_охир("timer"); + `.trim(); + + const result = compileCode(code); + expect(result).toContain('console.group'); + expect(result).toContain('console.log'); + expect(result).toContain('console.groupEnd()'); + expect(result).toContain('console.time'); + expect(result).toContain('console.timeLog'); + expect(result).toContain('console.timeEnd'); + + // Ensure no Tajik identifiers remain in output + expect(result).not.toContain('гуруҳ_охир'); + expect(result).not.toContain('вақт_сабт'); + expect(result).not.toContain('вақт_охир'); + }); + }); +}); From 54cbb507c80813e96bfd078d3f25b33dd6a9970a Mon Sep 17 00:00:00 2001 From: Bakhtier Gaibulloev Date: Thu, 20 Nov 2025 13:29:48 +0100 Subject: [PATCH 7/9] feat: remove underscore variant support and standardize camelCase method names --- examples/33-console-methods.som | 26 ++--- examples/78-camelcase-methods.som | 55 +++++++++++ examples/console-methods-guide.som | 28 +++--- src/codegen.ts | 56 +++++------ src/keyword-map.ts | 26 +++-- src/parser.ts | 26 +++-- src/tokens.ts | 16 +-- tests/camelcase-methods.test.ts | 150 +++++++++++++++++++++++++++++ tests/keyword-map.test.ts | 16 +-- tests/lexer-extended.test.ts | 6 +- tests/lexer.test.ts | 9 +- tests/underscore-variants.test.ts | 84 ++++++++-------- 12 files changed, 355 insertions(+), 143 deletions(-) create mode 100644 examples/78-camelcase-methods.som create mode 100644 tests/camelcase-methods.test.ts diff --git a/examples/33-console-methods.som b/examples/33-console-methods.som index d64e0bf..a9f380b 100644 --- a/examples/33-console-methods.som +++ b/examples/33-console-methods.som @@ -57,20 +57,20 @@ чоп.сабт("Ном: Сомонӣ Сомонов"); чоп.сабт("Синну сол: 30"); чоп.сабт("Касб: Барномасоз"); -чоп.гуруҳ_охир(); +чоп.гуруҳОхир(); чоп.гуруҳ("Танзимоти система"); чоп.сабт("ОС: Windows 11"); чоп.сабт("RAM: 16GB"); чоп.сабт("CPU: Intel i7"); -чоп.гуруҳ_охир(); +чоп.гуруҳОхир(); // console.groupCollapsed - collapsed group -чоп.гуруҳ_пӯшида("Тафсилоти иловагӣ"); +чоп.гуруҳПӯшида("Тафсилоти иловагӣ"); чоп.сабт("Версияи барнома: 1.0.0"); чоп.сабт("Санаи насб: 2024-01-15"); чоп.сабт("Ҳаҷми файл: 2.5MB"); -чоп.гуруҳ_охир(); +чоп.гуруҳОхир(); // console.time and console.timeEnd - timing operations чоп.сабт("\n=== Ченкунии вақт ==="); @@ -80,7 +80,7 @@ барои (тағйирёбанда и = 0; и < 1000000; и++) { натиҷа += и; } -чоп.вақт_охир("Ҳисобкунӣ"); +чоп.вақтОхир("Ҳисобкунӣ"); чоп.сабт("Натиҷа: " + натиҷа); // Multiple timers @@ -91,12 +91,12 @@ барои (тағйирёбанда и = 0; и < 100000; и++) { // Амалиёти 1 } -чоп.вақт_охир("Амалиёти 1"); +чоп.вақтОхир("Амалиёти 1"); барои (тағйирёбанда и = 0; и < 200000; и++) { // Амалиёти 2 } -чоп.вақт_охир("Амалиёти 2"); +чоп.вақтОхир("Амалиёти 2"); // console.count - counting calls чоп.сабт("\n=== Ҳисобкунии даъватҳо ==="); @@ -113,7 +113,7 @@ коркарди_маълумот("корбар"); // console.countReset - reset counter -чоп.қайд_асл("Даъвати функсия"); +чоп.қайдАсл("Даъвати функсия"); чоп.сабт("Ҳисобкунак аз нав оғоз шуд"); коркарди_маълумот("нав"); @@ -194,7 +194,7 @@ агар (контекст) { чоп.хато("Контекст:", контекст); } - чоп.гуруҳ_охир(); + чоп.гуруҳОхир(); } кӯшиш { @@ -211,15 +211,15 @@ чоп.вақт("Қадами 1"); // Simulate work барои (тағйирёбанда и = 0; и < 100000; и++) {} - чоп.вақт_охир("Қадами 1"); + чоп.вақтОхир("Қадами 1"); чоп.вақт("Қадами 2"); // Simulate work барои (тағйирёбанда и = 0; и < 200000; и++) {} - чоп.вақт_охир("Қадами 2"); + чоп.вақтОхир("Қадами 2"); - чоп.вақт_охир("Вақти умумӣ"); - чоп.гуруҳ_охир(); + чоп.вақтОхир("Вақти умумӣ"); + чоп.гуруҳОхир(); } иҷрои_амалиёт(); diff --git a/examples/78-camelcase-methods.som b/examples/78-camelcase-methods.som new file mode 100644 index 0000000..a72506a --- /dev/null +++ b/examples/78-camelcase-methods.som @@ -0,0 +1,55 @@ +// Намунаи истифодаи методҳои camelCase +// Example of camelCase method usage + +функсия тестКонсол() { + чоп.гуруҳ("Гурӯҳи асосӣ"); + чоп.сабт("Салом ҷаҳон!"); + чоп.маълумот("Маълумоти муфид"); + + // Методҳои вақт бо camelCase + чоп.вақт("ҳисоб"); + чоп.вақтСабт("ҳисоб", "Нуқтаи миёна"); + чоп.вақтОхир("ҳисоб"); + + // Гурӯҳи пӯшида + чоп.гуруҳПӯшида("Тафсилот"); + чоп.исфти("Маълумоти дебаг"); + чоп.гуруҳОхир(); + + // Методи ҳисобкунӣ + чоп.қайд("ҳисобгар"); + чоп.қайд("ҳисобгар"); + чоп.қайдАсл("ҳисобгар"); + + // XML феҳрист + тағйирёбанда объект = { ном: "Тест", синн: 25 }; + чоп.xmlФеҳрист(объект); + + чоп.гуруҳОхир(); +} + +// Намунаи методҳои сатр +функсия тестСатр() { + тағйирёбанда матн = "Салом ҷаҳон"; + + // Истифодаи дарозииСатр (camelCase) + тағйирёбанда дарозӣ = матн.дарозииСатр; + чоп.сабт("Дарозии матн: " + дарозӣ); + + // Истифодаи дигар методҳо + тағйирёбанда калон = матн.калон(); + чоп.сабт("Калон: " + калон); + + тағйирёбанда хурд = матн.хурд(); + чоп.сабт("Хурд: " + хурд); + + тағйирёбанда қисм = матн.қисмат(0, 5); + чоп.сабт("Қисм: " + қисм); +} + +// Иҷро кардан +тестКонсол(); +тестСатр(); + +// Эзоҳ: Методҳои бо зерхат (масалан: гуруҳ_охир, вақт_сабт) дигар кор намекунанд! +// Истифода кунед: гуруҳОхир, вақтСабт, қайдАсл, xmlФеҳрист ва ғайра diff --git a/examples/console-methods-guide.som b/examples/console-methods-guide.som index 9d5a35a..a1731fd 100644 --- a/examples/console-methods-guide.som +++ b/examples/console-methods-guide.som @@ -43,23 +43,23 @@ амалиёт_шумора = амалиёт_шумора + 1; } -// CountReset - қайд_асл (Сброс счётчика) -чоп.қайд_асл('амалиёт'); // Reset counter to 0 +// CountReset - қайдАсл (Сброс счётчика) +чоп.қайдАсл('амалиёт'); // Reset counter to 0 // 4. TIMING - ВАҚТҲО -// Time/TimeEnd - вақт/вақт_охир (Измерение времени) +// Time/TimeEnd - вақт/вақтОхир (Измерение времени) чоп.вақт('барномадавӣ'); барои (тағйирёбанда i = 0; i < 100; i++) { // simple loop } -чоп.вақт_охир('барномадавӣ'); // Show elapsed time +чоп.вақтОхир('барномадавӣ'); // Show elapsed time -// TimeLog - вақт_сабт (Лог с временем) +// TimeLog - вақтСабт (Лог с временем) чоп.вақт('бор'); -чоп.вақт_сабт('бор', 'Марҳалаи 1 комплет'); // Log without stopping -чоп.вақт_охир('бор'); +чоп.вақтСабт('бор', 'Марҳалаи 1 комплет'); // Log without stopping +чоп.вақтОхир('бор'); // 5. TABLE OUTPUT - ҶАДВАЛҲО @@ -94,17 +94,17 @@ // 9. GROUPING OUTPUT - ГУРУҲБАНДИИ НАТИҶАҲО -// Group/GroupEnd - гуруҳ/гуруҳ_охир (Группировка) +// Group/GroupEnd - гуруҳ/гуруҳОхир (Группировка) чоп.гуруҳ('Фасли 1'); чоп.сабт('Сатри 1'); чоп.сабт('Сатри 2'); -чоп.гуруҳ_охир(); +чоп.гуруҳОхир(); -// GroupCollapsed - гуруҳ_пӯшида (Скрытая группа) -чоп.гуруҳ_пӯшида('Фасли 2 (қалаб)'); +// GroupCollapsed - гуруҳПӯшида (Скрытая группа) +чоп.гуруҳПӯшида('Фасли 2 (қалаб)'); чоп.сабт('Сатри 3'); чоп.сабт('Сатри 4'); -чоп.гуруҳ_охир(); +чоп.гуруҳОхир(); // 10. COMPLETE EXAMPLE @@ -131,10 +131,10 @@ чоп.ҷадвал(натиҷа); // Конец - чоп.вақт_охир('раҳгирӣ'); + чоп.вақтОхир('раҳгирӣ'); чоп.сабт('Раҳгирӣ нумониши комплет'); - чоп.гуруҳ_охир(); + чоп.гуруҳОхир(); } раҳгирӣ_веб_сохӣ(); diff --git a/src/codegen.ts b/src/codegen.ts index 3635557..7b70f77 100644 --- a/src/codegen.ts +++ b/src/codegen.ts @@ -67,22 +67,16 @@ export class CodeGenerator { ['ҷадвал', 'table'], ['гуруҳ', 'group'], ['гуруҳОхир', 'groupEnd'], - ['гуруҳ_охир', 'groupEnd'], // Underscore variant ['гуруҳПӯшида', 'groupCollapsed'], - ['гуруҳ_пӯшида', 'groupCollapsed'], // Underscore variant ['вақт', 'time'], ['вақтОхир', 'timeEnd'], - ['вақт_охир', 'timeEnd'], // Underscore variant ['вақтСабт', 'timeLog'], - ['вақт_сабт', 'timeLog'], // Underscore variant ['қайд', 'count'], ['қайдАсл', 'countReset'], - ['қайд_асл', 'countReset'], // Underscore variant ['тасдиқ', 'assert'], ['полиз', 'clear'], ['феҳрист', 'dir'], ['xmlФеҳрист', 'dirxml'], - ['xml_феҳрист', 'dirxml'], // Underscore variant ['пайҷо', 'trace'], // Error handling @@ -137,9 +131,7 @@ export class CodeGenerator { // String methods ['сатр', 'String'], // String type/constructor ['сатрМетодҳо', 'String'], // String methods object - ['сатр_методҳо', 'String'], // Underscore variant ['дарозииСатр', 'length'], - ['дарозии_сатр', 'length'], // Underscore variant ['дар', 'at'], ['аломатДар', 'charAt'], ['кодиАломатДар', 'charCodeAt'], @@ -918,15 +910,7 @@ export class CodeGenerator { } // Map built-in constructors/objects (when used as identifiers) - const builtinConstructors = [ - 'сатр', - 'рӯйхат', - 'объект', - 'математика', - 'Риёзӣ', - 'сатрМетодҳо', - 'сатр_методҳо', // Underscore variant - ]; + const builtinConstructors = ['сатр', 'рӯйхат', 'объект', 'математика', 'Риёзӣ', 'сатрМетодҳо']; if (builtinConstructors.includes(node.name)) { const mapped = this.builtinMappings.get(node.name); if (mapped) { @@ -1043,15 +1027,7 @@ export class CodeGenerator { } const objectName = (node.object as Identifier).name; - const builtinObjects = [ - 'чоп', - 'математика', - 'объект', - 'Риёзӣ', - 'сатр', - 'сатрМетодҳо', - 'сатр_методҳо', // Underscore variant - ]; + const builtinObjects = ['чоп', 'математика', 'объект', 'Риёзӣ', 'сатр', 'сатрМетодҳо']; if (!builtinObjects.includes(objectName)) { return { mapped: object, wasMapped: false }; @@ -1091,13 +1067,26 @@ export class CodeGenerator { } const commonMethods = [ - // Console methods (underscore variants) - 'гуруҳ_охир', - 'гуруҳ_пӯшида', - 'вақт_сабт', - 'вақт_охир', - 'қайд_асл', - 'xml_феҳрист', + // Console methods (basic and camelCase) + 'сабт', + 'хато', + 'огоҳӣ', + 'маълумот', + 'исфти', + 'тасдиқ', + 'ҷадвал', + 'гуруҳ', + 'гуруҳОхир', + 'гуруҳПӯшида', + 'вақт', + 'вақтОхир', + 'вақтСабт', + 'қайд', + 'қайдАсл', + 'полиз', + 'феҳрист', + 'xmlФеҳрист', + 'пайҷо', // Array methods 'дарозӣ', 'дар', @@ -1144,7 +1133,6 @@ export class CodeGenerator { 'бо', // String methods 'дарозииСатр', - 'дарозии_сатр', // Underscore variant 'аломатДар', 'кодиАломатДар', 'нуқтаиКодДар', diff --git a/src/keyword-map.ts b/src/keyword-map.ts index 88c0758..2b4637f 100644 --- a/src/keyword-map.ts +++ b/src/keyword-map.ts @@ -38,18 +38,24 @@ export const KEYWORDS: ReadonlyMap = new Map = new Map { + function compileCode(source: string): string { + const lexer = new Lexer(source); + const tokens = lexer.tokenize(); + const parser = new Parser(tokens); + const ast = parser.parse(); + const codegen = new CodeGenerator(); + return codegen.generate(ast); + } + + describe('Console methods (camelCase)', () => { + test('should correctly map console methods with camelCase', () => { + const testCases = [ + { input: 'чоп.гуруҳОхир();', expected: 'console.groupEnd()' }, + { input: 'чоп.гуруҳПӯшида("test");', expected: 'console.groupCollapsed("test")' }, + { input: 'чоп.вақтСабт("timer");', expected: 'console.timeLog("timer")' }, + { input: 'чоп.вақтОхир("timer");', expected: 'console.timeEnd("timer")' }, + { input: 'чоп.қайдАсл("counter");', expected: 'console.countReset("counter")' }, + { input: 'чоп.xmlФеҳрист(obj);', expected: 'console.dirxml(obj)' }, + ]; + + testCases.forEach(({ input, expected }) => { + const result = compileCode(input); + expect(result.trim()).toBe(expected + ';'); + }); + }); + + test('should NOT translate underscore variants (methods remain as identifiers)', () => { + const testCases = [ + { input: 'чоп.гуруҳ_охир();', expected: 'console.гуруҳ_охир();' }, + { input: 'чоп.гуруҳ_пӯшида("test");', expected: 'console.гуруҳ_пӯшида("test");' }, + { input: 'чоп.вақт_сабт("timer");', expected: 'console.вақт_сабт("timer");' }, + { input: 'чоп.вақт_охир("timer");', expected: 'console.вақт_охир("timer");' }, + { input: 'чоп.қайд_асл("counter");', expected: 'console.қайд_асл("counter");' }, + { input: 'чоп.xml_феҳрист(obj);', expected: 'console.xml_феҳрист(obj);' }, + ]; + + testCases.forEach(({ input, expected }) => { + const result = compileCode(input); + // чоп is translated to console, but underscore methods remain unchanged + expect(result.trim()).toBe(expected); + }); + }); + }); + + describe('String helper methods (camelCase)', () => { + test('should correctly map string helper as object reference', () => { + const code = 'тағйирёбанда s = сатрМетодҳо;'; + const result = compileCode(code); + expect(result).toContain('let s = String;'); + }); + + test('should correctly map string length property', () => { + const code = 'тағйирёбанда len = текст.дарозииСатр;'; + const result = compileCode(code); + expect(result).toContain('let len = текст.length;'); + }); + + test('should NOT translate underscore string variants', () => { + const testCases = [ + { input: 'тағйирёбанда s = сатр_методҳо;', shouldContain: 'сатр_методҳо' }, + { input: 'тағйирёбанда len = текст.дарозии_сатр;', shouldContain: 'дарозии_сатр' }, + ]; + + testCases.forEach(({ input, shouldContain }) => { + const result = compileCode(input); + expect(result).toContain(shouldContain); + expect(result).not.toContain('String'); + expect(result).not.toContain('.length'); + }); + }); + }); + + describe('Complex usage scenarios', () => { + test('should handle mixed camelCase methods in a program', () => { + const code = ` + функсия тест() { + чоп.гуруҳ("Тест"); + чоп.сабт("Салом!"); + чоп.вақт("timer"); + чоп.вақтСабт("timer"); + чоп.вақтОхир("timer"); + чоп.гуруҳОхир(); + + тағйирёбанда текст = "Салом"; + тағйирёбанда дарозӣ = текст.дарозииСатр; + бозгашт дарозӣ; + } + `; + + const result = compileCode(code); + expect(result).toContain('console.group("Тест")'); + expect(result).toContain('console.log("Салом!")'); + expect(result).toContain('console.time("timer")'); + expect(result).toContain('console.timeLog("timer")'); + expect(result).toContain('console.timeEnd("timer")'); + expect(result).toContain('console.groupEnd()'); + expect(result).toContain('let дарозӣ = текст.length'); + }); + + test('should reject underscore methods in a program', () => { + const code = ` + функсия тест() { + чоп.гуруҳ_охир(); + тағйирёбанда s = сатр_методҳо; + тағйирёбанда len = текст.дарозии_сатр; + } + `; + + const result = compileCode(code); + // These should remain unchanged (not translated) + expect(result).toContain('гуруҳ_охир'); + expect(result).toContain('сатр_методҳо'); + expect(result).toContain('дарозии_сатр'); + // Should not contain translations + expect(result).not.toContain('console.groupEnd'); + expect(result).not.toContain('String'); + expect(result).not.toContain('.length'); + }); + }); + + describe('Lexer tokenization', () => { + test('should correctly tokenize camelCase keywords as keywords', () => { + const lexer = new Lexer('сатрМетодҳо дарозииСатр гуруҳОхир вақтСабт қайдАсл xmlФеҳрист'); + const tokens = lexer.tokenize(); + + // These are tokenized as keywords with specific token types + expect(tokens[0].type).toBe('САТРМЕТОДҲО'); + expect(tokens[1].type).toBe('ДАРОЗИИСАТР'); + expect(tokens[2].type).toBe('ГУРУҲОХИР'); + expect(tokens[3].type).toBe('ВАҚТСАБТ'); + expect(tokens[4].type).toBe('ҚАЙДАСЛ'); + expect(tokens[5].type).toBe('XMLФЕҲРИСТ'); + }); + + test('should treat underscore variants as regular identifiers', () => { + const lexer = new Lexer('сатр_методҳо дарозии_сатр гуруҳ_охир'); + const tokens = lexer.tokenize(); + + // These should be treated as regular IDENTIFIER tokens, not keywords + expect(tokens[0].type).toBe('IDENTIFIER'); + expect(tokens[1].type).toBe('IDENTIFIER'); + expect(tokens[2].type).toBe('IDENTIFIER'); + }); + }); +}); diff --git a/tests/keyword-map.test.ts b/tests/keyword-map.test.ts index ae2d372..c1daa9d 100644 --- a/tests/keyword-map.test.ts +++ b/tests/keyword-map.test.ts @@ -40,18 +40,18 @@ describe('Keyword map coverage', () => { ['исфти', TokenType.ИСФТИ], ['тасдиқ', TokenType.ТАСДИҚ], ['қайд', TokenType.ҚАЙД], - ['қайд_асл', TokenType.ҚАЙД_АСЛ], + ['қайдАсл', TokenType.ҚАЙДАСЛ], ['вақт', TokenType.ВАҚТ], - ['вақт_сабт', TokenType.ВАҚТ_САБТ], - ['вақт_охир', TokenType.ВАҚТ_ОХИР], + ['вақтСабт', TokenType.ВАҚТСАБТ], + ['вақтОхир', TokenType.ВАҚТОХИР], ['ҷадвал', TokenType.ҶАДВАЛ], ['феҳрист', TokenType.ФЕҲРИСТ], - ['xml_феҳрист', TokenType.XML_ФЕҲРИСТ], + ['xmlФеҳрист', TokenType.XMLФЕҲРИСТ], ['пайҷо', TokenType.ПАЙҶО], ['полиз', TokenType.ПОЛИЗ], ['гуруҳ', TokenType.ГУРУҲ], - ['гуруҳ_охир', TokenType.ГУРУҲ_ОХИР], - ['гуруҳ_пӯшида', TokenType.ГУРУҲ_ПӮШИДА], + ['гуруҳОхир', TokenType.ГУРУҲОХИР], + ['гуруҳПӯшида', TokenType.ГУРУҲПӮШИДА], // Array methods ['рӯйхат', TokenType.РӮЙХАТ], @@ -63,8 +63,8 @@ describe('Keyword map coverage', () => { ['кофтан', TokenType.КОФТАН], // String methods - ['сатр_методҳо', TokenType.САТР_МЕТОДҲО], - ['дарозии_сатр', TokenType.ДАРОЗИИ_САТР], + ['сатрМетодҳо', TokenType.САТРМЕТОДҲО], + ['дарозииСатр', TokenType.ДАРОЗИИСАТР], ['пайвастан', TokenType.ПАЙВАСТАН], ['ҷойивазкунӣ', TokenType.ҶОЙИВАЗКУНӢ], ['ҷудокунӣ', TokenType.ҶУДОКУНӢ], diff --git a/tests/lexer-extended.test.ts b/tests/lexer-extended.test.ts index ad37d01..a937164 100644 --- a/tests/lexer-extended.test.ts +++ b/tests/lexer-extended.test.ts @@ -466,11 +466,11 @@ describe('Lexer Extended Coverage Tests', () => { describe('String method tokens', () => { test('should tokenize string method identifiers', () => { - const source = 'сатр_методҳо дарозии_сатр пайвастан ҷойивазкунӣ ҷудокунӣ'; + const source = 'сатрМетодҳо дарозииСатр пайвастан ҷойивазкунӣ ҷудокунӣ'; const tokens = tokenize(source); - expect(tokens[0].type).toBe(TokenType.САТР_МЕТОДҲО); - expect(tokens[1].type).toBe(TokenType.ДАРОЗИИ_САТР); + expect(tokens[0].type).toBe(TokenType.САТРМЕТОДҲО); + expect(tokens[1].type).toBe(TokenType.ДАРОЗИИСАТР); expect(tokens[2].type).toBe(TokenType.ПАЙВАСТАН); expect(tokens[3].type).toBe(TokenType.ҶОЙИВАЗКУНӢ); expect(tokens[4].type).toBe(TokenType.ҶУДОКУНӢ); diff --git a/tests/lexer.test.ts b/tests/lexer.test.ts index e54a5de..79027a7 100644 --- a/tests/lexer.test.ts +++ b/tests/lexer.test.ts @@ -125,11 +125,12 @@ describe('Lexer', () => { expect(tokens[3].value).toBe('||'); }); - test('should tokenize string methods with new naming', () => { - const source = 'сатр_методҳо.дарозии_сатр'; + test('should tokenize string methods with camelCase naming', () => { + const source = 'сатрМетодҳо.дарозииСатр'; const tokens = tokenize(source); - expect(tokens[0].type).toBe('САТР_МЕТОДҲО'); - expect(tokens[2].type).toBe('ДАРОЗИИ_САТР'); + expect(tokens[0].type).toBe('САТРМЕТОДҲО'); + expect(tokens[1].type).toBe('.'); + expect(tokens[2].type).toBe('ДАРОЗИИСАТР'); }); }); diff --git a/tests/underscore-variants.test.ts b/tests/underscore-variants.test.ts index 92a8662..29a656e 100644 --- a/tests/underscore-variants.test.ts +++ b/tests/underscore-variants.test.ts @@ -2,7 +2,7 @@ import { Lexer } from '../src/lexer'; import { Parser } from '../src/parser'; import { CodeGenerator } from '../src/codegen'; -describe('Underscore variant mappings', () => { +describe('CamelCase-only mappings (no underscore support)', () => { function compileCode(source: string): string { const lexer = new Lexer(source); const tokens = lexer.tokenize(); @@ -12,79 +12,80 @@ describe('Underscore variant mappings', () => { return codegen.generate(ast); } - describe('Console method underscore variants', () => { - it('should map гуруҳ_охир to console.groupEnd', () => { + describe('Console method camelCase-only support', () => { + it('should NOT map underscore variant гуруҳ_охир', () => { const code = 'чоп.гуруҳ_охир();'; const result = compileCode(code); - expect(result).toContain('console.groupEnd()'); - expect(result).not.toContain('гуруҳ_охир'); + expect(result).toContain('гуруҳ_охир'); // Should remain unchanged + expect(result).not.toContain('console.groupEnd()'); }); - it('should map гуруҳ_пӯшида to console.groupCollapsed', () => { - const code = 'чоп.гуруҳ_пӯшида("test");'; + it('should map camelCase гуруҳОхир to console.groupEnd', () => { + const code = 'чоп.гуруҳОхир();'; const result = compileCode(code); - expect(result).toContain('console.groupCollapsed'); - expect(result).not.toContain('гуруҳ_пӯшида'); + expect(result).toContain('console.groupEnd()'); + expect(result).not.toContain('гуруҳОхир'); }); - it('should map вақт_сабт to console.timeLog', () => { + it('should NOT map underscore variant вақт_сабт', () => { const code = 'чоп.вақт_сабт("timer");'; const result = compileCode(code); - expect(result).toContain('console.timeLog'); - expect(result).not.toContain('вақт_сабт'); + expect(result).toContain('вақт_сабт'); // Should remain unchanged + expect(result).not.toContain('console.timeLog'); }); - it('should map вақт_охир to console.timeEnd', () => { - const code = 'чоп.вақт_охир("timer");'; + it('should map camelCase вақтСабт to console.timeLog', () => { + const code = 'чоп.вақтСабт("timer");'; const result = compileCode(code); - expect(result).toContain('console.timeEnd'); - expect(result).not.toContain('вақт_охир'); + expect(result).toContain('console.timeLog'); + expect(result).not.toContain('вақтСабт'); }); - it('should map қайд_асл to console.countReset', () => { + it('should NOT map underscore variant қайд_асл', () => { const code = 'чоп.қайд_асл("counter");'; const result = compileCode(code); - expect(result).toContain('console.countReset'); - expect(result).not.toContain('қайд_асл'); + expect(result).toContain('қайд_асл'); // Should remain unchanged + expect(result).not.toContain('console.countReset'); }); - it('should map xml_феҳрист to console.dirxml', () => { - const code = 'чоп.xml_феҳрист(obj);'; + it('should map camelCase қайдАсл to console.countReset', () => { + const code = 'чоп.қайдАсл("counter");'; const result = compileCode(code); - expect(result).toContain('console.dirxml'); - expect(result).not.toContain('xml_феҳрист'); + expect(result).toContain('console.countReset'); + expect(result).not.toContain('қайдАсл'); }); }); - describe('String helper underscore variants', () => { - it('should map сатр_методҳо to String', () => { - const code = 'тағйирёбанда s = сатр_методҳо;'; + describe('String helper camelCase variants', () => { + it('should map сатрМетодҳо to String', () => { + const code = 'тағйирёбанда s = сатрМетодҳо;'; const result = compileCode(code); expect(result).toContain('String'); - expect(result).not.toContain('сатр_методҳо'); + expect(result).not.toContain('сатрМетодҳо'); }); - it('should map дарозии_сатр to length', () => { - const code = 'тағйирёбанда len = текст.дарозии_сатр;'; + it('should map дарозииСатр to length', () => { + const code = 'тағйирёбанда len = текст.дарозииСатр;'; const result = compileCode(code); expect(result).toContain('.length'); - expect(result).not.toContain('дарозии_сатр'); + expect(result).not.toContain('дарозииСатр'); }); }); - describe('Backward compatibility', () => { - it('should support both camelCase and underscore variants', () => { + describe('CamelCase only support', () => { + it('should only support camelCase variants, not underscore', () => { const codeUnderscore = 'чоп.гуруҳ_охир();'; const codeCamel = 'чоп.гуруҳОхир();'; const resultUnderscore = compileCode(codeUnderscore); const resultCamel = compileCode(codeCamel); - expect(resultUnderscore).toContain('console.groupEnd()'); + // Underscore variant should NOT be translated + expect(resultUnderscore).toContain('гуруҳ_охир'); expect(resultCamel).toContain('console.groupEnd()'); }); - it('should work in complex example with mixed usage', () => { + it('should reject underscore methods in complex example', () => { const code = ` чоп.гуруҳ("Test"); чоп.сабт("Message"); @@ -96,17 +97,18 @@ describe('Underscore variant mappings', () => { `.trim(); const result = compileCode(code); + // Basic methods should work expect(result).toContain('console.group'); expect(result).toContain('console.log'); - expect(result).toContain('console.groupEnd()'); expect(result).toContain('console.time'); - expect(result).toContain('console.timeLog'); - expect(result).toContain('console.timeEnd'); - // Ensure no Tajik identifiers remain in output - expect(result).not.toContain('гуруҳ_охир'); - expect(result).not.toContain('вақт_сабт'); - expect(result).not.toContain('вақт_охир'); + // Underscore methods should NOT be translated + expect(result).toContain('гуруҳ_охир'); + expect(result).toContain('вақт_сабт'); + expect(result).toContain('вақт_охир'); + expect(result).not.toContain('console.groupEnd()'); + expect(result).not.toContain('console.timeLog'); + expect(result).not.toContain('console.timeEnd'); }); }); }); From 0d7e9c580ff62aabe32370fdf053f9e1b37f21b7 Mon Sep 17 00:00:00 2001 From: Bakhtier Gaibulloev Date: Thu, 20 Nov 2025 13:44:57 +0100 Subject: [PATCH 8/9] chore: remove figma-developer-mcp dependency and reformat lint-staged config --- package-lock.json | 3 +-- package.json | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index fddd4b7..03a2f31 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "babel-preset-minify": "^0.5.2", "chokidar": "^3.6.0", "commander": "^11.0.0", - "figma-developer-mcp": "^0.6.4", "source-map": "^0.7.6", "typescript": "^5.0.0" }, @@ -9590,4 +9589,4 @@ } } } -} +} \ No newline at end of file diff --git a/package.json b/package.json index f9eff31..75ac5b8 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,6 @@ "babel-preset-minify": "^0.5.2", "chokidar": "^3.6.0", "commander": "^11.0.0", - "figma-developer-mcp": "^0.6.4", "source-map": "^0.7.6", "typescript": "^5.0.0" }, From 680e8079adb58996cd5a427cdca2b4982a3e9929 Mon Sep 17 00:00:00 2001 From: Bakhtier Gaibulloev Date: Thu, 20 Nov 2025 13:54:53 +0100 Subject: [PATCH 9/9] test: add lowercase variant coverage for camelCase Tajik method names --- tests/keyword-map.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/keyword-map.test.ts b/tests/keyword-map.test.ts index c1daa9d..3079ed4 100644 --- a/tests/keyword-map.test.ts +++ b/tests/keyword-map.test.ts @@ -41,17 +41,23 @@ describe('Keyword map coverage', () => { ['тасдиқ', TokenType.ТАСДИҚ], ['қайд', TokenType.ҚАЙД], ['қайдАсл', TokenType.ҚАЙДАСЛ], + ['қайдасл', TokenType.ҚАЙДАСЛ], // Lowercase version ['вақт', TokenType.ВАҚТ], ['вақтСабт', TokenType.ВАҚТСАБТ], + ['вақтсабт', TokenType.ВАҚТСАБТ], // Lowercase version ['вақтОхир', TokenType.ВАҚТОХИР], + ['вақтохир', TokenType.ВАҚТОХИР], // Lowercase version ['ҷадвал', TokenType.ҶАДВАЛ], ['феҳрист', TokenType.ФЕҲРИСТ], ['xmlФеҳрист', TokenType.XMLФЕҲРИСТ], + ['xmlфеҳрист', TokenType.XMLФЕҲРИСТ], // Lowercase version ['пайҷо', TokenType.ПАЙҶО], ['полиз', TokenType.ПОЛИЗ], ['гуруҳ', TokenType.ГУРУҲ], ['гуруҳОхир', TokenType.ГУРУҲОХИР], + ['гуруҳохир', TokenType.ГУРУҲОХИР], // Lowercase version ['гуруҳПӯшида', TokenType.ГУРУҲПӮШИДА], + ['гуруҳпӯшида', TokenType.ГУРУҲПӮШИДА], // Lowercase version // Array methods ['рӯйхат', TokenType.РӮЙХАТ], @@ -64,7 +70,9 @@ describe('Keyword map coverage', () => { // String methods ['сатрМетодҳо', TokenType.САТРМЕТОДҲО], + ['сатрметодҳо', TokenType.САТРМЕТОДҲО], // Lowercase version ['дарозииСатр', TokenType.ДАРОЗИИСАТР], + ['дарозиисатр', TokenType.ДАРОЗИИСАТР], // Lowercase version ['пайвастан', TokenType.ПАЙВАСТАН], ['ҷойивазкунӣ', TokenType.ҶОЙИВАЗКУНӢ], ['ҷудокунӣ', TokenType.ҶУДОКУНӢ],