diff --git a/README.md b/README.md index ef723fe..3fb57a1 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ The extension is now available on the Chrome Web Store! [**Install it directly f ## 🚀 Stable Release -For the most stable and fully tested version, [**download the latest release here**](https://github.com/sevilayerkan/test-string-extention/releases/tag/1.0.1). +For the most stable and fully tested version, [**download the latest release here**](https://github.com/sevilayerkan/test-string-extention/releases/tag/v0.2.0-alpha). > **Note:** The `main` branch is pre-production and may include features under development. For production use, always prefer the latest release above. diff --git a/background.js b/background.js index 328ae55..78f4d0f 100644 --- a/background.js +++ b/background.js @@ -1,3 +1,151 @@ -chrome.action.onClicked.addListener(function (tab) { - chrome.runtime.connect({ name: 'popup' }); -}); +// Background Service Worker for Test String Generator Extension + +// Handle extension installation and updates +if (typeof chrome !== 'undefined' && chrome.runtime) { + chrome.runtime.onInstalled.addListener((details) => { + if (details.reason === 'install') { + console.log('Test String Generator extension installed'); + + // Set default settings + chrome.storage.sync.set({ + theme: 'light', + language: 'en' + }).catch(err => { + console.warn('Failed to set default settings:', err); + }); + } else if (details.reason === 'update') { + console.log('Test String Generator extension updated'); + + // Handle version migration if needed + handleVersionUpdate(details.previousVersion); + + // Show update notification + showUpdateNotification(); + } + }); +} + +// Handle extension startup +if (typeof chrome !== 'undefined' && chrome.runtime) { + chrome.runtime.onStartup.addListener(() => { + console.log('Test String Generator extension started'); + }); + + // Handle messages from content scripts or popup + chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + // Handle any background tasks if needed in the future + console.log('Background received message:', request); + + // Always respond to keep the message channel open + sendResponse({ status: 'received' }); + + return true; // Keep message channel open for async operations + }); + + // Handle external connections + chrome.runtime.onConnect.addListener((port) => { + if (port.name === 'popup') { + console.log('Popup connected'); + + port.onDisconnect.addListener(() => { + console.log('Popup disconnected'); + }); + } + }); +} + +// Handle context menu creation (if needed in future) +// chrome.contextMenus.create({ +// id: 'generate-test-string', +// title: 'Generate Test String', +// contexts: ['editable'] +// }); + +// Keep service worker alive by periodically performing tasks +if (typeof chrome !== 'undefined' && chrome.storage) { + const keepAlive = () => { + // Perform a lightweight operation + chrome.storage.local.set({ lastHeartbeat: Date.now() }); + }; + + // Set up heartbeat every 20 seconds + setInterval(keepAlive, 20000); +} + +// Update handling functions +function handleVersionUpdate(previousVersion) { + const currentVersion = chrome.runtime.getManifest().version; + console.log(`Updated from ${previousVersion} to ${currentVersion}`); + + // Handle data migration between versions if needed + if (previousVersion && chrome.storage) { + migrateDataIfNeeded(previousVersion, currentVersion); + } +} + +function showUpdateNotification() { + // Create a notification for the update + if (chrome.notifications) { + chrome.notifications.create('update-notification', { + type: 'basic', + iconUrl: 'assets/icon48.png', + title: 'Test String Generator Updated!', + message: 'New features and improvements are now available.' + }); + } +} + +function migrateDataIfNeeded(previousVersion, currentVersion) { + // Example: Migrate old settings format to new format + chrome.storage.sync.get(null).then(data => { + let needsMigration = false; + + // Add migration logic here based on version comparisons + if (compareVersions(previousVersion, '1.1.0') < 0) { + // Migrate to v1.1.0 format if needed + console.log('Migrating to v1.1.0 format...'); + needsMigration = true; + } + + if (needsMigration) { + chrome.storage.sync.set(data).then(() => { + console.log('Data migration completed'); + }); + } + }).catch(err => { + console.warn('Migration failed:', err); + }); +} + +function compareVersions(version1, version2) { + const v1parts = version1.split('.').map(Number); + const v2parts = version2.split('.').map(Number); + + for (let i = 0; i < Math.max(v1parts.length, v2parts.length); i++) { + const v1part = v1parts[i] || 0; + const v2part = v2parts[i] || 0; + + if (v1part < v2part) return -1; + if (v1part > v2part) return 1; + } + + return 0; +} + +// Check for updates periodically (optional) +function checkForUpdates() { + if (chrome.runtime.requestUpdateCheck) { + chrome.runtime.requestUpdateCheck((status, details) => { + if (status === 'update_available') { + console.log('Update available:', details); + // Optionally restart to apply update immediately + // chrome.runtime.reload(); + } + }); + } +} + +// Set up periodic update checks (every 24 hours) +setInterval(checkForUpdates, 24 * 60 * 60 * 1000); + +console.log('Test String Generator background script loaded'); diff --git a/data/address.json b/data/address.json index 2e8e9db..e6b5240 100644 --- a/data/address.json +++ b/data/address.json @@ -18,6 +18,53 @@ "Adnan Menderes Bulvarı No: 56, Eskişehir", "Karaağaç Mahallesi, Zeytin Sokak No: 23, Trabzon", "Gaziosmanpaşa Caddesi No: 89, Maltepe, İstanbul", - "Menderes Mahallesi, Atatürk Sokak No: 67, Edirne" + "Menderes Mahallesi, Atatürk Sokak No: 67, Edirne", + "Cumhuriyet Mahallesi, Çiçek Sokak No: 15, Konya", + "Zafer Bulvarı No: 91, Merkez, Kayseri", + "Doğanbey Mahallesi, Lale Sokak No: 24, Erzurum", + "Fevzi Çakmak Caddesi No: 36, Sivas", + "Hürriyet Mahallesi, Papatya Sokak No: 77, Gaziantep", + "Milli Egemenlik Bulvarı No: 42, Şanlıurfa", + "Barış Mahallesi, Kardelen Sokak No: 18, Van", + "Kültür Caddesi No: 63, Diyarbakır", + "Yeşiltepe Mahallesi, Nergis Sokak No: 29, Malatya", + "Güven Bulvarı No: 85, Elazığ", + "Çınarlı Mahallesi, Menekşe Sokak No: 41, Kocaeli", + "Özgürlük Caddesi No: 52, Sakarya", + "Tekkeköy Mahallesi, Karanfil Sokak No: 73, Samsun", + "Altınova Bulvarı No: 19, Ordu", + "Sahil Mahallesi, Martı Sokak No: 66, Sinop", + "Çay Caddesi No: 28, Rize", + "Değirmen Mahallesi, Fulya Sokak No: 94, Artvin", + "Akşemsettin Bulvarı No: 37, Kastamonu", + "Toprak Mahallesi, Begonva Sokak No: 59, Çorum", + "Yıldırım Caddesi No: 81, Amasya", + "Çilek Mahallesi, Lavanta Sokak No: 13, Tokat", + "Doğu Bulvarı No: 48, Yozgat", + "Kızılırmak Caddesi No: 76, Kırıkkale", + "Şehit Mahallesi, Gül Sokak No: 22, Nevşehir", + "Kapadokya Bulvarı No: 65, Kırşehir", + "Bagdat Caddesi No: 147, Üsküdar, İstanbul", + "Nişantaşı Mahallesi, Teşvikiye Sokak No: 88, Şişli, İstanbul", + "Levent Caddesi No: 201, Beşiktaş, İstanbul", + "Etiler Mahallesi, Akmerkez Sokak No: 35, Beşiktaş, İstanbul", + "Bebek Yolu No: 99, Bebek, İstanbul", + "Ortaköy Meydanı No: 17, Beşiktaş, İstanbul", + "Galata Kulesi Caddesi No: 44, Galata, İstanbul", + "Sultanahmet Meydanı No: 8, Fatih, İstanbul", + "Karaköy Mahallesi, Banker Sokak No: 52, Beyoğlu, İstanbul", + "Cihangir Mahallesi, Susam Sokak No: 71, Beyoğlu, İstanbul", + "Kızılay Meydanı No: 25, Çankaya, Ankara", + "Bahçelievler Mahallesi, Adalet Sokak No: 33, Çankaya, Ankara", + "Çayyolu Bulvarı No: 156, Çankaya, Ankara", + "Bilkent Üniversitesi Caddesi No: 1, Çankaya, Ankara", + "Tunalı Hilmi Caddesi No: 67, Çankaya, Ankara", + "Güvenpark Mahallesi, Atatürk Bulvarı No: 123, Altındağ, Ankara", + "Konak Meydanı No: 5, Konak, İzmir", + "Alsancak Limanı Caddesi No: 78, Konak, İzmir", + "Foça Sahil Yolu No: 34, Foça, İzmir", + "Çeşme Marina Bulvarı No: 92, Çeşme, İzmir", + "Alaçatı Mahallesi, Rüzgar Sokak No: 16, Çeşme, İzmir", + "Sığacık Limanı Caddesi No: 41, Seferihisar, İzmir" ] \ No newline at end of file diff --git a/data/email.json b/data/email.json index ac0f4c1..413f17e 100644 --- a/data/email.json +++ b/data/email.json @@ -208,6 +208,112 @@ "hr@example.com", "finance@example.com", "it@example.com", - "security@example.com" + "security@example.com", + "info@teknoloji.com", + "destek@yazilim.net", + "iletisim@proje.org", + "admin@sistem.gov.tr", + "user@domain.edu.tr", + "test@sample.co.uk", + "demo@example.io", + "contact@business.biz", + "help@support.tech", + "mail@webmail.online", + "inbox@messaging.app", + "notification@alerts.system", + "newsletter@updates.news", + "marketing@campaigns.digital", + "sales@ecommerce.shop", + "service@customer.care", + "feedback@review.platform", + "team@collaboration.workspace", + "dev@development.studio", + "api@integration.cloud", + "data@analytics.insights", + "security@protection.shield", + "backup@storage.vault", + "monitoring@performance.metrics", + "logging@tracking.events", + "report@business.intelligence", + "dashboard@visualization.charts", + "mobile@responsive.design", + "frontend@ui.experience", + "backend@server.infrastructure", + "database@sql.management", + "cache@redis.memory", + "queue@messaging.async", + "worker@background.process", + "scheduler@cron.automation", + "webhook@callback.integration", + "oauth@authentication.secure", + "jwt@token.authorization", + "session@state.management", + "cookie@browser.storage", + "localstorage@client.persistence", + "websocket@realtime.communication", + "sse@server.events", + "graphql@query.language", + "rest@api.endpoints", + "soap@legacy.protocol", + "xml@structured.data", + "json@lightweight.format", + "yaml@configuration.files", + "toml@simple.config", + "ini@settings.format", + "env@environment.variables", + "docker@container.platform", + "kubernetes@orchestration.system", + "aws@cloud.services", + "azure@microsoft.cloud", + "gcp@google.platform", + "heroku@deployment.service", + "netlify@static.hosting", + "vercel@frontend.deployment", + "firebase@google.backend", + "supabase@open.alternative", + "mongodb@document.database", + "postgresql@relational.sql", + "mysql@popular.database", + "sqlite@embedded.database", + "redis@inmemory.store", + "elasticsearch@search.engine", + "kafka@streaming.platform", + "rabbitmq@message.broker", + "nginx@web.server", + "apache@http.server", + "nodejs@javascript.runtime", + "python@programming.language", + "java@enterprise.platform", + "csharp@dotnet.framework", + "php@web.development", + "ruby@elegant.language", + "go@google.language", + "rust@systems.programming", + "swift@apple.development", + "kotlin@android.modern", + "typescript@javascript.typed", + "dart@flutter.language", + "scala@jvm.functional", + "clojure@lisp.dialect", + "haskell@pure.functional", + "erlang@concurrent.language", + "elixir@actor.model", + "react@facebook.library", + "vue@progressive.framework", + "angular@google.framework", + "svelte@compile.framework", + "nextjs@react.framework", + "nuxtjs@vue.framework", + "gatsby@static.generator", + "jekyll@ruby.generator", + "hugo@go.generator", + "eleventy@simple.generator", + "wordpress@content.management", + "drupal@flexible.cms", + "joomla@open.cms", + "magento@ecommerce.platform", + "shopify@hosted.ecommerce", + "woocommerce@wordpress.shop", + "prestashop@open.commerce" ] \ No newline at end of file diff --git a/data/enAddress.json b/data/enAddress.json new file mode 100644 index 0000000..1202f61 --- /dev/null +++ b/data/enAddress.json @@ -0,0 +1,42 @@ +[ + "123 Main Street, New York, NY 10001", + "456 Oak Avenue, Los Angeles, CA 90210", + "789 Pine Road, Chicago, IL 60601", + "321 Elm Street, Houston, TX 77001", + "654 Maple Drive, Phoenix, AZ 85001", + "987 Cedar Lane, Philadelphia, PA 19101", + "147 Birch Way, San Antonio, TX 78201", + "258 Spruce Court, San Diego, CA 92101", + "369 Willow Street, Dallas, TX 75201", + "741 Ash Boulevard, San Jose, CA 95101", + "852 Poplar Avenue, Austin, TX 73301", + "963 Cherry Street, Jacksonville, FL 32099", + "159 Walnut Drive, Fort Worth, TX 76101", + "357 Hickory Lane, Columbus, OH 43085", + "486 Sycamore Road, Charlotte, NC 28201", + "792 Magnolia Court, San Francisco, CA 94102", + "138 Dogwood Street, Indianapolis, IN 46201", + "246 Redwood Avenue, Seattle, WA 98101", + "468 Sequoia Drive, Denver, CO 80201", + "579 Cypress Lane, Washington, DC 20001", + "681 Juniper Way, Boston, MA 02101", + "793 Aspen Street, El Paso, TX 79901", + "135 Beech Court, Detroit, MI 48201", + "247 Fir Boulevard, Nashville, TN 37201", + "359 Hemlock Avenue, Portland, OR 97201", + "471 Larch Drive, Oklahoma City, OK 73101", + "583 Palm Street, Las Vegas, NV 89101", + "695 Yew Lane, Louisville, KY 40201", + "807 Alder Road, Baltimore, MD 21201", + "919 Basswood Court, Milwaukee, WI 53201", + "246 Buckeye Street, Albuquerque, NM 87101", + "357 Catalpa Avenue, Tucson, AZ 85701", + "468 Chestnut Drive, Fresno, CA 93701", + "579 Cottonwood Lane, Sacramento, CA 94203", + "681 Hackberry Way, Long Beach, CA 90801", + "793 Hawthorn Street, Kansas City, MO 64101", + "135 Ironwood Court, Mesa, AZ 85201", + "247 Locust Boulevard, Virginia Beach, VA 23451", + "359 Mesquite Avenue, Atlanta, GA 30301", + "471 Mulberry Drive, Colorado Springs, CO 80901" +] \ No newline at end of file diff --git a/data/enFemaleFirstName.json b/data/enFemaleFirstName.json new file mode 100644 index 0000000..47fa25e --- /dev/null +++ b/data/enFemaleFirstName.json @@ -0,0 +1,229 @@ +[ + "Mary", + "Patricia", + "Jennifer", + "Linda", + "Elizabeth", + "Barbara", + "Susan", + "Jessica", + "Sarah", + "Karen", + "Nancy", + "Lisa", + "Betty", + "Helen", + "Sandra", + "Donna", + "Carol", + "Ruth", + "Sharon", + "Michelle", + "Laura", + "Sarah", + "Kimberly", + "Deborah", + "Dorothy", + "Lisa", + "Nancy", + "Karen", + "Betty", + "Helen", + "Sandra", + "Donna", + "Carol", + "Ruth", + "Sharon", + "Michelle", + "Laura", + "Sarah", + "Kimberly", + "Deborah", + "Dorothy", + "Amy", + "Angela", + "Ashley", + "Brenda", + "Emma", + "Olivia", + "Cynthia", + "Marie", + "Janet", + "Catherine", + "Frances", + "Christine", + "Samantha", + "Debra", + "Rachel", + "Carolyn", + "Janet", + "Virginia", + "Maria", + "Heather", + "Diane", + "Julie", + "Joyce", + "Victoria", + "Kelly", + "Christina", + "Joan", + "Evelyn", + "Lauren", + "Judith", + "Megan", + "Cheryl", + "Andrea", + "Hannah", + "Jacqueline", + "Martha", + "Gloria", + "Teresa", + "Sara", + "Janice", + "Marie", + "Julia", + "Heather", + "Diane", + "Ruth", + "Julie", + "Joyce", + "Virginia", + "Victoria", + "Kelly", + "Christina", + "Joan", + "Evelyn", + "Lauren", + "Judith", + "Megan", + "Anna", + "Jacqueline", + "Cheryl", + "Grace", + "Sophia", + "Isabella", + "Ava", + "Mia", + "Charlotte", + "Amelia", + "Olivia", + "Sophia", + "Harper", + "Evelyn", + "Abigail", + "Emily", + "Elizabeth", + "Mila", + "Ella", + "Avery", + "Sofia", + "Camila", + "Aria", + "Scarlett", + "Victoria", + "Madison", + "Luna", + "Grace", + "Chloe", + "Penelope", + "Layla", + "Riley", + "Zoey", + "Nora", + "Lily", + "Eleanor", + "Hannah", + "Lillian", + "Addison", + "Aubrey", + "Ellie", + "Stella", + "Natalie", + "Zoe", + "Leah", + "Hazel", + "Violet", + "Aurora", + "Savannah", + "Audrey", + "Brooklyn", + "Bella", + "Claire", + "Skylar", + "Lucy", + "Paisley", + "Everly", + "Anna", + "Caroline", + "Nova", + "Genesis", + "Emilia", + "Kennedy", + "Samantha", + "Maya", + "Willow", + "Kinsley", + "Naomi", + "Aaliyah", + "Elena", + "Sarah", + "Ariana", + "Allison", + "Gabriella", + "Alice", + "Madelyn", + "Cora", + "Ruby", + "Eva", + "Serenity", + "Autumn", + "Adeline", + "Hailey", + "Gianna", + "Valentina", + "Isla", + "Eliana", + "Quinn", + "Nevaeh", + "Ivy", + "Sadie", + "Piper", + "Lydia", + "Alexa", + "Josephine", + "Emery", + "Julia", + "Delilah", + "Arianna", + "Vivian", + "Kaylee", + "Sophie", + "Brielle", + "Madeline", + "Peyton", + "Rylee", + "Clara", + "Hadley", + "Melanie", + "Mackenzie", + "Reagan", + "Adalynn", + "Liliana", + "Aubree", + "Jade", + "Katherine", + "Isabelle", + "Natalia", + "Raelynn", + "Maria", + "Athena", + "Ximena", + "Arya", + "Leilani", + "Taylor", + "Alyssa", + "Eden", + "Khloe", + "Remi", + "Remington" +] \ No newline at end of file diff --git a/data/enMaleFirstName.json b/data/enMaleFirstName.json new file mode 100644 index 0000000..2da225d --- /dev/null +++ b/data/enMaleFirstName.json @@ -0,0 +1,171 @@ +[ + "James", + "Robert", + "John", + "Michael", + "William", + "David", + "Richard", + "Joseph", + "Thomas", + "Christopher", + "Charles", + "Daniel", + "Matthew", + "Anthony", + "Mark", + "Donald", + "Steven", + "Paul", + "Andrew", + "Kenneth", + "Joshua", + "Kevin", + "Brian", + "George", + "Timothy", + "Ronald", + "Jason", + "Edward", + "Jeffrey", + "Ryan", + "Jacob", + "Gary", + "Nicholas", + "Eric", + "Jonathan", + "Stephen", + "Larry", + "Justin", + "Scott", + "Brandon", + "Benjamin", + "Samuel", + "Gregory", + "Alexander", + "Patrick", + "Frank", + "Raymond", + "Jack", + "Dennis", + "Jerry", + "Tyler", + "Aaron", + "Jose", + "Henry", + "Adam", + "Douglas", + "Nathan", + "Peter", + "Zachary", + "Kyle", + "Noah", + "Alan", + "Ethan", + "Jeremy", + "Lionel", + "Angel", + "Wayne", + "Arthur", + "Sean", + "Carl", + "Harold", + "Bruce", + "Logan", + "Billy", + "Joe", + "Ralph", + "Roy", + "Eugene", + "Louis", + "Philip", + "Bobby", + "Mason", + "Albert", + "Wayne", + "Willie", + "Juan", + "Lawrence", + "Victor", + "Louis", + "Jesse", + "Wayne", + "Ralph", + "Roy", + "Eugene", + "Arthur", + "Carl", + "Harold", + "Bruce", + "Logan", + "Billy", + "Austin", + "Miles", + "Cole", + "Mason", + "Luke", + "Alexander", + "William", + "Benjamin", + "Lucas", + "Henry", + "Theodore", + "Jack", + "Levi", + "Oliver", + "Jackson", + "Mateo", + "Daniel", + "Michael", + "Mason", + "Sebastian", + "Ethan", + "Logan", + "Owen", + "Samuel", + "Jacob", + "Asher", + "Aiden", + "John", + "Joseph", + "Wyatt", + "David", + "Leo", + "Luke", + "Julian", + "Hudson", + "Grayson", + "Matthew", + "Ezra", + "Gabriel", + "Carter", + "Isaac", + "Jayden", + "Luca", + "Anthony", + "Dylan", + "Lincoln", + "Thomas", + "Maverick", + "Elijah", + "Cooper", + "Josiah", + "Hunter", + "Jordan", + "Adrian", + "Nicholas", + "Mason", + "Parker", + "Ian", + "Nolan", + "Jameson", + "Christopher", + "Jaxon", + "Leonardo", + "Axel", + "Everett", + "Kayden", + "Miles", + "Sawyer", + "Jason" +] \ No newline at end of file diff --git a/data/enSurname.json b/data/enSurname.json new file mode 100644 index 0000000..8a6fa30 --- /dev/null +++ b/data/enSurname.json @@ -0,0 +1,532 @@ +[ + "Smith", + "Johnson", + "Williams", + "Brown", + "Jones", + "Garcia", + "Miller", + "Davis", + "Rodriguez", + "Martinez", + "Hernandez", + "Lopez", + "Gonzalez", + "Wilson", + "Anderson", + "Thomas", + "Taylor", + "Moore", + "Jackson", + "Martin", + "Lee", + "Perez", + "Thompson", + "White", + "Harris", + "Sanchez", + "Clark", + "Ramirez", + "Lewis", + "Robinson", + "Walker", + "Young", + "Allen", + "King", + "Wright", + "Scott", + "Torres", + "Nguyen", + "Hill", + "Flores", + "Green", + "Adams", + "Nelson", + "Baker", + "Hall", + "Rivera", + "Campbell", + "Mitchell", + "Carter", + "Roberts", + "Gomez", + "Phillips", + "Evans", + "Turner", + "Diaz", + "Parker", + "Cruz", + "Edwards", + "Collins", + "Reyes", + "Stewart", + "Morris", + "Morales", + "Murphy", + "Cook", + "Rogers", + "Gutierrez", + "Ortiz", + "Morgan", + "Cooper", + "Peterson", + "Bailey", + "Reed", + "Kelly", + "Howard", + "Ramos", + "Kim", + "Cox", + "Ward", + "Richardson", + "Watson", + "Brooks", + "Chavez", + "Wood", + "James", + "Bennett", + "Gray", + "Mendoza", + "Ruiz", + "Hughes", + "Price", + "Alvarez", + "Castillo", + "Sanders", + "Patel", + "Myers", + "Long", + "Ross", + "Foster", + "Jimenez", + "Powell", + "Jenkins", + "Perry", + "Russell", + "Sullivan", + "Bell", + "Coleman", + "Butler", + "Henderson", + "Barnes", + "Gonzales", + "Fisher", + "Vasquez", + "Simmons", + "Romero", + "Jordan", + "Patterson", + "Alexander", + "Hamilton", + "Graham", + "Reynolds", + "Griffin", + "Wallace", + "Moreno", + "West", + "Cole", + "Hayes", + "Bryant", + "Herrera", + "Gibson", + "Ellis", + "Tran", + "Medina", + "Aguilar", + "Stevens", + "Murray", + "Ford", + "Castro", + "Marshall", + "Owens", + "Harrison", + "Fernandez", + "Mcdonald", + "Woods", + "Washington", + "Kennedy", + "Wells", + "Vargas", + "Henry", + "Chen", + "Freeman", + "Webb", + "Tucker", + "Guzman", + "Burns", + "Crawford", + "Olson", + "Simpson", + "Porter", + "Hunter", + "Gordon", + "Mendez", + "Silva", + "Shaw", + "Snyder", + "Mason", + "Dixon", + "Munoz", + "Hunt", + "Hicks", + "Holmes", + "Palmer", + "Wagner", + "Black", + "Robertson", + "Boyd", + "Rose", + "Stone", + "Salazar", + "Fox", + "Warren", + "Mills", + "Meyer", + "Rice", + "Schmidt", + "Garza", + "Daniels", + "Ferguson", + "Nichols", + "Stephens", + "Soto", + "Weaver", + "Ryan", + "Gardner", + "Payne", + "Grant", + "Dunn", + "Kelley", + "Spencer", + "Hawkins", + "Arnold", + "Pierce", + "Vazquez", + "Hansen", + "Peters", + "Santos", + "Hart", + "Bradley", + "Knight", + "Elliott", + "Cunningham", + "Duncan", + "Armstrong", + "Hudson", + "Carroll", + "Lane", + "Riley", + "Andrews", + "Alvarado", + "Ray", + "Delgado", + "Berry", + "Perkins", + "Hoffman", + "Johnston", + "Matthews", + "Pena", + "Richards", + "Contreras", + "Willis", + "Carpenter", + "Lawrence", + "Sandoval", + "Guerrero", + "George", + "Chapman", + "Rios", + "Estrada", + "Ortega", + "Watkins", + "Greene", + "Nunez", + "Wheeler", + "Valdez", + "Harper", + "Burke", + "Larson", + "Santiago", + "Maldonado", + "Morrison", + "Franklin", + "Carlson", + "Austin", + "Dominguez", + "Carr", + "Lawson", + "Jacobs", + "Obrien", + "Lynch", + "Singh", + "Vega", + "Bishop", + "Montgomery", + "Oliver", + "Jensen", + "Harvey", + "Williamson", + "Gilbert", + "Dean", + "Sims", + "Espinoza", + "Howell", + "Li", + "Wong", + "Reid", + "Hanson", + "Le", + "Mccoy", + "Garrett", + "Burton", + "Fuller", + "Wang", + "Weber", + "Welch", + "Rojas", + "Lucas", + "Marquez", + "Fields", + "Park", + "Yang", + "Little", + "Banks", + "Padilla", + "Day", + "Walsh", + "Bowman", + "Schultz", + "Luna", + "Fowler", + "Mejia", + "Davidson", + "Acosta", + "Brewer", + "May", + "Holland", + "Juarez", + "Newman", + "Pearson", + "Curtis", + "Cortez", + "Douglas", + "Schneider", + "Joseph", + "Barrett", + "Navarro", + "Figueroa", + "Keller", + "Avila", + "Wade", + "Molina", + "Stanley", + "Hopkins", + "Campos", + "Barnett", + "Bates", + "Chambers", + "Caldwell", + "Beck", + "Lambert", + "Miranda", + "Byrd", + "Craig", + "Ayala", + "Lowe", + "Frazier", + "Powers", + "Neal", + "Leonard", + "Gregory", + "Carrillo", + "Sutton", + "Fleming", + "Rhodes", + "Shelton", + "Schwartz", + "Norris", + "Jennings", + "Watts", + "Duran", + "Walters", + "Cohen", + "Mcdaniel", + "Moran", + "Parks", + "Steele", + "Vaughn", + "Becker", + "Holt", + "Deleon", + "Barker", + "Terry", + "Hale", + "Leon", + "Hail", + "Benson", + "Haynes", + "Horton", + "Miles", + "Lyons", + "Pham", + "Graves", + "Bush", + "Thornton", + "Wolfe", + "Warner", + "Cabrera", + "Mckinney", + "Mann", + "Zimmerman", + "Dawson", + "Lara", + "Fletcher", + "Page", + "Mccarthy", + "Love", + "Robles", + "Cervantes", + "Solis", + "Erickson", + "Reeves", + "Chang", + "Klein", + "Salinas", + "Fuentes", + "Baldwin", + "Daniel", + "Simon", + "Velazquez", + "Hardy", + "Higgins", + "Aguirre", + "Lin", + "Cummings", + "Chandler", + "Sharp", + "Barber", + "Bowen", + "Ochoa", + "Dennis", + "Robbins", + "Liu", + "Ramsey", + "Francis", + "Griffith", + "Paul", + "Blair", + "Oconnor", + "Cardenas", + "Pacheco", + "Cross", + "Calderon", + "Quinn", + "Moss", + "Swanson", + "Chan", + "Rivas", + "Khan", + "Rodgers", + "Serrano", + "Fitzgerald", + "Rosales", + "Stevenson", + "Christensen", + "Manning", + "Gill", + "Curry", + "Mclaughlin", + "Harmon", + "Mcgee", + "Gross", + "Doyle", + "Garner", + "Newton", + "Burgess", + "Reese", + "Walton", + "Blake", + "Trujillo", + "Adkins", + "Brady", + "Goodman", + "Roman", + "Webster", + "Goodwin", + "Fischer", + "Huang", + "Potter", + "Delacruz", + "Montoya", + "Todd", + "Wu", + "Hines", + "Mullins", + "Castaneda", + "Malone", + "Cannon", + "Tate", + "Mack", + "Sherman", + "Hubbard", + "Hodges", + "Zhang", + "Guerra", + "Wolf", + "Valencia", + "Franco", + "Saunders", + "Rowe", + "Gallagher", + "Farmer", + "Hammond", + "Hampton", + "Townsend", + "Ingram", + "Wise", + "Gallegos", + "Clarke", + "Bautista", + "Colon", + "Mahoney", + "Hurst", + "Hendricks", + "Mcconnell", + "Sanford", + "Mcmahon", + "Waters", + "Kramer", + "Mccormick", + "Vazquez", + "Abbott", + "Price", + "Pearson", + "Mckenzie", + "Frank", + "Monroe", + "Christensen", + "Keller", + "Klein", + "Lowe", + "Lynch", + "Oconnor", + "Garner", + "Fischer", + "Powell", + "Mcgee", + "Weber", + "Lynch", + "Robertson", + "Alvarez", + "Reese", + "Andrews", + "Hubbard", + "Webb", + "Silva", + "Mendez", + "Guerra", + "Burke", + "Jimenez", + "Sanchez", + "Smith" +] \ No newline at end of file diff --git a/data/femaleFirstName.json b/data/femaleFirstName.json index f2b9b50..00d47b3 100644 --- a/data/femaleFirstName.json +++ b/data/femaleFirstName.json @@ -1,116 +1,209 @@ [ - "Ayşe", - "Aslı", - "Asuman", - "Arzu", - "Ayla", - "Bahar", - "Banu", - "Berrin", - "Binnur", - "Burcu", - "Cemile", - "Ceyda", - "Cansu", - "Canan", - "Derya", - "Deniz", - "Duygu", - "Dilek", - "Duru", - "Elif", - "Emine", - "Esra", - "Ebru", - "Ece", - "Fadime", - "Feride", - "Figen", - "Fatma", - "Fulya", - "Gül", - "Gonca", - "Gülden", - "Gülay", - "Gamze", - "Hacer", - "Hale", - "Hande", - "Hilal", - "Hülya", - "Irmak", - "Ilgın", - "Irmak", - "Isparta", - "Jale", - "Janset", - "Jemal", - "Jülide", - "Jale", - "Kader", - "Kamile", - "Kumru", - "Kardelen", - "Kıymet", - "Leyla", - "Lale", - "Leman", - "Lütfiye", - "Lokman", - "Merve", - "Melek", - "Müjde", - "Meryem", - "Mine", - "Nesrin", - "Nuray", - "Nihan", - "Nermin", - "Nurten", - "Oya", - "Oyku", - "Olcay", - "Oktay", - "Oyku", - "Pelin", - "Perihan", - "Pınar", - "Papatya", - "Pelin", - "Rabia", - "Reyhan", - "Rüya", - "Rengin", - "Rabia", - "Şeyma", - "Şule", - "Şebnem", - "Şenay", - "Şermin", - "Tuğba", - "Tuba", - "Tülay", - "Tansu", - "Tuba", - "Ülkü", - "Ümmü", - "Ülker", - "Ülkem", - "Ünzile", - "Vildan", - "Vahide", - "Vildan", - "Vuslat", - "Vildan", - "Yasemin", - "Yeliz", - "Yasemin", - "Yüksel", - "Yasmin", - "Zeynep", - "Züleyha", - "Zehra", - "Zeliha", - "Zerrin" - ] + "Ayşe", + "Aslı", + "Asuman", + "Arzu", + "Ayla", + "Azra", + "Aynur", + "Adalet", + "Acelya", + "Alev", + "Bahar", + "Banu", + "Berrin", + "Binnur", + "Burcu", + "Belgin", + "Berna", + "Beril", + "Beyza", + "Buse", + "Cemile", + "Ceyda", + "Cansu", + "Canan", + "Ceren", + "Çiğdem", + "Çisem", + "Çağla", + "Derya", + "Deniz", + "Duygu", + "Dilek", + "Duru", + "Dilara", + "Defne", + "Damla", + "Dilan", + "Elif", + "Emine", + "Esra", + "Ebru", + "Ece", + "Ela", + "Emel", + "Esin", + "Evrim", + "Eda", + "Fadime", + "Feride", + "Figen", + "Fatma", + "Fulya", + "Funda", + "Filiz", + "Fahriye", + "Ferda", + "Gül", + "Gonca", + "Gülden", + "Gülay", + "Gamze", + "Gizem", + "Gülşen", + "Gönül", + "Güler", + "Hacer", + "Hale", + "Hande", + "Hilal", + "Hülya", + "Hatice", + "Hava", + "Havva", + "Hayriye", + "Irmak", + "İlkay", + "İpek", + "İnci", + "İrem", + "İdil", + "İlknur", + "Jale", + "Jülide", + "Kader", + "Kamile", + "Kumru", + "Kardelen", + "Kıymet", + "Kübra", + "Kezban", + "Leyla", + "Lale", + "Leman", + "Lütfiye", + "Leyla", + "Merve", + "Melek", + "Müjde", + "Meryem", + "Mine", + "Meral", + "Müberra", + "Miray", + "Meltem", + "Nesrin", + "Nuray", + "Nihan", + "Nermin", + "Nurten", + "Neslihan", + "Nilüfer", + "Nazlı", + "Oya", + "Özlem", + "Özge", + "Özgür", + "Pelin", + "Perihan", + "Pınar", + "Papatya", + "Pembe", + "Rabia", + "Reyhan", + "Rüya", + "Rengin", + "Rojda", + "Seda", + "Sevil", + "Sibel", + "Serap", + "Selen", + "Şeyma", + "Şule", + "Şebnem", + "Şenay", + "Şermin", + "Şirin", + "Tuğba", + "Tuba", + "Tülay", + "Tansu", + "Tülin", + "Tülün", + "Ülkü", + "Ümmü", + "Ülker", + "Ülkem", + "Ünzile", + "Vildan", + "Vahide", + "Vuslat", + "Yasemin", + "Yeliz", + "Yüksel", + "Yasmin", + "Yelda", + "Zeynep", + "Züleyha", + "Zehra", + "Zeliha", + "Zerrin", + "Zara", + "Arıf", + "Berkan", + "Cihan", + "Doğa", + "Ecrin", + "Feyza", + "Gaye", + "Handan", + "İlay", + "Jülide", + "Kısmet", + "Lara", + "Mahira", + "Nilgün", + "Olgun", + "Pırıl", + "Rüveyda", + "Sıla", + "Şeyda", + "Tanya", + "Ülkü", + "Vefa", + "Yıldız", + "Zümrüt", + "Asya", + "Büşra", + "Çetin", + "Derin", + "Ezgi", + "Feryal", + "Gürkan", + "Hava", + "İpek", + "Jelal", + "Kadriye", + "Lara", + "Mina", + "Naz", + "Oğul", + "Pırıl", + "Renda", + "Sıla", + "Şevval", + "Tara" +] \ No newline at end of file diff --git a/data/maleFirstName.json b/data/maleFirstName.json index 5048c51..e70658f 100644 --- a/data/maleFirstName.json +++ b/data/maleFirstName.json @@ -1,136 +1,127 @@ [ - "Ahmet", - "Ali", - "Ayhan", - "Arif", - "Adem", - "Barış", - "Burak", - "Berk", - "Bilal", - "Bora", - "Cem", - "Can", - "Cihan", - "Celal", - "Cihat", - "Çağrı", - "Çetin", - "Çınar", - "Çağlar", - "Çetinkaya", - "Doğan", - "Deniz", - "Derviş", - "Devrim", - "Doruk", - "Eren", - "Emre", - "Enes", - "Erkan", - "Ercan", - "Fatih", - "Ferit", - "Fikret", - "Furkan", - "Fırat", - "Gökhan", - "Gürcan", - "Gürkan", - "Güven", - "Güney", - "Hakan", - "Halit", - "Hasan", - "Hüseyin", - "Hüsnü", - "Ilgın", - "Irmak", - "Ilgaz", - "İsmail", - "İlker", - "İlkay", - "İnan", - "İlyas", - "Cemal", - "Kaan", - "Kerem", - "Kaan", - "Kaya", - "Kürşat", - "Levent", - "Lütfü", - "Lezgin", - "Lami", - "Lokman", - "Mustafa", - "Mert", - "Murat", - "Mehmet", - "Mazlum", - "Nail", - "Necmi", - "Nihat", - "Nuh", - "Nuri", - "Oğuz", - "Onur", - "Osman", - "Oktay", - "Orhan", - "Ömer", - "Özgür", - "Özkan", - "Özhan", - "Pamir", - "Polat", - "Poyraz", - "Pınar", - "Ramazan", - "Raşit", - "Recep", - "Rüzgar", - "Rıza", - "Rıfat", - "Sercan", - "Selim", - "Sinan", - "Sadi", - "Savaş", - "Şükrü", - "Şeref", - "Şahin", - "Şafak", - "Şevket", - "Tolga", - "Tarkan", - "Tayyar", - "Tansu", - "Talat", - "Ufuk", - "Umut", - "Utku", - "Uğur", - "Uysal", - "Ümit", - "Ünal", - "Ülkü", - "Ülkem", - "Üzeyir", - "Volkan", - "Veysel", - "Vedat", - "Veli", - "Vural", - "Yasin", - "Yalın", - "Yavuz", - "Yunus", - "Yiğit", - "Zafer", - "Zeki", - "Zülfikar", - "Ziya", - "Zümrüt" - ] + "Ahmet", + "Ali", + "Mehmet", + "Abdullah", + "Abdurrahman", + "Adnan", + "Akif", + "Alparslan", + "Berat", + "Burak", + "Bayram", + "Berkay", + "Batuhan", + "Bülent", + "Bahadır", + "Can", + "Cem", + "Cengiz", + "Ceyhun", + "Caner", + "Cemil", + "Cafer", + "Çetin", + "Çağdaş", + "Çağatay", + "Deniz", + "Dursun", + "Davut", + "Duran", + "Erdal", + "Emre", + "Erol", + "Emir", + "Erdem", + "Ergin", + "Erhan", + "Fatih", + "Ferhat", + "Faruk", + "Fazıl", + "Fuat", + "Gökhan", + "Gökmen", + "Gürsel", + "Galip", + "Hasan", + "Halil", + "Hamit", + "Haydar", + "Hilmi", + "İbrahim", + "İsmail", + "İdris", + "İhsan", + "İrfan", + "Kemal", + "Kaan", + "Kerem", + "Kaya", + "Kürşat", + "Kadir", + "Kamil", + "Kazım", + "Levent", + "Lütfü", + "Lezgin", + "Murat", + "Mahmut", + "Metin", + "Muharrem", + "Musa", + "Nihat", + "Necdet", + "Nazım", + "Orhan", + "Ömer", + "Özkan", + "Özdemir", + "Pamir", + "Polat", + "Poyraz", + "Recep", + "Rifat", + "Serkan", + "Salih", + "Semih", + "Sedat", + "Serdar", + "Seyit", + "Şahin", + "Şaban", + "Tolga", + "Tuncay", + "Tuğrul", + "Ufuk", + "Veli", + "Yaşar", + "Yusuf", + "Yakup", + "Zafer", + "Zeynel", + "Adil", + "Akın", + "Atilla", + "Aziz", + "Bekir", + "Cahit", + "Cemal", + "Engin", + "Ertuğrul", + "Fahrettin", + "Haluk", + "İzzet", + "Kahraman", + "Latif", + "Mesut", + "Nihat", + "Orhan", + "Rıdvan", + "Süleyman", + "Tahsin", + "Vecdi", + "Yılmaz", + "Ziyad" +] \ No newline at end of file diff --git a/data/password.json b/data/password.json index a76f0b7..3f800ab 100644 --- a/data/password.json +++ b/data/password.json @@ -1,86 +1,230 @@ [ - "G3l1ş1m5h", - "K0dL@r1m", - "Pr0j3Y0n3t1m", - "Güv3nL!k2o2", - "T3kNoloj1F0rum", - "P@r0l@G1zle", - "Y4z1l1mDuny4s1", - "S1fr3s1zl1k", - "Y@z1l!m@Ş3h!r", - "B!lg!Güv3nL!ği", - "K0dY@z1l!m", - "S1b3rGüv3nL!k", - "Ş1fr3l3n3nDuny4", - "G3l1ş1m3", - "Y@zılımD3st3k", - "Pr0j3Y0n3t1m2", - "Güv3nL!k123", - "B!lg!Güv3nL!ğ1", - "Ş1fr3l3", - "S1fr3L0g", - "Y@z1l!mT3kn0l0j!s1", - "B!lg!Yönt3m", - "Pr0j3Y0n3t1m3", - "Güv3nL!k456", - "S1f3rS1fr3", - "Ş1fr3K0d", - "G3l1ş1m4", - "Y@z1l!mY@z1l!m", - "Pr0j3Y0n3t1m4", - "Güv3nL!k789", - "B!lg!Y@zılım", - "Ş1fr3l3nm1ş", - "S1f3rT3kn0l0j1", - "G3l1ş1m5", - "Y@z1l!mB3lg!s1", - "Pr0j3Y0n3t1m5", - "Güv3nL!kABC", - "B!lg!Y@zılım2", - "Ş1fr3Kod1", - "S1f3rGüv3nL!k", - "G3l1ş1m6", - "Y@z1l!mY3nt3m", - "Pr0j3Y0n3t1m6", - "Güv3nL!kDEF", - "B!lg!Y@zılım3", - "Ş1fr3Kod2", - "S1f3rGüv3nL!k1", - "G3l1ş1m7", - "Y@z1l!mY0nt3m", - "Pr0j3Y0n3t1m7", - "Güv3nL!kGHI", - "B!lg!Y@zılım4", - "Ş1fr3Kod3", - "S1f3rGüv3nL!k2", - "G3l1ş1m8", - "Y@z1l!mY@zılım", - "Pr0j3Y0n3t1m8", - "Güv3nL!kJKL", - "B!lg!Y@zılım5", - "Ş1fr3Kod4", - "S1f3rGüv3nL!k3", - "G3l1ş1m9", - "Y@z1l!mB3lg!l3r1", - "Pr0j3Y0n3t1m9", - "Güv3nL!kMNO", - "B!lg!Y@zılım6", - "Ş1fr3Kod5", - "S1f3rGüv3nL!k4", - "G3l1ş1m10", - "Y@z1l!mB3lg!l3r2", - "Pr0j3Y0n3t1m10", - "Güv3nL!kPQR", - "B!lg!Y@zılım7", - "Ş1fr3Kod6", - "S1f3rGüv3nL!k5", - "password123", - "123456789", - "123456", - "12345678", - "1234567890", - "12345678901", - "123456789012", - "1234567890123" - ] + "G3l1ş1m5h", + "K0dL@r1m", + "Pr0j3Y0n3t1m", + "Güv3nL!k2o2", + "T3kNoloj1F0rum", + "P@r0l@G1zle", + "Y4z1l1mDuny4s1", + "S1fr3s1zl1k", + "Y@z1l!m@Ş3h!r", + "B!lg!Güv3nL!ği", + "K0dY@z1l!m", + "S1b3rGüv3nL!k", + "Ş1fr3l3n3nDuny4", + "G3l1ş1m3", + "Y@zılımD3st3k", + "Pr0j3Y0n3t1m2", + "Güv3nL!k123", + "B!lg!Güv3nL!ğ1", + "Ş1fr3l3", + "S1fr3L0g", + "Y@z1l!mT3kn0l0j!s1", + "B!lg!Yönt3m", + "Pr0j3Y0n3t1m3", + "Güv3nL!k456", + "S1f3rS1fr3", + "Ş1fr3K0d", + "G3l1ş1m4", + "Y@z1l!mY@z1l!m", + "Pr0j3Y0n3t1m4", + "Güv3nL!k789", + "B!lg!Y@zılım", + "Ş1fr3l3nm1ş", + "S1f3rT3kn0l0j1", + "G3l1ş1m5", + "Y@z1l!mB3lg!s1", + "Pr0j3Y0n3t1m5", + "Güv3nL!kABC", + "B!lg!Y@zılım2", + "Ş1fr3Kod1", + "S1f3rGüv3nL!k", + "G3l1ş1m6", + "Y@z1l!mY3nt3m", + "Pr0j3Y0n3t1m6", + "Güv3nL!kDEF", + "B!lg!Y@zılım3", + "Ş1fr3Kod2", + "S1f3rGüv3nL!k1", + "G3l1ş1m7", + "Y@z1l!mY0nt3m", + "Pr0j3Y0n3t1m7", + "Güv3nL!kGHI", + "B!lg!Y@zılım4", + "Ş1fr3Kod3", + "S1f3rGüv3nL!k2", + "G3l1ş1m8", + "Y@z1l!mY@zılım", + "Pr0j3Y0n3t1m8", + "Güv3nL!kJKL", + "B!lg!Y@zılım5", + "Ş1fr3Kod4", + "S1f3rGüv3nL!k3", + "G3l1ş1m9", + "Y@z1l!mB3lg!l3r1", + "Pr0j3Y0n3t1m9", + "Güv3nL!kMNO", + "B!lg!Y@zılım6", + "Ş1fr3Kod5", + "S1f3rGüv3nL!k4", + "G3l1ş1m10", + "Y@z1l!mB3lg!l3r2", + "Pr0j3Y0n3t1m10", + "Güv3nL!kPQR", + "B!lg!Y@zılım7", + "Ş1fr3Kod6", + "S1f3rGüv3nL!k5", + "V3r1T4b4n1!", + "M0d3rn@P4ssw0rd", + "S4f3&S3cur3!", + "K0mpl3ks$1fr3", + "Güçlü#Ş1fr3", + "D1j1t4l&Düny4", + "T3kn0@G3l3c3k", + "Y3n1Ç4ğ#2024", + "S1b3r@Sp4c3", + "K0d&G3l1şt1r", + "B1lg1$4y4r", + "Pr0t3k$1y0n", + "V3r1#Güv3nl1k", + "S1st3m@Yön3t1c1", + "D4t4B4s3&Mgmt", + "W3b#D3v3l0pm3nt", + "M0b1l3$4pp", + "Cl0ud&C0mput1ng", + "A1&M4ch1n3L3rn", + "Bl0ckCh41n#T3ch", + "I0T&Sm4rtD3v1c3", + "C1b3r$3cur1ty", + "D1g1t4l@Tr4nsf0rm", + "1nn0v4t10n#L4b", + "T3ch$St4rtup", + "C0d1ng&Pr0gr4m", + "S0ftw4r3#Eng1n33r", + "D3v0ps&4ut0m4t10n", + "4g1l3@M3th0d0l0gy", + "Sc4l4bl3$Syst3m", + "M1cr0s3rv1c3#4rch", + "4P1&1nt3gr4t10n", + "D4t4$V1su4l1z4t10n", + "M4ch1n3@L34rn1ng", + "D33p&N3ur4lN3tw0rk", + "4rt1f1c14l#1nt3ll", + "Q4ntum$C0mput1ng", + "V1rtu4l@R34l1ty", + "4ugm3nt3d#R34l1ty", + "1mm3rs1v3$T3ch", + "G4m3@D3v3l0pm3nt", + "3$p0rts&G4m1ng", + "Str34m1ng#T3ch", + "S0c14l@M3d14", + "D1g1t4l$M4rk3t1ng", + "3C0mm3rc3#Pl4tf0rm", + "F1nT3ch&1nn0v4t10n", + "Cr1pt0@Curr3ncy", + "NFT&D1g1t4lA4rt", + "M3t4v3rs3#3xp3r13nc3", + "W3b3&D3c3ntr4l1z3d", + "Sm4rt$C0ntr4ct", + "D40&Bl0ckCh41n", + "C0ns3nsus@M3ch4n1sm", + "D1str1but3d#L3dg3r", + "P33r2P33r$N3tw0rk", + "D3c3ntr4l1z3d@F1n4nc3", + "Y13ld&F4rm1ng", + "L1qu1d1ty$P00l", + "St4k1ng@R3w4rds", + "G0v3rn4nc3#T0k3n", + "D40&V0t1ng", + "C0mmun1ty@Dr1v3n", + "0p3nS0urc3#Pr0j3ct", + "C0ll4b0r4t1v3$D3v", + "R3m0t3@W0rk", + "D1g1t4l#N0m4d", + "W0rk&L1f3B4l4nc3", + "M1ndfuln3ss$T3ch", + "W3llb31ng@4pp", + "H34lth#M0n1t0r1ng", + "F1tn3ss$Tr4ck3r", + "Nutr1t10n@4n4lys1s", + "Sl33p&0pt1m1z4t10n", + "M3nt4l#H34lthT3ch", + "Th3r4py$4pp", + "M3d1t4t10n@Gu1d3", + "Y0g4&M1ndfuln3ss", + "Str3ss$M4n4g3m3nt", + "password123", + "123456", + "qwerty", + "admin", + "letmein", + "welcome", + "monkey", + "sunshine", + "shadow", + "password1", + "123123", + "dragon", + "princess", + "football", + "master", + "welcome123", + "trustno1", + "starwars", + "freedom", + "computer", + "batman", + "superman", + "michael", + "jordan", + "hello", + "killer", + "silver", + "access", + "whatever", + "696969", + "pepper", + "buster", + "soccer", + "hockey", + "charlie", + "maggie", + "guitar", + "orange", + "banana", + "purple", + "flower", + "summer", + "winter", + "spring", + "autumn", + "rainbow", + "dolphin", + "angel", + "tiger", + "cheese", + "coffee", + "cookie", + "forever", + "garden", + "heaven", + "island", + "jungle", + "castle", + "bridge", + "forest", + "hunter", + "knight", + "magic", + "nature", + "ocean", + "peace", + "queen", + "river", + "spirit", + "thunder", + "unity", + "victory", + "wisdom" +] \ No newline at end of file diff --git a/data/surname.json b/data/surname.json index 4ac6143..8808246 100644 --- a/data/surname.json +++ b/data/surname.json @@ -1,98 +1,180 @@ [ - "Yılmaz", - "Kaya", - "Demir", - "Çelik", - "Arslan", - "Koç", - "Güneş", - "Aydın", - "Türk", - "Kurt", - "Erbay", - "Aksoy", - "Karadeniz", - "Uçar", - "Başaran", - "Yalçın", - "Tekin", - "Öztürk", - "Can", - "Büyükkaya", - "Bilgin", - "Ceylan", - "Dağdelen", - "Durmaz", - "Özkan", - "Erdoğan", - "Göktürk", - "Şahin", - "Sezer", - "Sönmez", - "Şen", - "Yıldız", - "Tuncer", - "Bilir", - "Taşkın", - "Ünlü", - "Avcı", - "Gür", - "Erdem", - "Kaplan", - "Güzel", - "Yalın", - "Kılıç", - "Kurtuluş", - "Şeker", - "Bulut", - "Aykan", - "Karaman", - "Yavuz", - "Koçak", - "Turan", - "Çetin", - "Alkan", - "Aslan", - "Dinçer", - "Gündoğdu", - "Yücel", - "Demirtaş", - "Özdemir", - "Türkoğlu", - "Eren", - "Cengiz", - "Demirci", - "Çetinkaya", - "Balcı", - "Kasap", - "Karagöz", - "Güngör", - "Arıcan", - "Uzun", - "Toprak", - "Yıldırım", - "Özmen", - "Özdemir", - "Yıldız", - "Koçyiğit", - "Koçak", - "Karakaş", - "Tosun", - "Akgün", - "Kırıcı", - "Oğuz", - "Yüksel", - "Bulut", - "Erdal", - "Ateş", - "Aktaş", - "Akyüz", - "Yurtsever", - "Yılmazer", - "Görgülü", - "Karakaya", - "Karataş", - "Yıldız", - "Yaman" - ] + "Yılmaz", + "Kaya", + "Demir", + "Çelik", + "Arslan", + "Koç", + "Güneş", + "Aydın", + "Türk", + "Kurt", + "Erbay", + "Aksoy", + "Karadeniz", + "Uçar", + "Başaran", + "Yalçın", + "Tekin", + "Öztürk", + "Can", + "Büyükkaya", + "Bilgin", + "Ceylan", + "Dağdelen", + "Durmaz", + "Özkan", + "Erdoğan", + "Göktürk", + "Şahin", + "Sezer", + "Sönmez", + "Şen", + "Yıldız", + "Tuncer", + "Bilir", + "Taşkın", + "Ünlü", + "Avcı", + "Gür", + "Erdem", + "Kaplan", + "Güzel", + "Yalın", + "Kılıç", + "Kurtuluş", + "Şeker", + "Bulut", + "Aykan", + "Karaman", + "Yavuz", + "Koçak", + "Turan", + "Çetin", + "Alkan", + "Aslan", + "Dinçer", + "Gündoğdu", + "Yücel", + "Demirtaş", + "Özdemir", + "Türkoğlu", + "Eren", + "Cengiz", + "Demirci", + "Çetinkaya", + "Balcı", + "Kasap", + "Karagöz", + "Güngör", + "Arıcan", + "Uzun", + "Toprak", + "Yıldırım", + "Özmen", + "Karakaş", + "Tosun", + "Akgün", + "Kırıcı", + "Oğuz", + "Yüksel", + "Erdal", + "Ateş", + "Aktaş", + "Akyüz", + "Yurtsever", + "Yılmazer", + "Görgülü", + "Karakaya", + "Karataş", + "Yaman", + "Bayrak", + "Bozkurt", + "Çakır", + "Duman", + "Erkin", + "Fidan", + "Gökçe", + "Hazar", + "İşler", + "Kartal", + "Levent", + "Meral", + "Nazlı", + "Oral", + "Polat", + "Rençber", + "Sarı", + "Turgut", + "Uysal", + "Vural", + "Yener", + "Zorlu", + "Akay", + "Başar", + "Candan", + "Dost", + "Elmas", + "Fırat", + "Gençer", + "Hakim", + "İnce", + "Karadağ", + "Liman", + "Mutlu", + "Nalçacı", + "Okur", + "Peker", + "Rüzgar", + "Sever", + "Tanrıverdi", + "Uluç", + "Varol", + "Yakar", + "Zengin", + "Adıgüzel", + "Baş", + "Çakmak", + "Deniz", + "Evren", + "Fındık", + "Gazi", + "Hazer", + "İçli", + "Kaynak", + "Leylek", + "Mavioğlu", + "Nas", + "Okan", + "Pamuk", + "Reşit", + "Solmaz", + "Teker", + "Uğurlu", + "Verimli", + "Yaşar", + "Zenginer", + "Altın", + "Berber", + "Çiftçi", + "Diker", + "Erol", + "Fırın", + "Gider", + "Hacı", + "İmar", + "Kader", + "Lider", + "Maden", + "Nalbur", + "Ocak", + "Pala", + "Reis", + "Sağlam", + "Tuna", + "Usta", + "Vatan", + "Yazgı", + "Zaman" +] \ No newline at end of file diff --git a/manifest.json b/manifest.json index a859cac..386b2b2 100644 --- a/manifest.json +++ b/manifest.json @@ -1,8 +1,9 @@ { "manifest_version": 3, "name": "Test String Generator", - "version": "1.0.0", - "description": "A lightweight Chrome extension designed for test data generation and Turkish localization.", + "version": "1.1.0", + "description": "A lightweight Chrome extension designed for test data generation and multi-language localization.", + "update_url": "https://clients2.google.com/service/update2/crx", "icons": { "16": "assets/icon16.png", "32": "assets/icon32.png", @@ -18,8 +19,14 @@ "permissions": [ "activeTab", "clipboardRead", - "clipboardWrite" + "clipboardWrite", + "storage", + "notifications" ], + "web_accessible_resources": [{ + "resources": ["data/*.json"], + "matches": [""] + }], "background": { "service_worker": "background.js" } diff --git a/popup.html b/popup.html index e5d421d..37b402c 100644 --- a/popup.html +++ b/popup.html @@ -1,102 +1,202 @@ - - - - - Test String Generator - - -
-

Test String Generator

+ + + + Test String Generator + + + +
+
+ +
+

Test String Generator

+ +
- - - + + +
-
- +
+
+ +
+ +
+
- - - +
+ + + +
- - - + + +
- +
- Characters: 0 | Words: 0 | Lines: 0 -
- -
- + + + + + - -
+ +
- +
- + - + - + +
+ +
+
+ + +
+ +
+ + +
- - - + + +
- + + + + + + + + - + +
+ diff --git a/src/css/popup.css b/src/css/popup.css index ed7392d..188dcd7 100644 --- a/src/css/popup.css +++ b/src/css/popup.css @@ -2,74 +2,129 @@ --primary-color: #2196F3; --secondary-color: #90CAF9; --background-color: #FFFFFF; + --surface-color: #F8F9FA; --text-color: #333333; + --text-secondary: #666666; --border-color: #E0E0E0; --shadow-color: rgba(0, 0, 0, 0.1); --radius: 8px; + --radius-large: 12px; --spacing: 16px; + --header-bg: linear-gradient(135deg, var(--primary-color), #1976D2); + --transition: all 0.2s ease; +} + +[data-theme="dark"] { + --primary-color: #2196F3; + --secondary-color: #1565C0; + --background-color: #1E1E1E; + --surface-color: #2D2D2D; + --text-color: #FFFFFF; + --text-secondary: #B0B0B0; + --border-color: #404040; + --shadow-color: rgba(0, 0, 0, 0.3); + --header-bg: linear-gradient(135deg, #1976D2, #0D47A1); +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; } body { width: 350px; margin: 0; - margin-top: 10px; - padding: 12px; - font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', sans-serif; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', sans-serif; background-color: var(--background-color); color: var(--text-color); - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - text-rendering: optimizeLegibility; -} - -/* Remove global font smoothing and apply selectively */ -* { - -webkit-font-smoothing: auto; - -moz-osx-font-smoothing: auto; + font-size: 14px; + line-height: 1.5; + transition: var(--transition); + overflow-x: hidden; } .app-container { display: flex; flex-direction: column; - gap: var(--spacing); } -h1 { - font-size: 16px; - font-weight: 500; - text-align: center; - margin: 0 0 var(--spacing); - color: var(--text-color); - letter-spacing: -0.02em; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; +/* Header Styles */ +.app-header { + background: var(--header-bg); + color: white; + padding: 12px; + display: flex; + justify-content: space-between; + align-items: center; + box-shadow: 0 2px 8px var(--shadow-color); + position: relative; +} + +.app-header h1 { + font-size: 18px; + font-weight: 600; + margin: 0; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); } -/* Tabs */ +.settings-button { + background: rgba(255, 255, 255, 0.2); + border: none; + border-radius: 50%; + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: var(--transition); + color: white; +} + +.settings-button:hover { + background: rgba(255, 255, 255, 0.3); + transform: rotate(90deg); +} + +.settings-button svg { + width: 20px; + height: 20px; +} + +/* Main Content */ .tabs { display: flex; - gap: 8px; - margin-bottom: var(--spacing); + gap: 4px; + padding: 12px; + padding-bottom: 0; + background: var(--background-color); } .tab-button { flex: 1; - padding: 10px; + padding: 12px 8px; border: none; - background: var(--secondary-color); - color: var(--text-color); + background: var(--surface-color); + color: var(--text-secondary); border-radius: var(--radius); cursor: pointer; font-weight: 500; - transition: all 0.2s ease; - letter-spacing: -0.01em; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + font-size: 13px; + transition: var(--transition); + border: 1px solid var(--border-color); +} + +.tab-button:hover { + background: var(--secondary-color); + color: white; } .tab-button.active { background: var(--primary-color); color: white; + box-shadow: 0 2px 4px rgba(33, 150, 243, 0.3); } /* Content Areas */ @@ -77,39 +132,156 @@ h1 { display: none; flex-direction: column; gap: var(--spacing); + padding: 12px; } .tab-content.active { display: flex; } -/* Form Elements */ -.input-group { - display: flex; +.option-group { + display: none; flex-direction: column; gap: 12px; } +.option-group.active { + display: flex; +} + +.length-input-container { + display: flex; + gap: 8px; + align-items: stretch; +} + +.length-input-container input { + flex: 1; +} + +.unit-toggle { + display: flex; +} + +.unit-toggle-btn { + padding: 8px 12px; + border: 1px solid var(--border-color); + background: var(--surface-color); + color: var(--text-color); + border-radius: var(--radius); + cursor: pointer; + transition: var(--transition); + display: flex; + align-items: center; + gap: 6px; + font-size: 12px; + font-weight: 500; + min-width: 90px; + justify-content: space-between; +} + +.unit-toggle-btn:hover { + background: var(--secondary-color); + color: white; +} + +.unit-toggle-btn[data-unit="words"] { + background: var(--primary-color); + color: white; + border-color: var(--primary-color); +} + +.toggle-icon { + width: 16px; + height: 16px; + transition: transform 0.2s ease; +} + +.unit-toggle-btn[data-unit="words"] .toggle-icon { + transform: rotate(180deg); +} + +.checkbox-row { + display: flex; + gap: 16px; + flex-wrap: wrap; +} + +/* Bulk Generation Options */ +.bulk-options { + background: var(--surface-color); + border: 1px solid var(--border-color); + border-radius: var(--radius); + padding: 12px; + margin: 8px 0; +} + +.bulk-row { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 8px; +} + +.bulk-row:last-child { + margin-bottom: 0; +} + +.bulk-label { + font-size: 13px; + font-weight: 500; + color: var(--text-color); + min-width: 60px; +} + +.bulk-input { + flex: 1; + padding: 6px 7px !important; + border: 1px solid var(--border-color); + border-radius: var(--radius); + background: var(--background-color); + color: var(--text-color); + font-size: 13px; +} + +.bulk-select { + flex: 1; + padding: 6px 8px; + border: 1px solid var(--border-color); + border-radius: var(--radius); + background: var(--background-color); + color: var(--text-color); + font-size: 13px; +} + +/* Form Inputs */ input[type="number"], input[type="text"], select, textarea { width: 100%; - padding: 12px; + padding: 10px; border: 1px solid var(--border-color); border-radius: var(--radius); - background: white; + background: var(--surface-color); + color: var(--text-color); font-size: 14px; - box-sizing: border-box; - -webkit-font-smoothing: auto; - -moz-osx-font-smoothing: auto; - font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', sans-serif; + font-family: inherit; + transition: var(--transition); +} + +input:focus, +select:focus, +textarea:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1); } textarea { - min-height: 120px; + min-height: 80px; + max-height: 160px; resize: vertical; - font-family: inherit; } /* Checkboxes and Radio Buttons */ @@ -119,25 +291,30 @@ textarea { align-items: center; gap: 8px; cursor: pointer; + padding: 8px 0; +} + +.checkbox-wrapper input, +.radio-wrapper input { + width: auto; + margin: 0; } /* Buttons */ .primary-button, .secondary-button { - width: 90%; - padding: 10px; + width: 100%; + padding: 12px; border: none; border-radius: var(--radius); font-weight: 500; - align-self: start; - /* center the button! */ - margin: 0 auto; + font-size: 14px; cursor: pointer; - transition: all 0.2s ease; - font-family: ui-sans-serif, system-ui, -apple-system, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', Arial, sans-serif; - letter-spacing: -0.01em; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + transition: var(--transition); + display: flex; + align-items: center; + justify-content: center; + gap: 8px; } .primary-button { @@ -145,157 +322,351 @@ textarea { color: white; } +.primary-button:hover { + background: #1976D2; + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(33, 150, 243, 0.3); +} + .secondary-button { - background: var(--secondary-color); + background: var(--surface-color); color: var(--text-color); + border: 1px solid var(--border-color); +} + +.secondary-button:hover { + background: var(--border-color); } /* Counter Stats */ .counter-stats { + font-size: 13px; + color: var(--text-secondary); + padding: 12px; + background: var(--surface-color); + border-radius: var(--radius); + border: 1px solid var(--border-color); +} + +.stats-row { + display: flex; + justify-content: space-around; + margin-bottom: 8px; +} + +.stats-row:last-child { + margin-bottom: 0; +} + +.stat-item { + display: flex; + flex-direction: column; + align-items: center; text-align: center; - font-size: 14px; + min-width: 60px; +} + +.stat-label { + font-size: 11px; + color: var(--text-secondary); + margin-bottom: 2px; +} + +.stat-value { + font-size: 16px; + font-weight: 600; color: var(--text-color); - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; } /* Option Groups */ .option-group { display: none; + flex-direction: column; gap: 12px; padding: 12px; - background: #F5F5F5; + background: var(--surface-color); border-radius: var(--radius); + border: 1px solid var(--border-color); } -/* Feedback Messages */ -.feedback { +.option-group.active { + display: flex; +} + +/* Modal Styles */ +.modal { position: fixed; - bottom: 20px; - left: 50%; - transform: translateX(-50%); - padding: 12px 24px; - border-radius: var(--radius); - background: var(--primary-color); + top: 0; + left: 0; + width: 100%; + height: 100%; + background: var(--background-color); + display: flex; + flex-direction: column; + z-index: 1000; + opacity: 0; + visibility: hidden; + transition: var(--transition); +} + +.modal[style*="display: none"] { + display: none !important; +} + +.modal.active { + opacity: 1; + visibility: visible; +} + +.modal-content { + background: var(--background-color); + width: 100%; + height: 100%; + overflow-y: auto; + display: flex; + flex-direction: column; + transition: var(--transition); +} + +.modal.active .modal-content { + transform: none; +} + +.modal-header { + padding: 16px; + border-bottom: 1px solid var(--border-color); + display: flex; + justify-content: space-between; + align-items: center; + background: var(--surface-color); + min-height: 60px; +} + +.modal-header h2 { + font-size: 18px; + font-weight: 600; + color: var(--text-color); +} + +.close-button { + background: none; + border: none; + font-size: 24px; + color: var(--text-secondary); + cursor: pointer; + padding: 0; + width: 36px; + height: 36px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + transition: var(--transition); +} + +.close-button:hover { + background: var(--border-color); + color: var(--text-color); +} + +.close-button:active { + background: var(--secondary-color); color: white; - font-weight: 500; - box-shadow: 0 2px 8px var(--shadow-color); - animation: slideUp 0.3s ease; } -@keyframes slideUp { - from { transform: translate(-50%, 20px); opacity: 0; } - to { transform: translate(-50%, 0); opacity: 1; } +.modal-body { + padding: 20px; + flex: 1; + overflow-y: auto; } -/* Enhanced Retina Display Support */ -@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { - body { - font-size: 14px; - } - - input, select, textarea { - font-size: 16px; - } +.setting-group { + margin-bottom: 24px; +} - .tab-button { - font-weight: 500; - } +.setting-group:last-child { + margin-bottom: 0; +} - textarea { - line-height: 1.5; - } +.setting-label { + display: block; + font-weight: 500; + margin-bottom: 8px; + color: var(--text-color); } -/* Specific text rendering for UI elements */ -h1, -.tab-button, -.primary-button, -.secondary-button, -.checkbox-label, -.radio-label, -.counter-stats { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - letter-spacing: -0.01em; +/* Theme Selector */ +.theme-selector { + display: flex; + gap: 8px; } -/* Input and textarea specific rendering */ -input, select, textarea { - -webkit-font-smoothing: auto; - -moz-osx-font-smoothing: auto; - font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', 'Helvetica Neue', sans-serif; - font-size: 14px; +.theme-button { + flex: 1; + padding: 10px; + border: 1px solid var(--border-color); + background: var(--surface-color); + color: var(--text-color); + border-radius: var(--radius); + cursor: pointer; + transition: var(--transition); + font-size: 13px; + font-weight: 500; +} + +.theme-button:hover { + background: var(--secondary-color); + color: white; } -.tab-button, .primary-button, .secondary-button { - font-family: ui-sans-serif, system-ui, -apple-system, 'SF Pro Display', 'SF Pro Text', 'Helvetica Neue', Arial, sans-serif; - letter-spacing: -0.01em; +.theme-button.active { + background: var(--primary-color); + color: white; + border-color: var(--primary-color); } /* Support Links */ .support-links { display: flex; - justify-content: center; - gap: 16px; - margin-top: 16px; - padding-top: 16px; - border-top: 1px solid var(--border-color); + flex-direction: column; + gap: 12px; } .support-link { display: flex; align-items: center; - gap: 6px; - padding: 8px 12px; - background: #f8f9fa; - border: 1px solid var(--border-color); - border-radius: var(--radius); + gap: 12px; + padding: 12px; + background: var(--surface-color); color: var(--text-color); text-decoration: none; - font-size: 12px; - font-weight: 500; - transition: all 0.2s ease; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + border-radius: var(--radius); + border: 1px solid var(--border-color); + transition: var(--transition); + font-size: 14px; } .support-link:hover { background: var(--primary-color); color: white; - border-color: var(--primary-color); transform: translateY(-1px); - box-shadow: 0 2px 8px var(--shadow-color); + box-shadow: 0 4px 8px rgba(33, 150, 243, 0.2); } .support-icon { - width: 16px; - height: 16px; + width: 20px; + height: 20px; flex-shrink: 0; } -/* Buy Me a Coffee specific styling */ -.support-link:first-child { - background: #ffdd00; - border-color: #ffdd00; - color: #000; +/* Loading Overlay */ +.loading-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.7); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + z-index: 2000; + color: white; + font-size: 16px; + font-weight: 500; } -.support-link:first-child:hover { - background: #ffd700; - border-color: #ffd700; - color: #000; +.loading-spinner { + width: 40px; + height: 40px; + border: 3px solid rgba(255, 255, 255, 0.3); + border-top: 3px solid white; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 16px; } -/* GitHub specific styling */ -.support-link:last-child { - background: #24292e; - border-color: #24292e; - color: white; +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } } -.support-link:last-child:hover { - background: #2f363d; - border-color: #2f363d; +/* Feedback Messages */ +.feedback { + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + padding: 12px 24px; + border-radius: var(--radius); color: white; + font-weight: 500; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + z-index: 1500; + animation: slideUp 0.3s ease; + max-width: 90%; + text-align: center; +} + +.feedback.success { + background: #4CAF50; +} + +.feedback.error { + background: #F44336; +} + +@keyframes slideUp { + from { + transform: translate(-50%, 20px); + opacity: 0; + } + to { + transform: translate(-50%, 0); + opacity: 1; + } +} + +/* Extension Fixed Width - No Responsive */ + +/* Focus Styles for Accessibility */ +button:focus-visible, +input:focus-visible, +select:focus-visible, +textarea:focus-visible { + outline: 2px solid var(--primary-color); + outline-offset: 2px; +} + +/* Print Styles */ +@media print { + .app-header, + .settings-button, + .modal, + .loading-overlay { + display: none !important; + } +} + +/* High Contrast Mode */ +@media (prefers-contrast: high) { + :root { + --border-color: #000000; + --text-color: #000000; + } + + [data-theme="dark"] { + --border-color: #FFFFFF; + --text-color: #FFFFFF; + } +} + +/* Reduced Motion */ +@media (prefers-reduced-motion: reduce) { + * { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } } \ No newline at end of file diff --git a/src/js/i18n.js b/src/js/i18n.js new file mode 100644 index 0000000..1454d01 --- /dev/null +++ b/src/js/i18n.js @@ -0,0 +1,227 @@ +// Internationalization (i18n) System +class I18n { + constructor() { + this.currentLanguage = 'en'; + this.translations = { + en: { + // App + 'app-title': 'Test String Generator', + 'loading': 'Loading...', + + // Tabs + 'tab-generator': 'Generator', + 'tab-counter': 'Counter', + 'tab-misc': 'Misc', + + // Generator + 'placeholder-length': 'Text Length', + 'unit-characters': 'Characters', + 'unit-words': 'Words', + 'label-remove-punct': 'Remove Punctuation', + 'label-remove-space': 'Remove Spaces', + 'btn-generate': 'Generate Text', + 'placeholder-result': 'Generated text will appear here...', + 'btn-copy': 'Copy to Clipboard', + + // Counter + 'placeholder-counter': 'Enter or paste your text here...', + 'stats-chars': 'Characters', + 'stats-words': 'Words', + 'stats-lines': 'Lines', + 'stats-sentences': 'Sentences', + 'stats-paragraphs': 'Paragraphs', + + // Misc + 'select-data-type': 'Select Data Type', + 'option-name': 'Full Name', + 'option-email': 'Email', + 'option-address': 'Address', + 'option-password': 'Password', + 'gender-male': 'Male', + 'gender-female': 'Female', + 'domain-random': 'Random Domain', + 'domain-custom': 'Custom Domain', + 'placeholder-custom-domain': 'Enter custom domain', + 'bulk-count': 'Count', + 'bulk-format': 'Format', + 'format-plain': 'Plain Text', + 'format-json': 'JSON', + 'format-json-id': 'JSON with ID', + + // Settings + 'settings-title': 'Settings', + 'setting-theme': 'Theme', + 'theme-light': 'Light', + 'theme-dark': 'Dark', + 'setting-language': 'Language', + 'setting-support': 'Support', + 'support-coffee': 'Buy Me a Coffee', + 'support-github': 'GitHub', + + // Messages + 'msg-copied': 'Copied to clipboard!', + 'msg-copy-failed': 'Failed to copy to clipboard', + 'msg-no-text': 'No text to copy', + 'msg-invalid-length': 'Please enter a valid positive number for length', + 'msg-max-length': 'Maximum length is 999,999 characters', + 'msg-select-type': 'Please select a data type', + 'msg-loading-error': 'Error loading data' + }, + + tr: { + // App + 'app-title': 'Test Metin Üreteci', + 'loading': 'Yükleniyor...', + + // Tabs + 'tab-generator': 'Üretici', + 'tab-counter': 'Sayaç', + 'tab-misc': 'Diğer', + + // Generator + 'placeholder-length': 'Metin Uzunluğu', + 'unit-characters': 'Karakter', + 'unit-words': 'Kelime', + 'label-remove-punct': 'Noktalama İşaretlerini Kaldır', + 'label-remove-space': 'Boşlukları Kaldır', + 'btn-generate': 'Metin Üret', + 'placeholder-result': 'Üretilen metin burada görünecek...', + 'btn-copy': 'Panoya Kopyala', + + // Counter + 'placeholder-counter': 'Metninizi buraya girin veya yapıştırın...', + 'stats-chars': 'Karakter', + 'stats-words': 'Kelime', + 'stats-lines': 'Satır', + 'stats-sentences': 'Cümle', + 'stats-paragraphs': 'Paragraf', + + // Misc + 'select-data-type': 'Veri Türü Seçin', + 'option-name': 'Tam İsim', + 'option-email': 'E-posta', + 'option-address': 'Adres', + 'option-password': 'Şifre', + 'gender-male': 'Erkek', + 'gender-female': 'Kadın', + 'domain-random': 'Rastgele Domain', + 'domain-custom': 'Özel Domain', + 'placeholder-custom-domain': 'Özel domain girin', + 'bulk-count': 'Adet', + 'bulk-format': 'Format', + 'format-plain': 'Düz Metin', + 'format-json': 'JSON', + 'format-json-id': 'ID\'li JSON', + + // Settings + 'settings-title': 'Ayarlar', + 'setting-theme': 'Tema', + 'theme-light': 'Açık', + 'theme-dark': 'Koyu', + 'setting-language': 'Dil', + 'setting-support': 'Destek', + 'support-coffee': 'Bana Kahve Ismarla', + 'support-github': 'GitHub', + + // Messages + 'msg-copied': 'Panoya kopyalandı!', + 'msg-copy-failed': 'Panoya kopyalama başarısız', + 'msg-no-text': 'Kopyalanacak metin yok', + 'msg-invalid-length': 'Lütfen uzunluk için geçerli pozitif bir sayı girin', + 'msg-max-length': 'Maksimum uzunluk 999.999 karakterdir', + 'msg-select-type': 'Lütfen bir veri türü seçin', + 'msg-loading-error': 'Veri yükleme hatası' + } + }; + + this.initialize(); + } + + async initialize() { + // Load saved language from storage + try { + if (typeof chrome !== 'undefined' && chrome.storage) { + const result = await chrome.storage.sync.get(['language']); + if (result.language) { + this.currentLanguage = result.language; + } + } else { + // Fallback to localStorage for development + const savedLanguage = localStorage.getItem('language'); + if (savedLanguage) { + this.currentLanguage = savedLanguage; + } + } + } catch (error) { + console.warn('Failed to load language preference:', error); + } + + this.updateUI(); + } + + translate(key, fallback = '') { + const translation = this.translations[this.currentLanguage]?.[key] || + this.translations['en']?.[key] || + fallback || + key; + return translation; + } + + async setLanguage(lang) { + if (this.translations[lang]) { + this.currentLanguage = lang; + + // Save to storage + try { + if (typeof chrome !== 'undefined' && chrome.storage) { + await chrome.storage.sync.set({ language: lang }); + } else { + // Fallback to localStorage for development + localStorage.setItem('language', lang); + } + } catch (error) { + console.warn('Failed to save language preference:', error); + } + + this.updateUI(); + + // Dispatch event for other components + window.dispatchEvent(new CustomEvent('languageChanged', { + detail: { language: lang } + })); + } + } + + updateUI() { + // Update all elements with data-i18n attribute + document.querySelectorAll('[data-i18n]').forEach(element => { + const key = element.getAttribute('data-i18n'); + element.textContent = this.translate(key); + }); + + // Update placeholders + document.querySelectorAll('[data-i18n-placeholder]').forEach(element => { + const key = element.getAttribute('data-i18n-placeholder'); + element.placeholder = this.translate(key); + }); + + // Update HTML lang attribute + document.documentElement.lang = this.currentLanguage; + } + + getCurrentLanguage() { + return this.currentLanguage; + } + + getSupportedLanguages() { + return Object.keys(this.translations); + } +} + +// Create global instance +window.i18n = new I18n(); + +// Export for other modules +if (typeof module !== 'undefined' && module.exports) { + module.exports = I18n; +} \ No newline at end of file diff --git a/src/js/misc.js b/src/js/misc.js index 6cd8271..393f637 100644 --- a/src/js/misc.js +++ b/src/js/misc.js @@ -1,37 +1,396 @@ -// Load the JSON data -let DATA = { - maleNames: [], - femaleNames: [], - surnames: [], - emails: [], - addresses: [], - passwords: [] -}; - -// Load all JSON data -async function loadData() { - try { - const [maleNames, femaleNames, surnames, emails, addresses, passwords] = await Promise.all([ - fetch('data/maleFirstName.json').then(r => r.json()), - fetch('data/femaleFirstName.json').then(r => r.json()), - fetch('data/surname.json').then(r => r.json()), - fetch('data/email.json').then(r => r.json()), - fetch('data/address.json').then(r => r.json()), - fetch('data/password.json').then(r => r.json()) +// Enhanced Miscellaneous Data Generator with Multi-language Support +class MiscDataGenerator { + constructor() { + this.DATA = { + tr: { + maleNames: [], + femaleNames: [], + surnames: [], + emails: [], + addresses: [], + passwords: [] + }, + en: { + maleNames: [], + femaleNames: [], + surnames: [], + emails: [], + addresses: [], + passwords: [] + } + }; + + this.isLoading = false; + this.loadPromise = null; + this.currentLanguage = 'en'; + + this.initialize(); + } + + async initialize() { + // Listen for language changes + window.addEventListener('languageChanged', (e) => { + this.currentLanguage = e.detail.language; + }); + + // Get current language from i18n + if (window.i18n) { + this.currentLanguage = window.i18n.getCurrentLanguage(); + } + + await this.loadAllData(); + this.initializeUI(); + } + + async loadAllData() { + if (this.isLoading) { + return this.loadPromise; + } + + this.isLoading = true; + this.showLoading(true); + + this.loadPromise = this.performDataLoad(); + + try { + await this.loadPromise; + } catch (error) { + console.error('Failed to load data:', error); + this.showFeedback(window.i18n?.translate('msg-loading-error') || 'Error loading data', 'error'); + } finally { + this.isLoading = false; + this.showLoading(false); + } + + return this.loadPromise; + } + + async performDataLoad() { + const dataFiles = { + tr: { + maleNames: 'data/maleFirstName.json', + femaleNames: 'data/femaleFirstName.json', + surnames: 'data/surname.json', + emails: 'data/email.json', + addresses: 'data/address.json', + passwords: 'data/password.json' + }, + en: { + maleNames: 'data/enMaleFirstName.json', + femaleNames: 'data/enFemaleFirstName.json', + surnames: 'data/enSurname.json', + emails: 'data/email.json', // Shared + addresses: 'data/enAddress.json', + passwords: 'data/password.json' // Shared + } + }; + + const loadLanguageData = async (lang) => { + const files = dataFiles[lang]; + const results = await Promise.allSettled([ + this.loadJSONFile(files.maleNames), + this.loadJSONFile(files.femaleNames), + this.loadJSONFile(files.surnames), + this.loadJSONFile(files.emails), + this.loadJSONFile(files.addresses), + this.loadJSONFile(files.passwords) + ]); + + return { + maleNames: results[0].status === 'fulfilled' ? results[0].value : [], + femaleNames: results[1].status === 'fulfilled' ? results[1].value : [], + surnames: results[2].status === 'fulfilled' ? results[2].value : [], + emails: results[3].status === 'fulfilled' ? results[3].value : [], + addresses: results[4].status === 'fulfilled' ? results[4].value : [], + passwords: results[5].status === 'fulfilled' ? results[5].value : [] + }; + }; + + // Load both languages in parallel + const [trData, enData] = await Promise.allSettled([ + loadLanguageData('tr'), + loadLanguageData('en') ]); + + if (trData.status === 'fulfilled') { + this.DATA.tr = trData.value; + } + if (enData.status === 'fulfilled') { + this.DATA.en = enData.value; + } + + // Fallback: if EN data fails, use TR data for both + if (enData.status === 'rejected' && trData.status === 'fulfilled') { + this.DATA.en = { ...trData.value }; + } + } + + async loadJSONFile(url) { + try { + const response = await fetch(chrome.runtime.getURL(url)); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return await response.json(); + } catch (error) { + console.warn(`Failed to load ${url}:`, error); + return []; + } + } + + showLoading(show) { + const overlay = document.getElementById('loadingOverlay'); + if (overlay) { + overlay.style.display = show ? 'flex' : 'none'; + } + } + + showFeedback(message, type = 'success') { + const feedback = document.createElement('div'); + feedback.className = `feedback ${type}`; + feedback.textContent = message; + document.body.appendChild(feedback); + + setTimeout(() => { + if (feedback.parentNode) { + feedback.parentNode.removeChild(feedback); + } + }, 3000); + } + + initializeUI() { + const dataTypeSelect = document.getElementById('dataTypeSelect'); + const genderOptions = document.getElementById('genderOptions'); + const emailOptions = document.getElementById('emailOptions'); + const customDomain = document.getElementById('customDomain'); + const domainSelect = document.getElementById('domainSelect'); + const generateButton = document.getElementById('generateMiscButton'); + const copyButton = document.getElementById('copyMiscButton'); + + if (!dataTypeSelect) return; + + // Data type selection handler + dataTypeSelect.addEventListener('change', () => { + const selectedType = dataTypeSelect.value; + + // Hide all option groups + genderOptions?.classList.remove('active'); + emailOptions?.classList.remove('active'); + + // Show relevant options + if (selectedType === 'name') { + genderOptions?.classList.add('active'); + } else if (selectedType === 'email') { + emailOptions?.classList.add('active'); + } + }); + + // Domain selection handler + if (domainSelect) { + domainSelect.addEventListener('change', () => { + const isCustom = domainSelect.value === 'custom'; + if (customDomain) { + customDomain.style.display = isCustom ? 'block' : 'none'; + customDomain.required = isCustom; + } + }); + } + + // Generate button handler + if (generateButton) { + generateButton.addEventListener('click', () => this.generateMiscData()); + } + + // Copy button handler + if (copyButton) { + copyButton.addEventListener('click', () => this.copyMiscResult()); + } + } + + getCurrentData() { + const data = this.DATA[this.currentLanguage]; + return data && Object.keys(data).length > 0 ? data : this.DATA.tr; + } + + generateMiscData() { + const dataType = document.getElementById('dataTypeSelect')?.value; + const count = parseInt(document.getElementById('bulkCount')?.value || 1); + const format = document.getElementById('outputFormat')?.value || 'plain'; + + if (!dataType) { + this.showFeedback(window.i18n?.translate('msg-select-type') || 'Please select a data type', 'error'); + return; + } + + try { + const results = []; + for (let i = 0; i < count; i++) { + let result; + switch (dataType) { + case 'name': + result = this.generateFullName(); + break; + case 'email': + result = this.generateEmail(); + break; + case 'address': + result = this.generateAddress(); + break; + case 'password': + result = this.generatePassword(); + break; + default: + throw new Error('Invalid data type'); + } + results.push(result); + } + + this.displayResults(results, format); + this.showFeedback(window.i18n?.translate('msg-generated') || 'Data generated successfully!'); + } catch (error) { + console.error('Generation error:', error); + this.showFeedback(window.i18n?.translate('msg-generation-error') || 'Error generating data', 'error'); + } + } + + generateFullName() { + const data = this.getCurrentData(); + const gender = document.querySelector('input[name="gender"]:checked')?.value || 'male'; + + const firstNames = gender === 'male' ? data.maleNames : data.femaleNames; + const firstNamesList = Array.isArray(firstNames) ? firstNames : []; + const surnamesList = Array.isArray(data.surnames) ? data.surnames : []; + + if (firstNamesList.length === 0 || surnamesList.length === 0) { + throw new Error('Name data not available'); + } + + const firstName = this.getRandomItem(firstNamesList); + const surname = this.getRandomItem(surnamesList); + + return `${firstName} ${surname}`; + } + + generateEmail() { + const data = this.getCurrentData(); + const domainSelect = document.getElementById('domainSelect'); + const customDomain = document.getElementById('customDomain'); + + let domain; + if (domainSelect?.value === 'custom') { + domain = customDomain?.value?.trim(); + if (!domain) { + throw new Error('Custom domain is required'); + } + } else if (domainSelect?.value === 'random') { + const emailList = Array.isArray(data.emails) ? data.emails : []; + if (emailList.length === 0) { + throw new Error('Email data not available'); + } + return this.getRandomItem(emailList); + } else { + domain = domainSelect?.value || 'example.com'; + } + + // Generate a random username + const firstNames = [...(data.maleNames || []), ...(data.femaleNames || [])]; + if (firstNames.length === 0) { + throw new Error('Name data not available for email generation'); + } + + const name = this.getRandomItem(firstNames).toLowerCase(); + const randomNum = Math.floor(Math.random() * 1000); + const username = this.sanitizeEmailLocalPart(`${name}${randomNum}`); + + return `${username}@${domain}`; + } + + sanitizeEmailLocalPart(str) { + return str + .normalize('NFD') + .replace(/[\u0300-\u036f]/g, '') // Remove diacritics + .replace(/[çğıöşüÇĞIÖŞÜ]/g, (char) => { + const map = { + 'ç': 'c', 'ğ': 'g', 'ı': 'i', 'ö': 'o', 'ş': 's', 'ü': 'u', + 'Ç': 'c', 'Ğ': 'g', 'I': 'i', 'Ö': 'o', 'Ş': 's', 'Ü': 'u' + }; + return map[char] || char; + }) + .replace(/[^a-zA-Z0-9.]/g, '') + .toLowerCase(); + } + + generateAddress() { + const data = this.getCurrentData(); + const addressList = Array.isArray(data.addresses) ? data.addresses : []; + + if (addressList.length === 0) { + throw new Error('Address data not available'); + } + + return this.getRandomItem(addressList); + } + + generatePassword() { + const data = this.getCurrentData(); + const passwordList = Array.isArray(data.passwords) ? data.passwords : []; + + if (passwordList.length === 0) { + throw new Error('Password data not available'); + } + + return this.getRandomItem(passwordList); + } + + displayResults(results, format) { + const textarea = document.getElementById('miscResultText'); + if (!textarea) return; + + let output; + switch (format) { + case 'json': + output = JSON.stringify(results, null, 2); + break; + case 'json-with-id': + const withIds = results.map((item, index) => ({ + id: index + 1, + value: item + })); + output = JSON.stringify(withIds, null, 2); + break; + default: + output = results.join('\n'); + } + + textarea.value = output; + } + + copyMiscResult() { + const textarea = document.getElementById('miscResultText'); + if (!textarea || !textarea.value) { + this.showFeedback(window.i18n?.translate('msg-no-data') || 'No data to copy', 'error'); + return; + } + + navigator.clipboard.writeText(textarea.value).then(() => { + this.showFeedback(window.i18n?.translate('msg-copied') || 'Copied to clipboard!'); + }).catch(err => { + console.error('Failed to copy:', err); + this.showFeedback(window.i18n?.translate('msg-copy-error') || 'Failed to copy to clipboard', 'error'); + }); + } + + getRandomItem(array) { + return array[Math.floor(Math.random() * array.length)]; + } +} - DATA = { - maleNames, - femaleNames, - surnames, - emails, - addresses, - passwords - }; - } catch (error) { - console.error('Error loading data:', error); - showFeedback('Error loading data', 'error'); +// Legacy support functions for backward compatibility +async function loadData() { + if (!window.miscGenerator) { + window.miscGenerator = new MiscDataGenerator(); } + return window.miscGenerator.loadAllData(); } function getRandomItem(array) { @@ -39,97 +398,55 @@ function getRandomItem(array) { } function generateFullName(gender) { - const nameArray = gender === 'male' ? DATA.maleNames : DATA.femaleNames; - const firstName = getRandomItem(nameArray); - const surname = getRandomItem(DATA.surnames); - return `${firstName} ${surname}`; + if (!window.miscGenerator) { + window.miscGenerator = new MiscDataGenerator(); + } + + // Set gender if provided + if (gender) { + const radioButton = document.querySelector(`input[name="gender"][value="${gender}"]`); + if (radioButton) radioButton.checked = true; + } + + return window.miscGenerator.generateFullName(); } -// Utility: Sanitize Turkish characters for email local part function sanitizeEmailLocalPart(str) { - return str - .replace(/ç/g, 'c') - .replace(/ğ/g, 'g') - .replace(/ı/g, 'i') - .replace(/ö/g, 'o') - .replace(/ş/g, 's') - .replace(/ü/g, 'u') - .replace(/Ç/g, 'c') - .replace(/Ğ/g, 'g') - .replace(/İ/g, 'i') - .replace(/Ö/g, 'o') - .replace(/Ş/g, 's') - .replace(/Ü/g, 'u'); + if (!window.miscGenerator) { + window.miscGenerator = new MiscDataGenerator(); + } + return window.miscGenerator.sanitizeEmailLocalPart(str); } function generateEmail(domainType, customDomain) { - if (domainType === 'random') { - return getRandomItem(DATA.emails); + if (!window.miscGenerator) { + window.miscGenerator = new MiscDataGenerator(); } - let name = generateFullName(Math.random() > 0.5 ? 'male' : 'female') - .toLowerCase() - .replace(' ', '.'); - name = sanitizeEmailLocalPart(name); + // Set domain options if provided + const domainSelect = document.getElementById('domainSelect'); + const customDomainInput = document.getElementById('customDomain'); - const domain = domainType === 'custom' ? customDomain : domainType; - return `${name}@${domain}`; + if (domainType && domainSelect) { + domainSelect.value = domainType; + } + if (customDomain && customDomainInput) { + customDomainInput.value = customDomain; + } + + return window.miscGenerator.generateEmail(); } +// Initialize the misc tab function initializeMiscTab() { - loadData(); - - const dataType = document.getElementById('dataType'); - const nameOptions = document.getElementById('nameOptions'); - const emailOptions = document.getElementById('emailOptions'); - const emailDomain = document.getElementById('emailDomain'); - const customDomain = document.getElementById('customDomain'); - const generateButton = document.getElementById('generateMiscButton'); - const copyButton = document.getElementById('copyMiscButton'); - const resultText = document.getElementById('miscResultText'); - - dataType.addEventListener('change', () => { - nameOptions.style.display = dataType.value === 'name' ? 'block' : 'none'; - emailOptions.style.display = dataType.value === 'email' ? 'block' : 'none'; - }); - - emailDomain.addEventListener('change', () => { - customDomain.style.display = emailDomain.value === 'custom' ? 'block' : 'none'; - }); - - generateButton.addEventListener('click', () => { - let result = ''; - - switch (dataType.value) { - case 'name': - const gender = document.querySelector('input[name="gender"]:checked').value; - result = generateFullName(gender); - break; - case 'email': - result = generateEmail(emailDomain.value, customDomain.value); - break; - case 'address': - result = getRandomItem(DATA.addresses); - break; - case 'password': - result = getRandomItem(DATA.passwords); - break; - default: - showFeedback('Please select a data type', 'error'); - return; - } - - resultText.value = result; - }); + if (!window.miscGenerator) { + window.miscGenerator = new MiscDataGenerator(); + } +} - copyButton.addEventListener('click', () => { - if (!resultText.value) { - showFeedback('No text to copy', 'error'); - return; - } - - navigator.clipboard.writeText(resultText.value) - .then(() => showFeedback('Copied to clipboard!', 'success')) - .catch(() => showFeedback('Failed to copy to clipboard', 'error')); - }); +// Auto-initialize when DOM is ready +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initializeMiscTab); +} else { + initializeMiscTab(); } diff --git a/src/js/popup.js b/src/js/popup.js index 9bd6f69..0736f4a 100644 --- a/src/js/popup.js +++ b/src/js/popup.js @@ -1,109 +1,351 @@ -document.addEventListener('DOMContentLoaded', function () { - clearTextarea(); - initializeTabs(); - initializeCharacterCounter(); - initializeMiscTab(); - - const generateButton = document.getElementById('generateButton'); - const copyButton = document.getElementById('copyButton'); - - generateButton.addEventListener('click', () => { - const length = parseInt(document.getElementById('lengthInput').value); - const removePunct = document.getElementById('removePunct').checked; - const removeSpace = document.getElementById('removeSpace').checked; - - if (isNaN(length) || length <= 0) { - showFeedback('Please enter a valid positive number for length', 'error'); - clearTextarea(); - } else if (length > 999999) { - showFeedback('Maximum length is 999,999 characters', 'error'); - clearTextarea(); - } else { - document.getElementById('resultText').value = window.generateLoremIpsum( - length, - removeSpace, - removePunct - ); +// Enhanced Popup Management System +class PopupManager { + constructor() { + this.elements = {}; + this.isInitialized = false; + this.initialize(); + } + + async initialize() { + if (this.isInitialized) return; + + // Wait for i18n to be ready + await this.waitForI18n(); + + this.cacheElements(); + this.clearTextarea(); + this.initializeTabs(); + this.initializeCharacterCounter(); + this.bindEvents(); + this.updateUnitToggleText(); + + this.isInitialized = true; + } + + async waitForI18n() { + let retries = 0; + const maxRetries = 50; // 5 seconds max + + while (!window.i18n && retries < maxRetries) { + await new Promise(resolve => setTimeout(resolve, 100)); + retries++; } - }); - - copyButton.addEventListener('click', copyToClipboard); -}); - -function initializeTabs() { - const tabButtons = document.querySelectorAll('.tab-button'); - const tabContents = document.querySelectorAll('.tab-content'); - - tabButtons.forEach(button => { - button.addEventListener('click', () => { - // Remove active class from all buttons and contents - tabButtons.forEach(btn => btn.classList.remove('active')); - tabContents.forEach(content => content.classList.remove('active')); + } + + cacheElements() { + this.elements = { + generateButton: document.getElementById('generateButton'), + copyButton: document.getElementById('copyButton'), + lengthInput: document.getElementById('lengthInput'), + unitToggle: document.getElementById('unitToggle'), + removePunct: document.getElementById('removePunct'), + removeSpace: document.getElementById('removeSpace'), + resultText: document.getElementById('resultText'), + counterText: document.getElementById('counterText'), + characterCount: document.getElementById('characterCount'), + tabButtons: document.querySelectorAll('.tab-button'), + tabContents: document.querySelectorAll('.tab-content') + }; + } + + bindEvents() { + // Generator events + this.elements.generateButton?.addEventListener('click', () => { + this.handleGenerate(); + }); + + this.elements.copyButton?.addEventListener('click', () => { + this.handleCopy(); + }); + + // Input validation + this.elements.lengthInput?.addEventListener('input', (e) => { + this.validateLengthInput(e.target); + }); + + // Enter key support for generation + this.elements.lengthInput?.addEventListener('keydown', (e) => { + if (e.key === 'Enter') { + this.handleGenerate(); + } + }); + + // Unit toggle functionality + this.elements.unitToggle?.addEventListener('click', () => { + this.toggleUnit(); + }); - // Add active class to clicked button and corresponding content - button.classList.add('active'); - const tabId = button.getAttribute('data-tab'); - document.getElementById(tabId).classList.add('active'); + // Listen for language changes + window.addEventListener('languageChanged', () => { + this.updateCharacterCount(); + this.updateUnitToggleText(); }); - }); + } + + handleGenerate() { + const length = parseInt(this.elements.lengthInput?.value); + const removePunct = this.elements.removePunct?.checked || false; + const removeSpace = this.elements.removeSpace?.checked || false; + const unit = this.elements.unitToggle?.getAttribute('data-unit') || 'characters'; + + // Validation + if (!this.validateLength(length)) { + return; + } + + try { + // Show loading state + this.setGenerateButtonState(true); + + // Generate text with slight delay for better UX + setTimeout(() => { + let text; + if (unit === 'words') { + text = window.generateWords ? window.generateWords(length) : window.generateText(length * 5); + } else { + text = window.generateText ? window.generateText(length) : this.generateFallbackText(length); + } + + // Apply filters + if (removePunct) { + text = text.replace(/[.,\/#!$%\^&\*;:{}=\-_`~()]/g, ''); + } + + if (removeSpace) { + text = text.replace(/\s/g, ''); + } + + // Update result + if (this.elements.resultText) { + this.elements.resultText.value = text; + } + + this.showFeedback(window.i18n?.translate('msg-generated') || 'Text generated successfully!'); + this.setGenerateButtonState(false); + }, 100); + + } catch (error) { + console.error('Generation error:', error); + this.showFeedback(window.i18n?.translate('msg-generation-error') || 'Error generating text', 'error'); + this.setGenerateButtonState(false); + } + } + + generateFallbackText(length) { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 '; + let result = ''; + for (let i = 0; i < length; i++) { + result += chars.charAt(Math.floor(Math.random() * chars.length)); + } + return result; + } + + handleCopy() { + const text = this.elements.resultText?.value; + if (!text) { + this.showFeedback(window.i18n?.translate('msg-no-text') || 'No text to copy', 'error'); + return; + } + + navigator.clipboard.writeText(text).then(() => { + this.showFeedback(window.i18n?.translate('msg-copied') || 'Copied to clipboard!'); + }).catch(err => { + console.error('Failed to copy text:', err); + this.showFeedback(window.i18n?.translate('msg-copy-error') || 'Failed to copy text', 'error'); + }); + } + + validateLength(length) { + if (isNaN(length) || length < 1) { + this.showFeedback(window.i18n?.translate('msg-invalid-length') || 'Please enter a valid length', 'error'); + return false; + } + + const maxLength = 999999; + if (length > maxLength) { + this.showFeedback(window.i18n?.translate('msg-length-too-large') || `Length cannot exceed ${maxLength}`, 'error'); + return false; + } + + return true; + } + + validateLengthInput(input) { + const value = parseInt(input.value); + const min = parseInt(input.min) || 1; + const max = parseInt(input.max) || 999999; + + if (value < min) { + input.value = min; + } else if (value > max) { + input.value = max; + } + } + + toggleUnit() { + const currentUnit = this.elements.unitToggle?.getAttribute('data-unit') || 'characters'; + const newUnit = currentUnit === 'characters' ? 'words' : 'characters'; + + if (this.elements.unitToggle) { + this.elements.unitToggle.setAttribute('data-unit', newUnit); + } + + this.updateUnitToggleText(); + } + + updateUnitToggleText() { + const unit = this.elements.unitToggle?.getAttribute('data-unit') || 'characters'; + const unitLabel = this.elements.unitToggle?.querySelector('.unit-label'); + + if (unitLabel && window.i18n) { + const translationKey = unit === 'words' ? 'unit-words' : 'unit-characters'; + unitLabel.textContent = window.i18n.translate(translationKey); + } + } + + setGenerateButtonState(loading) { + if (!this.elements.generateButton) return; + + this.elements.generateButton.disabled = loading; + this.elements.generateButton.textContent = loading + ? (window.i18n?.translate('btn-generating') || 'Generating...') + : (window.i18n?.translate('btn-generate') || 'Generate Text'); + } + + showFeedback(message, type = 'success') { + const feedback = document.createElement('div'); + feedback.className = `feedback ${type}`; + feedback.textContent = message; + document.body.appendChild(feedback); + + setTimeout(() => { + if (feedback.parentNode) { + feedback.parentNode.removeChild(feedback); + } + }, 3000); + } + + clearTextarea() { + if (this.elements.resultText) { + this.elements.resultText.value = ''; + } + if (this.elements.counterText) { + this.elements.counterText.value = ''; + } + } + + initializeTabs() { + this.elements.tabButtons?.forEach(button => { + button.addEventListener('click', () => { + const targetTab = button.getAttribute('data-tab'); + this.switchTab(targetTab, button); + }); + }); + } + + switchTab(targetTab, activeButton) { + // Remove active class from all tabs and buttons + this.elements.tabButtons?.forEach(btn => btn.classList.remove('active')); + this.elements.tabContents?.forEach(content => content.classList.remove('active')); + + // Add active class to clicked button and corresponding content + activeButton?.classList.add('active'); + document.getElementById(targetTab)?.classList.add('active'); + + // Clear content when switching tabs + this.clearTextarea(); + + // Update character count if switching to counter tab + if (targetTab === 'counter') { + this.updateCharacterCount(); + } + } + + initializeCharacterCounter() { + if (this.elements.counterText) { + this.elements.counterText.addEventListener('input', () => { + this.updateCharacterCount(); + }); + + this.elements.counterText.addEventListener('paste', () => { + setTimeout(() => this.updateCharacterCount(), 10); + }); + } + } + + updateCharacterCount() { + const text = this.elements.counterText?.value || ''; + const characterCount = this.elements.characterCount; + + if (!characterCount) return; + + const stats = this.calculateTextStats(text); + + // Update individual stat elements + const charCount = document.getElementById('charCount'); + const wordCount = document.getElementById('wordCount'); + const lineCount = document.getElementById('lineCount'); + const sentenceCount = document.getElementById('sentenceCount'); + const paragraphCount = document.getElementById('paragraphCount'); + + if (charCount) charCount.textContent = stats.characters; + if (wordCount) wordCount.textContent = stats.words; + if (lineCount) lineCount.textContent = stats.lines; + if (sentenceCount) sentenceCount.textContent = stats.sentences; + if (paragraphCount) paragraphCount.textContent = stats.paragraphs; + } + + calculateTextStats(text) { + return { + characters: text.length, + words: text.trim() ? text.trim().split(/\s+/).length : 0, + lines: text ? text.split('\n').length : 0, + sentences: text.trim() ? (text.match(/[.!?]+/g) || []).length : 0, + paragraphs: text.trim() ? text.split(/\n\s*\n/).filter(p => p.trim().length > 0).length : 0 + }; + } } -function initializeCharacterCounter() { - const counterText = document.getElementById('counterText'); - const characterCount = document.getElementById('characterCount'); - - function updateCount() { - const text = counterText.value; - const chars = text.length; - const words = text.trim() === '' ? 0 : text.trim().split(/\s+/).length; - const lines = text.trim() === '' ? '-' : text.split('\n').length; - - characterCount.textContent = - `Characters: ${chars} | Words: ${words} | Lines: ${lines}`; +// Legacy support functions for backward compatibility +function copyToClipboard() { + if (window.popupManager) { + window.popupManager.handleCopy(); } - - counterText.addEventListener('input', updateCount); - // Initialize with empty state - updateCount(); } -// Clear textarea when the popup is shown -chrome.runtime.onConnect.addListener(function (port) { - if (port.name === 'popup') { - clearTextarea(); +function showFeedback(message, type = 'success') { + if (window.popupManager) { + window.popupManager.showFeedback(message, type); + } else { + console.log(`${type.toUpperCase()}: ${message}`); } -}); +} -function copyToClipboard() { - const resultText = document.getElementById('resultText').value; - if (!resultText.trim()) { - showFeedback('No text to copy', 'error'); - return; - } - navigator.clipboard - .writeText(resultText) - .then(() => showFeedback('Copied to clipboard!', 'success')) - .catch((err) => { - console.error('Failed to copy: ', err); - showFeedback('Failed to copy to clipboard', 'error'); - }); +function clearTextarea() { + if (window.popupManager) { + window.popupManager.clearTextarea(); + } } -function showFeedback(message, type) { - const feedbackElement = document.createElement('div'); - feedbackElement.textContent = message; - feedbackElement.className = `feedback ${type}`; - document.body.appendChild(feedbackElement); +function initializeTabs() { + // Legacy function - now handled by PopupManager +} - setTimeout(() => { - feedbackElement.remove(); - }, 3000); +function initializeCharacterCounter() { + // Legacy function - now handled by PopupManager } -// Function to clear the textarea -function clearTextarea() { - const resultText = document.getElementById('resultText'); - if (resultText) { - resultText.value = ''; +function updateCount() { + if (window.popupManager) { + window.popupManager.updateCharacterCount(); } } + +// Initialize the popup manager when DOM is ready +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + window.popupManager = new PopupManager(); + }); +} else { + window.popupManager = new PopupManager(); +} diff --git a/src/js/settings.js b/src/js/settings.js new file mode 100644 index 0000000..6cb54e6 --- /dev/null +++ b/src/js/settings.js @@ -0,0 +1,229 @@ +// Settings Management System +class SettingsManager { + constructor() { + this.settings = { + theme: 'light', + language: 'en' + }; + + this.initialize(); + } + + async initialize() { + await this.loadSettings(); + this.bindEvents(); + this.applyTheme(); + } + + async loadSettings() { + try { + if (typeof chrome !== 'undefined' && chrome.storage) { + const result = await chrome.storage.sync.get(['theme', 'language']); + this.settings = { + theme: result.theme || 'light', + language: result.language || 'en' + }; + } else { + // Fallback to localStorage for development + this.settings = { + theme: localStorage.getItem('theme') || 'light', + language: localStorage.getItem('language') || 'en' + }; + } + } catch (error) { + console.warn('Failed to load settings:', error); + } + } + + async saveSettings() { + try { + if (typeof chrome !== 'undefined' && chrome.storage) { + await chrome.storage.sync.set(this.settings); + } else { + // Fallback to localStorage for development + localStorage.setItem('theme', this.settings.theme); + localStorage.setItem('language', this.settings.language); + } + } catch (error) { + console.warn('Failed to save settings:', error); + } + } + + bindEvents() { + // Settings button + const settingsButton = document.getElementById('settingsButton'); + const settingsModal = document.getElementById('settingsModal'); + const closeSettings = document.getElementById('closeSettings'); + + if (settingsButton) { + settingsButton.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); + this.openModal(); + }); + } + + // Close modal events + closeSettings?.addEventListener('click', () => { + this.closeModal(); + }); + + // Remove click-outside-to-close since it's now fullscreen + // settingsModal?.addEventListener('click', (e) => { + // if (e.target === settingsModal) { + // this.closeModal(); + // } + // }); + + // Escape key to close modal + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && settingsModal?.classList.contains('active')) { + this.closeModal(); + } + }); + + // Theme buttons + const lightTheme = document.getElementById('lightTheme'); + const darkTheme = document.getElementById('darkTheme'); + + lightTheme?.addEventListener('click', () => { + this.setTheme('light'); + }); + + darkTheme?.addEventListener('click', () => { + this.setTheme('dark'); + }); + + // Language select + const languageSelect = document.getElementById('languageSelect'); + languageSelect?.addEventListener('change', (e) => { + this.setLanguage(e.target.value); + }); + + // Update UI with current settings + this.updateSettingsUI(); + } + + openModal() { + const modal = document.getElementById('settingsModal'); + + if (modal) { + modal.classList.add('active'); + modal.style.display = 'flex'; + + // Focus trap + const focusableElements = modal.querySelectorAll( + 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' + ); + if (focusableElements?.length > 0) { + focusableElements[0].focus(); + } + } + } + + closeModal() { + const modal = document.getElementById('settingsModal'); + + if (modal) { + modal.classList.remove('active'); + modal.style.display = 'none'; + } + + // Return focus to settings button + document.getElementById('settingsButton')?.focus(); + } + + async setTheme(theme) { + if (theme !== this.settings.theme) { + this.settings.theme = theme; + await this.saveSettings(); + this.applyTheme(); + this.updateThemeButtons(); + } + } + + applyTheme() { + document.body.setAttribute('data-theme', this.settings.theme); + + // Update meta theme-color + let themeColorMeta = document.querySelector('meta[name="theme-color"]'); + if (!themeColorMeta) { + themeColorMeta = document.createElement('meta'); + themeColorMeta.name = 'theme-color'; + document.head.appendChild(themeColorMeta); + } + + const themeColor = this.settings.theme === 'dark' ? '#1E1E1E' : '#FFFFFF'; + themeColorMeta.content = themeColor; + } + + async setLanguage(language) { + if (language !== this.settings.language && window.i18n) { + this.settings.language = language; + await this.saveSettings(); + await window.i18n.setLanguage(language); + this.updateLanguageSelect(); + } + } + + updateSettingsUI() { + this.updateThemeButtons(); + this.updateLanguageSelect(); + } + + updateThemeButtons() { + const lightTheme = document.getElementById('lightTheme'); + const darkTheme = document.getElementById('darkTheme'); + + lightTheme?.classList.toggle('active', this.settings.theme === 'light'); + darkTheme?.classList.toggle('active', this.settings.theme === 'dark'); + } + + updateLanguageSelect() { + const languageSelect = document.getElementById('languageSelect'); + if (languageSelect) { + languageSelect.value = this.settings.language; + } + } + + getSettings() { + return { ...this.settings }; + } +} + +// Initialize when DOM is loaded +document.addEventListener('DOMContentLoaded', () => { + window.settingsManager = new SettingsManager(); +}); + +// Handle system theme changes +if (window.matchMedia) { + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + + const handleSystemThemeChange = (e) => { + // Only auto-switch if user hasn't manually set a preference + if (typeof chrome !== 'undefined' && chrome.storage) { + chrome.storage.sync.get(['theme']).then(result => { + if (!result.theme && window.settingsManager) { + const systemTheme = e.matches ? 'dark' : 'light'; + window.settingsManager.setTheme(systemTheme); + } + }).catch(() => { + console.warn('Could not check theme preference'); + }); + } else { + // Fallback for development + if (!localStorage.getItem('theme') && window.settingsManager) { + const systemTheme = e.matches ? 'dark' : 'light'; + window.settingsManager.setTheme(systemTheme); + } + } + }; + + mediaQuery.addEventListener('change', handleSystemThemeChange); + + // Check initial system preference + document.addEventListener('DOMContentLoaded', () => { + handleSystemThemeChange(mediaQuery); + }); +} \ No newline at end of file