tangled
alpha
login
or
join now
danielmorrisey.com
/
seo-tester
0
fork
atom
A simple SEO inspecter Tool, to get social media card previews
0
fork
atom
overview
issues
pulls
pipelines
Add API and documentation
gpt-engineer-app[bot]
5 months ago
76a171ce
4a1c2fbb
+1007
-6
10 changed files
expand all
collapse all
unified
split
.env
package-lock.json
package.json
src
App.tsx
components
SEOTester.tsx
integrations
supabase
client.ts
types.ts
pages
Docs.tsx
supabase
config.toml
functions
analyze-seo
index.ts
+3
.env
···
1
1
+
VITE_SUPABASE_PROJECT_ID="gjhfnqiknusundbktwxs"
2
2
+
VITE_SUPABASE_PUBLISHABLE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImdqaGZucWlrbnVzdW5kYmt0d3hzIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NjAxMzI1NjgsImV4cCI6MjA3NTcwODU2OH0.zNRPupvAPnzJsTvXkg8tm0nycVKzc6dSG_2RRQZKKv0"
3
3
+
VITE_SUPABASE_URL="https://gjhfnqiknusundbktwxs.supabase.co"
+248
-5
package-lock.json
···
36
36
"@radix-ui/react-toggle": "^1.1.9",
37
37
"@radix-ui/react-toggle-group": "^1.1.10",
38
38
"@radix-ui/react-tooltip": "^1.2.7",
39
39
+
"@supabase/supabase-js": "^2.75.0",
39
40
"@tanstack/react-query": "^5.83.0",
40
41
"class-variance-authority": "^0.7.1",
41
42
"clsx": "^2.1.1",
···
82
83
"version": "5.2.0",
83
84
"resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
84
85
"integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
86
86
+
"dev": true,
85
87
"license": "MIT",
86
88
"engines": {
87
89
"node": ">=10"
···
845
847
"version": "8.0.2",
846
848
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
847
849
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
850
850
+
"dev": true,
848
851
"license": "ISC",
849
852
"dependencies": {
850
853
"string-width": "^5.1.2",
···
862
865
"version": "0.3.5",
863
866
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
864
867
"integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
868
868
+
"dev": true,
865
869
"license": "MIT",
866
870
"dependencies": {
867
871
"@jridgewell/set-array": "^1.2.1",
···
876
880
"version": "3.1.2",
877
881
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
878
882
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
883
883
+
"dev": true,
879
884
"license": "MIT",
880
885
"engines": {
881
886
"node": ">=6.0.0"
···
885
890
"version": "1.2.1",
886
891
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
887
892
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
893
893
+
"dev": true,
888
894
"license": "MIT",
889
895
"engines": {
890
896
"node": ">=6.0.0"
···
894
900
"version": "1.5.0",
895
901
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
896
902
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
903
903
+
"dev": true,
897
904
"license": "MIT"
898
905
},
899
906
"node_modules/@jridgewell/trace-mapping": {
900
907
"version": "0.3.25",
901
908
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
902
909
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
910
910
+
"dev": true,
903
911
"license": "MIT",
904
912
"dependencies": {
905
913
"@jridgewell/resolve-uri": "^3.1.0",
···
910
918
"version": "2.1.5",
911
919
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
912
920
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
921
921
+
"dev": true,
913
922
"license": "MIT",
914
923
"dependencies": {
915
924
"@nodelib/fs.stat": "2.0.5",
···
923
932
"version": "2.0.5",
924
933
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
925
934
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
935
935
+
"dev": true,
926
936
"license": "MIT",
927
937
"engines": {
928
938
"node": ">= 8"
···
932
942
"version": "1.2.8",
933
943
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
934
944
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
945
945
+
"dev": true,
935
946
"license": "MIT",
936
947
"dependencies": {
937
948
"@nodelib/fs.scandir": "2.1.5",
···
945
956
"version": "0.11.0",
946
957
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
947
958
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
959
959
+
"dev": true,
948
960
"license": "MIT",
949
961
"optional": true,
950
962
"engines": {
···
2545
2557
"win32"
2546
2558
]
2547
2559
},
2560
2560
+
"node_modules/@supabase/auth-js": {
2561
2561
+
"version": "2.75.0",
2562
2562
+
"resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.75.0.tgz",
2563
2563
+
"integrity": "sha512-J8TkeqCOMCV4KwGKVoxmEBuDdHRwoInML2vJilthOo7awVCro2SM+tOcpljORwuBQ1vHUtV62Leit+5wlxrNtw==",
2564
2564
+
"license": "MIT",
2565
2565
+
"dependencies": {
2566
2566
+
"@supabase/node-fetch": "2.6.15"
2567
2567
+
}
2568
2568
+
},
2569
2569
+
"node_modules/@supabase/functions-js": {
2570
2570
+
"version": "2.75.0",
2571
2571
+
"resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.75.0.tgz",
2572
2572
+
"integrity": "sha512-18yk07Moj/xtQ28zkqswxDavXC3vbOwt1hDuYM3/7xPnwwpKnsmPyZ7bQ5th4uqiJzQ135t74La9tuaxBR6e7w==",
2573
2573
+
"license": "MIT",
2574
2574
+
"dependencies": {
2575
2575
+
"@supabase/node-fetch": "2.6.15"
2576
2576
+
}
2577
2577
+
},
2578
2578
+
"node_modules/@supabase/node-fetch": {
2579
2579
+
"version": "2.6.15",
2580
2580
+
"resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz",
2581
2581
+
"integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==",
2582
2582
+
"license": "MIT",
2583
2583
+
"dependencies": {
2584
2584
+
"whatwg-url": "^5.0.0"
2585
2585
+
},
2586
2586
+
"engines": {
2587
2587
+
"node": "4.x || >=6.0.0"
2588
2588
+
}
2589
2589
+
},
2590
2590
+
"node_modules/@supabase/postgrest-js": {
2591
2591
+
"version": "2.75.0",
2592
2592
+
"resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.75.0.tgz",
2593
2593
+
"integrity": "sha512-YfBz4W/z7eYCFyuvHhfjOTTzRrQIvsMG2bVwJAKEVVUqGdzqfvyidXssLBG0Fqlql1zJFgtsPpK1n4meHrI7tg==",
2594
2594
+
"license": "MIT",
2595
2595
+
"dependencies": {
2596
2596
+
"@supabase/node-fetch": "2.6.15"
2597
2597
+
}
2598
2598
+
},
2599
2599
+
"node_modules/@supabase/realtime-js": {
2600
2600
+
"version": "2.75.0",
2601
2601
+
"resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.75.0.tgz",
2602
2602
+
"integrity": "sha512-B4Xxsf2NHd5cEnM6MGswOSPSsZKljkYXpvzKKmNxoUmNQOfB7D8HOa6NwHcUBSlxcjV+vIrYKcYXtavGJqeGrw==",
2603
2603
+
"license": "MIT",
2604
2604
+
"dependencies": {
2605
2605
+
"@supabase/node-fetch": "2.6.15",
2606
2606
+
"@types/phoenix": "^1.6.6",
2607
2607
+
"@types/ws": "^8.18.1",
2608
2608
+
"ws": "^8.18.2"
2609
2609
+
}
2610
2610
+
},
2611
2611
+
"node_modules/@supabase/storage-js": {
2612
2612
+
"version": "2.75.0",
2613
2613
+
"resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.75.0.tgz",
2614
2614
+
"integrity": "sha512-wpJMYdfFDckDiHQaTpK+Ib14N/O2o0AAWWhguKvmmMurB6Unx17GGmYp5rrrqCTf8S1qq4IfIxTXxS4hzrUySg==",
2615
2615
+
"license": "MIT",
2616
2616
+
"dependencies": {
2617
2617
+
"@supabase/node-fetch": "2.6.15"
2618
2618
+
}
2619
2619
+
},
2620
2620
+
"node_modules/@supabase/supabase-js": {
2621
2621
+
"version": "2.75.0",
2622
2622
+
"resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.75.0.tgz",
2623
2623
+
"integrity": "sha512-8UN/vATSgS2JFuJlMVr51L3eUDz+j1m7Ww63wlvHLKULzCDaVWYzvacCjBTLW/lX/vedI2LBI4Vg+01G9ufsJQ==",
2624
2624
+
"license": "MIT",
2625
2625
+
"dependencies": {
2626
2626
+
"@supabase/auth-js": "2.75.0",
2627
2627
+
"@supabase/functions-js": "2.75.0",
2628
2628
+
"@supabase/node-fetch": "2.6.15",
2629
2629
+
"@supabase/postgrest-js": "2.75.0",
2630
2630
+
"@supabase/realtime-js": "2.75.0",
2631
2631
+
"@supabase/storage-js": "2.75.0"
2632
2632
+
}
2633
2633
+
},
2548
2634
"node_modules/@swc/core": {
2549
2635
"version": "1.13.2",
2550
2636
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.2.tgz",
···
2907
2993
"version": "22.16.5",
2908
2994
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.16.5.tgz",
2909
2995
"integrity": "sha512-bJFoMATwIGaxxx8VJPeM8TonI8t579oRvgAuT8zFugJsJZgzqv0Fu8Mhp68iecjzG7cnN3mO2dJQ5uUM2EFrgQ==",
2910
2910
-
"dev": true,
2911
2996
"license": "MIT",
2912
2997
"dependencies": {
2913
2998
"undici-types": "~6.21.0"
2914
2999
}
2915
3000
},
3001
3001
+
"node_modules/@types/phoenix": {
3002
3002
+
"version": "1.6.6",
3003
3003
+
"resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz",
3004
3004
+
"integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==",
3005
3005
+
"license": "MIT"
3006
3006
+
},
2916
3007
"node_modules/@types/prop-types": {
2917
3008
"version": "15.7.13",
2918
3009
"resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
2919
3010
"integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==",
2920
2920
-
"devOptional": true,
3011
3011
+
"dev": true,
2921
3012
"license": "MIT"
2922
3013
},
2923
3014
"node_modules/@types/react": {
2924
3015
"version": "18.3.23",
2925
3016
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.23.tgz",
2926
3017
"integrity": "sha512-/LDXMQh55EzZQ0uVAZmKKhfENivEvWz6E+EYzh+/MCjMhNsotd+ZHhBGIjFDTi6+fz0OhQQQLbTgdQIxxCsC0w==",
2927
2927
-
"devOptional": true,
3018
3018
+
"dev": true,
2928
3019
"license": "MIT",
2929
3020
"dependencies": {
2930
3021
"@types/prop-types": "*",
···
2935
3026
"version": "18.3.7",
2936
3027
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
2937
3028
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
2938
2938
-
"devOptional": true,
3029
3029
+
"dev": true,
2939
3030
"license": "MIT",
2940
3031
"peerDependencies": {
2941
3032
"@types/react": "^18.0.0"
3033
3033
+
}
3034
3034
+
},
3035
3035
+
"node_modules/@types/ws": {
3036
3036
+
"version": "8.18.1",
3037
3037
+
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
3038
3038
+
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
3039
3039
+
"license": "MIT",
3040
3040
+
"dependencies": {
3041
3041
+
"@types/node": "*"
2942
3042
}
2943
3043
},
2944
3044
"node_modules/@typescript-eslint/eslint-plugin": {
···
3257
3357
"version": "6.1.0",
3258
3358
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
3259
3359
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
3360
3360
+
"dev": true,
3260
3361
"license": "MIT",
3261
3362
"engines": {
3262
3363
"node": ">=12"
···
3269
3370
"version": "4.3.0",
3270
3371
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
3271
3372
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
3373
3373
+
"dev": true,
3272
3374
"license": "MIT",
3273
3375
"dependencies": {
3274
3376
"color-convert": "^2.0.1"
···
3284
3386
"version": "1.3.0",
3285
3387
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
3286
3388
"integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
3389
3389
+
"dev": true,
3287
3390
"license": "MIT"
3288
3391
},
3289
3392
"node_modules/anymatch": {
3290
3393
"version": "3.1.3",
3291
3394
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
3292
3395
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
3396
3396
+
"dev": true,
3293
3397
"license": "ISC",
3294
3398
"dependencies": {
3295
3399
"normalize-path": "^3.0.0",
···
3303
3407
"version": "5.0.2",
3304
3408
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
3305
3409
"integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
3410
3410
+
"dev": true,
3306
3411
"license": "MIT"
3307
3412
},
3308
3413
"node_modules/argparse": {
···
3366
3471
"version": "1.0.2",
3367
3472
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
3368
3473
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
3474
3474
+
"dev": true,
3369
3475
"license": "MIT"
3370
3476
},
3371
3477
"node_modules/binary-extensions": {
3372
3478
"version": "2.3.0",
3373
3479
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
3374
3480
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
3481
3481
+
"dev": true,
3375
3482
"license": "MIT",
3376
3483
"engines": {
3377
3484
"node": ">=8"
···
3395
3502
"version": "3.0.3",
3396
3503
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
3397
3504
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
3505
3505
+
"dev": true,
3398
3506
"license": "MIT",
3399
3507
"dependencies": {
3400
3508
"fill-range": "^7.1.1"
···
3450
3558
"version": "2.0.1",
3451
3559
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
3452
3560
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
3561
3561
+
"dev": true,
3453
3562
"license": "MIT",
3454
3563
"engines": {
3455
3564
"node": ">= 6"
···
3497
3606
"version": "3.6.0",
3498
3607
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
3499
3608
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
3609
3609
+
"dev": true,
3500
3610
"license": "MIT",
3501
3611
"dependencies": {
3502
3612
"anymatch": "~3.1.2",
···
3521
3631
"version": "5.1.2",
3522
3632
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
3523
3633
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
3634
3634
+
"dev": true,
3524
3635
"license": "ISC",
3525
3636
"dependencies": {
3526
3637
"is-glob": "^4.0.1"
···
3569
3680
"version": "2.0.1",
3570
3681
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
3571
3682
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
3683
3683
+
"dev": true,
3572
3684
"license": "MIT",
3573
3685
"dependencies": {
3574
3686
"color-name": "~1.1.4"
···
3581
3693
"version": "1.1.4",
3582
3694
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
3583
3695
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
3696
3696
+
"dev": true,
3584
3697
"license": "MIT"
3585
3698
},
3586
3699
"node_modules/commander": {
3587
3700
"version": "4.1.1",
3588
3701
"resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
3589
3702
"integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
3703
3703
+
"dev": true,
3590
3704
"license": "MIT",
3591
3705
"engines": {
3592
3706
"node": ">= 6"
···
3603
3717
"version": "7.0.6",
3604
3718
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
3605
3719
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
3720
3720
+
"dev": true,
3606
3721
"dependencies": {
3607
3722
"path-key": "^3.1.0",
3608
3723
"shebang-command": "^2.0.0",
···
3616
3731
"version": "3.0.0",
3617
3732
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
3618
3733
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
3734
3734
+
"dev": true,
3619
3735
"license": "MIT",
3620
3736
"bin": {
3621
3737
"cssesc": "bin/cssesc"
···
3802
3918
"version": "1.2.2",
3803
3919
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
3804
3920
"integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
3921
3921
+
"dev": true,
3805
3922
"license": "Apache-2.0"
3806
3923
},
3807
3924
"node_modules/dlv": {
3808
3925
"version": "1.1.3",
3809
3926
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
3810
3927
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
3928
3928
+
"dev": true,
3811
3929
"license": "MIT"
3812
3930
},
3813
3931
"node_modules/dom-helpers": {
···
3824
3942
"version": "0.2.0",
3825
3943
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
3826
3944
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
3945
3945
+
"dev": true,
3827
3946
"license": "MIT"
3828
3947
},
3829
3948
"node_modules/electron-to-chromium": {
···
3865
3984
"version": "9.2.2",
3866
3985
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
3867
3986
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
3987
3987
+
"dev": true,
3868
3988
"license": "MIT"
3869
3989
},
3870
3990
"node_modules/esbuild": {
···
4143
4263
"version": "3.3.2",
4144
4264
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
4145
4265
"integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
4266
4266
+
"dev": true,
4146
4267
"license": "MIT",
4147
4268
"dependencies": {
4148
4269
"@nodelib/fs.stat": "^2.0.2",
···
4159
4280
"version": "5.1.2",
4160
4281
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
4161
4282
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
4283
4283
+
"dev": true,
4162
4284
"license": "ISC",
4163
4285
"dependencies": {
4164
4286
"is-glob": "^4.0.1"
···
4185
4307
"version": "1.17.1",
4186
4308
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
4187
4309
"integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
4310
4310
+
"dev": true,
4188
4311
"license": "ISC",
4189
4312
"dependencies": {
4190
4313
"reusify": "^1.0.4"
···
4207
4330
"version": "7.1.1",
4208
4331
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
4209
4332
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
4333
4333
+
"dev": true,
4210
4334
"license": "MIT",
4211
4335
"dependencies": {
4212
4336
"to-regex-range": "^5.0.1"
···
4257
4381
"version": "3.3.0",
4258
4382
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
4259
4383
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
4384
4384
+
"dev": true,
4260
4385
"license": "ISC",
4261
4386
"dependencies": {
4262
4387
"cross-spawn": "^7.0.0",
···
4287
4412
"version": "2.3.3",
4288
4413
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
4289
4414
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
4415
4415
+
"dev": true,
4290
4416
"hasInstallScript": true,
4291
4417
"license": "MIT",
4292
4418
"optional": true,
···
4301
4427
"version": "1.1.2",
4302
4428
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
4303
4429
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
4430
4430
+
"dev": true,
4304
4431
"license": "MIT",
4305
4432
"funding": {
4306
4433
"url": "https://github.com/sponsors/ljharb"
···
4319
4446
"version": "10.4.5",
4320
4447
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
4321
4448
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
4449
4449
+
"dev": true,
4322
4450
"license": "ISC",
4323
4451
"dependencies": {
4324
4452
"foreground-child": "^3.1.0",
···
4339
4467
"version": "6.0.2",
4340
4468
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
4341
4469
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
4470
4470
+
"dev": true,
4342
4471
"license": "ISC",
4343
4472
"dependencies": {
4344
4473
"is-glob": "^4.0.3"
···
4351
4480
"version": "2.0.2",
4352
4481
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
4353
4482
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
4483
4483
+
"dev": true,
4354
4484
"license": "MIT",
4355
4485
"dependencies": {
4356
4486
"balanced-match": "^1.0.0"
···
4360
4490
"version": "9.0.5",
4361
4491
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
4362
4492
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
4493
4493
+
"dev": true,
4363
4494
"license": "ISC",
4364
4495
"dependencies": {
4365
4496
"brace-expansion": "^2.0.1"
···
4405
4536
"version": "2.0.2",
4406
4537
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
4407
4538
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
4539
4539
+
"dev": true,
4408
4540
"license": "MIT",
4409
4541
"dependencies": {
4410
4542
"function-bind": "^1.1.2"
···
4473
4605
"version": "2.1.0",
4474
4606
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
4475
4607
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
4608
4608
+
"dev": true,
4476
4609
"license": "MIT",
4477
4610
"dependencies": {
4478
4611
"binary-extensions": "^2.0.0"
···
4485
4618
"version": "2.15.1",
4486
4619
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
4487
4620
"integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
4621
4621
+
"dev": true,
4488
4622
"license": "MIT",
4489
4623
"dependencies": {
4490
4624
"hasown": "^2.0.2"
···
4500
4634
"version": "2.1.1",
4501
4635
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
4502
4636
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
4637
4637
+
"dev": true,
4503
4638
"license": "MIT",
4504
4639
"engines": {
4505
4640
"node": ">=0.10.0"
···
4509
4644
"version": "3.0.0",
4510
4645
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
4511
4646
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
4647
4647
+
"dev": true,
4512
4648
"license": "MIT",
4513
4649
"engines": {
4514
4650
"node": ">=8"
···
4518
4654
"version": "4.0.3",
4519
4655
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
4520
4656
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
4657
4657
+
"dev": true,
4521
4658
"license": "MIT",
4522
4659
"dependencies": {
4523
4660
"is-extglob": "^2.1.1"
···
4530
4667
"version": "7.0.0",
4531
4668
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
4532
4669
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
4670
4670
+
"dev": true,
4533
4671
"license": "MIT",
4534
4672
"engines": {
4535
4673
"node": ">=0.12.0"
···
4539
4677
"version": "2.0.0",
4540
4678
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
4541
4679
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
4680
4680
+
"dev": true,
4542
4681
"license": "ISC"
4543
4682
},
4544
4683
"node_modules/jackspeak": {
4545
4684
"version": "3.4.3",
4546
4685
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
4547
4686
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
4687
4687
+
"dev": true,
4548
4688
"license": "BlueOak-1.0.0",
4549
4689
"dependencies": {
4550
4690
"@isaacs/cliui": "^8.0.2"
···
4560
4700
"version": "1.21.6",
4561
4701
"resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
4562
4702
"integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
4703
4703
+
"dev": true,
4563
4704
"license": "MIT",
4564
4705
"bin": {
4565
4706
"jiti": "bin/jiti.js"
···
4633
4774
"version": "3.1.3",
4634
4775
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
4635
4776
"integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
4777
4777
+
"dev": true,
4636
4778
"license": "MIT",
4637
4779
"engines": {
4638
4780
"node": ">=14"
···
4645
4787
"version": "1.2.4",
4646
4788
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
4647
4789
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
4790
4790
+
"dev": true,
4648
4791
"license": "MIT"
4649
4792
},
4650
4793
"node_modules/locate-path": {
···
5154
5297
"version": "10.4.3",
5155
5298
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
5156
5299
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
5300
5300
+
"dev": true,
5157
5301
"license": "ISC"
5158
5302
},
5159
5303
"node_modules/lucide-react": {
···
5178
5322
"version": "1.4.1",
5179
5323
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
5180
5324
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
5325
5325
+
"dev": true,
5181
5326
"license": "MIT",
5182
5327
"engines": {
5183
5328
"node": ">= 8"
···
5187
5332
"version": "4.0.8",
5188
5333
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
5189
5334
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
5335
5335
+
"dev": true,
5190
5336
"license": "MIT",
5191
5337
"dependencies": {
5192
5338
"braces": "^3.0.3",
···
5213
5359
"version": "7.1.2",
5214
5360
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
5215
5361
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
5362
5362
+
"dev": true,
5216
5363
"license": "ISC",
5217
5364
"engines": {
5218
5365
"node": ">=16 || 14 >=14.17"
···
5229
5376
"version": "2.7.0",
5230
5377
"resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
5231
5378
"integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
5379
5379
+
"dev": true,
5232
5380
"license": "MIT",
5233
5381
"dependencies": {
5234
5382
"any-promise": "^1.0.0",
···
5240
5388
"version": "3.3.11",
5241
5389
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
5242
5390
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
5391
5391
+
"dev": true,
5243
5392
"funding": [
5244
5393
{
5245
5394
"type": "github",
···
5282
5431
"version": "3.0.0",
5283
5432
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
5284
5433
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
5434
5434
+
"dev": true,
5285
5435
"license": "MIT",
5286
5436
"engines": {
5287
5437
"node": ">=0.10.0"
···
5310
5460
"version": "3.0.0",
5311
5461
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
5312
5462
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
5463
5463
+
"dev": true,
5313
5464
"license": "MIT",
5314
5465
"engines": {
5315
5466
"node": ">= 6"
···
5369
5520
"version": "1.0.1",
5370
5521
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
5371
5522
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
5523
5523
+
"dev": true,
5372
5524
"license": "BlueOak-1.0.0"
5373
5525
},
5374
5526
"node_modules/parent-module": {
···
5398
5550
"version": "3.1.1",
5399
5551
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
5400
5552
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
5553
5553
+
"dev": true,
5401
5554
"license": "MIT",
5402
5555
"engines": {
5403
5556
"node": ">=8"
···
5407
5560
"version": "1.0.7",
5408
5561
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
5409
5562
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
5563
5563
+
"dev": true,
5410
5564
"license": "MIT"
5411
5565
},
5412
5566
"node_modules/path-scurry": {
5413
5567
"version": "1.11.1",
5414
5568
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
5415
5569
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
5570
5570
+
"dev": true,
5416
5571
"license": "BlueOak-1.0.0",
5417
5572
"dependencies": {
5418
5573
"lru-cache": "^10.2.0",
···
5429
5584
"version": "1.1.1",
5430
5585
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
5431
5586
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
5587
5587
+
"dev": true,
5432
5588
"license": "ISC"
5433
5589
},
5434
5590
"node_modules/picomatch": {
5435
5591
"version": "2.3.1",
5436
5592
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
5437
5593
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
5594
5594
+
"dev": true,
5438
5595
"license": "MIT",
5439
5596
"engines": {
5440
5597
"node": ">=8.6"
···
5447
5604
"version": "2.3.0",
5448
5605
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
5449
5606
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
5607
5607
+
"dev": true,
5450
5608
"license": "MIT",
5451
5609
"engines": {
5452
5610
"node": ">=0.10.0"
···
5456
5614
"version": "4.0.6",
5457
5615
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
5458
5616
"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
5617
5617
+
"dev": true,
5459
5618
"license": "MIT",
5460
5619
"engines": {
5461
5620
"node": ">= 6"
···
5465
5624
"version": "8.5.6",
5466
5625
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz",
5467
5626
"integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
5627
5627
+
"dev": true,
5468
5628
"funding": [
5469
5629
{
5470
5630
"type": "opencollective",
···
5493
5653
"version": "15.1.0",
5494
5654
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
5495
5655
"integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
5656
5656
+
"dev": true,
5496
5657
"license": "MIT",
5497
5658
"dependencies": {
5498
5659
"postcss-value-parser": "^4.0.0",
···
5510
5671
"version": "4.0.1",
5511
5672
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
5512
5673
"integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
5674
5674
+
"dev": true,
5513
5675
"license": "MIT",
5514
5676
"dependencies": {
5515
5677
"camelcase-css": "^2.0.1"
···
5529
5691
"version": "4.0.2",
5530
5692
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
5531
5693
"integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
5694
5694
+
"dev": true,
5532
5695
"funding": [
5533
5696
{
5534
5697
"type": "opencollective",
···
5564
5727
"version": "6.2.0",
5565
5728
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
5566
5729
"integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
5730
5730
+
"dev": true,
5567
5731
"funding": [
5568
5732
{
5569
5733
"type": "opencollective",
···
5589
5753
"version": "6.1.2",
5590
5754
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
5591
5755
"integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
5756
5756
+
"dev": true,
5592
5757
"license": "MIT",
5593
5758
"dependencies": {
5594
5759
"cssesc": "^3.0.0",
···
5602
5767
"version": "4.2.0",
5603
5768
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
5604
5769
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
5770
5770
+
"dev": true,
5605
5771
"license": "MIT"
5606
5772
},
5607
5773
"node_modules/prelude-ls": {
···
5645
5811
"version": "1.2.3",
5646
5812
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
5647
5813
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
5814
5814
+
"dev": true,
5648
5815
"funding": [
5649
5816
{
5650
5817
"type": "github",
···
5868
6035
"version": "1.0.0",
5869
6036
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
5870
6037
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
6038
6038
+
"dev": true,
5871
6039
"license": "MIT",
5872
6040
"dependencies": {
5873
6041
"pify": "^2.3.0"
···
5877
6045
"version": "3.6.0",
5878
6046
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
5879
6047
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
6048
6048
+
"dev": true,
5880
6049
"license": "MIT",
5881
6050
"dependencies": {
5882
6051
"picomatch": "^2.2.1"
···
5921
6090
"version": "1.22.8",
5922
6091
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
5923
6092
"integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
6093
6093
+
"dev": true,
5924
6094
"license": "MIT",
5925
6095
"dependencies": {
5926
6096
"is-core-module": "^2.13.0",
···
5948
6118
"version": "1.0.4",
5949
6119
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
5950
6120
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
6121
6121
+
"dev": true,
5951
6122
"license": "MIT",
5952
6123
"engines": {
5953
6124
"iojs": ">=1.0.0",
···
5994
6165
"version": "1.2.0",
5995
6166
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
5996
6167
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
6168
6168
+
"dev": true,
5997
6169
"funding": [
5998
6170
{
5999
6171
"type": "github",
···
6039
6211
"version": "2.0.0",
6040
6212
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
6041
6213
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
6214
6214
+
"dev": true,
6042
6215
"license": "MIT",
6043
6216
"dependencies": {
6044
6217
"shebang-regex": "^3.0.0"
···
6051
6224
"version": "3.0.0",
6052
6225
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
6053
6226
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
6227
6227
+
"dev": true,
6054
6228
"license": "MIT",
6055
6229
"engines": {
6056
6230
"node": ">=8"
···
6060
6234
"version": "4.1.0",
6061
6235
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
6062
6236
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
6237
6237
+
"dev": true,
6063
6238
"license": "ISC",
6064
6239
"engines": {
6065
6240
"node": ">=14"
···
6082
6257
"version": "1.2.1",
6083
6258
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
6084
6259
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
6260
6260
+
"dev": true,
6085
6261
"license": "BSD-3-Clause",
6086
6262
"engines": {
6087
6263
"node": ">=0.10.0"
···
6091
6267
"version": "5.1.2",
6092
6268
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
6093
6269
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
6270
6270
+
"dev": true,
6094
6271
"license": "MIT",
6095
6272
"dependencies": {
6096
6273
"eastasianwidth": "^0.2.0",
···
6109
6286
"version": "4.2.3",
6110
6287
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
6111
6288
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
6289
6289
+
"dev": true,
6112
6290
"license": "MIT",
6113
6291
"dependencies": {
6114
6292
"emoji-regex": "^8.0.0",
···
6123
6301
"version": "5.0.1",
6124
6302
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
6125
6303
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
6304
6304
+
"dev": true,
6126
6305
"license": "MIT",
6127
6306
"engines": {
6128
6307
"node": ">=8"
···
6132
6311
"version": "8.0.0",
6133
6312
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
6134
6313
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
6314
6314
+
"dev": true,
6135
6315
"license": "MIT"
6136
6316
},
6137
6317
"node_modules/string-width-cjs/node_modules/strip-ansi": {
6138
6318
"version": "6.0.1",
6139
6319
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6140
6320
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
6321
6321
+
"dev": true,
6141
6322
"license": "MIT",
6142
6323
"dependencies": {
6143
6324
"ansi-regex": "^5.0.1"
···
6150
6331
"version": "7.1.0",
6151
6332
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
6152
6333
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
6334
6334
+
"dev": true,
6153
6335
"license": "MIT",
6154
6336
"dependencies": {
6155
6337
"ansi-regex": "^6.0.1"
···
6166
6348
"version": "6.0.1",
6167
6349
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6168
6350
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
6351
6351
+
"dev": true,
6169
6352
"license": "MIT",
6170
6353
"dependencies": {
6171
6354
"ansi-regex": "^5.0.1"
···
6178
6361
"version": "5.0.1",
6179
6362
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
6180
6363
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
6364
6364
+
"dev": true,
6181
6365
"license": "MIT",
6182
6366
"engines": {
6183
6367
"node": ">=8"
···
6200
6384
"version": "3.35.0",
6201
6385
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
6202
6386
"integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
6387
6387
+
"dev": true,
6203
6388
"license": "MIT",
6204
6389
"dependencies": {
6205
6390
"@jridgewell/gen-mapping": "^0.3.2",
···
6235
6420
"version": "1.0.0",
6236
6421
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
6237
6422
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
6423
6423
+
"dev": true,
6238
6424
"license": "MIT",
6239
6425
"engines": {
6240
6426
"node": ">= 0.4"
···
6257
6443
"version": "3.4.17",
6258
6444
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz",
6259
6445
"integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==",
6446
6446
+
"dev": true,
6260
6447
"license": "MIT",
6261
6448
"dependencies": {
6262
6449
"@alloc/quick-lru": "^5.2.0",
···
6303
6490
"version": "3.3.1",
6304
6491
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
6305
6492
"integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
6493
6493
+
"dev": true,
6306
6494
"license": "MIT",
6307
6495
"dependencies": {
6308
6496
"any-promise": "^1.0.0"
···
6312
6500
"version": "1.6.0",
6313
6501
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
6314
6502
"integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
6503
6503
+
"dev": true,
6315
6504
"license": "MIT",
6316
6505
"dependencies": {
6317
6506
"thenify": ">= 3.1.0 < 4"
···
6330
6519
"version": "5.0.1",
6331
6520
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
6332
6521
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
6522
6522
+
"dev": true,
6333
6523
"license": "MIT",
6334
6524
"dependencies": {
6335
6525
"is-number": "^7.0.0"
···
6338
6528
"node": ">=8.0"
6339
6529
}
6340
6530
},
6531
6531
+
"node_modules/tr46": {
6532
6532
+
"version": "0.0.3",
6533
6533
+
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
6534
6534
+
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
6535
6535
+
"license": "MIT"
6536
6536
+
},
6341
6537
"node_modules/ts-api-utils": {
6342
6538
"version": "2.1.0",
6343
6539
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
···
6355
6551
"version": "0.1.13",
6356
6552
"resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
6357
6553
"integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
6554
6554
+
"dev": true,
6358
6555
"license": "Apache-2.0"
6359
6556
},
6360
6557
"node_modules/tslib": {
···
6418
6615
"version": "6.21.0",
6419
6616
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
6420
6617
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
6421
6421
-
"dev": true,
6422
6618
"license": "MIT"
6423
6619
},
6424
6620
"node_modules/update-browserslist-db": {
···
6518
6714
"version": "1.0.2",
6519
6715
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
6520
6716
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
6717
6717
+
"dev": true,
6521
6718
"license": "MIT"
6522
6719
},
6523
6720
"node_modules/vaul": {
···
6615
6812
}
6616
6813
}
6617
6814
},
6815
6815
+
"node_modules/webidl-conversions": {
6816
6816
+
"version": "3.0.1",
6817
6817
+
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
6818
6818
+
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
6819
6819
+
"license": "BSD-2-Clause"
6820
6820
+
},
6821
6821
+
"node_modules/whatwg-url": {
6822
6822
+
"version": "5.0.0",
6823
6823
+
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
6824
6824
+
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
6825
6825
+
"license": "MIT",
6826
6826
+
"dependencies": {
6827
6827
+
"tr46": "~0.0.3",
6828
6828
+
"webidl-conversions": "^3.0.0"
6829
6829
+
}
6830
6830
+
},
6618
6831
"node_modules/which": {
6619
6832
"version": "2.0.2",
6620
6833
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
6621
6834
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
6835
6835
+
"dev": true,
6622
6836
"license": "ISC",
6623
6837
"dependencies": {
6624
6838
"isexe": "^2.0.0"
···
6644
6858
"version": "8.1.0",
6645
6859
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
6646
6860
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
6861
6861
+
"dev": true,
6647
6862
"license": "MIT",
6648
6863
"dependencies": {
6649
6864
"ansi-styles": "^6.1.0",
···
6662
6877
"version": "7.0.0",
6663
6878
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
6664
6879
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
6880
6880
+
"dev": true,
6665
6881
"license": "MIT",
6666
6882
"dependencies": {
6667
6883
"ansi-styles": "^4.0.0",
···
6679
6895
"version": "5.0.1",
6680
6896
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
6681
6897
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
6898
6898
+
"dev": true,
6682
6899
"license": "MIT",
6683
6900
"engines": {
6684
6901
"node": ">=8"
···
6688
6905
"version": "8.0.0",
6689
6906
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
6690
6907
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
6908
6908
+
"dev": true,
6691
6909
"license": "MIT"
6692
6910
},
6693
6911
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
6694
6912
"version": "4.2.3",
6695
6913
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
6696
6914
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
6915
6915
+
"dev": true,
6697
6916
"license": "MIT",
6698
6917
"dependencies": {
6699
6918
"emoji-regex": "^8.0.0",
···
6708
6927
"version": "6.0.1",
6709
6928
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
6710
6929
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
6930
6930
+
"dev": true,
6711
6931
"license": "MIT",
6712
6932
"dependencies": {
6713
6933
"ansi-regex": "^5.0.1"
···
6720
6940
"version": "6.2.1",
6721
6941
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
6722
6942
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
6943
6943
+
"dev": true,
6723
6944
"license": "MIT",
6724
6945
"engines": {
6725
6946
"node": ">=12"
···
6728
6949
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
6729
6950
}
6730
6951
},
6952
6952
+
"node_modules/ws": {
6953
6953
+
"version": "8.18.3",
6954
6954
+
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
6955
6955
+
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
6956
6956
+
"license": "MIT",
6957
6957
+
"engines": {
6958
6958
+
"node": ">=10.0.0"
6959
6959
+
},
6960
6960
+
"peerDependencies": {
6961
6961
+
"bufferutil": "^4.0.1",
6962
6962
+
"utf-8-validate": ">=5.0.2"
6963
6963
+
},
6964
6964
+
"peerDependenciesMeta": {
6965
6965
+
"bufferutil": {
6966
6966
+
"optional": true
6967
6967
+
},
6968
6968
+
"utf-8-validate": {
6969
6969
+
"optional": true
6970
6970
+
}
6971
6971
+
}
6972
6972
+
},
6731
6973
"node_modules/yaml": {
6732
6974
"version": "2.6.0",
6733
6975
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
6734
6976
"integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
6977
6977
+
"dev": true,
6735
6978
"license": "ISC",
6736
6979
"bin": {
6737
6980
"yaml": "bin.mjs"
+1
package.json
···
39
39
"@radix-ui/react-toggle": "^1.1.9",
40
40
"@radix-ui/react-toggle-group": "^1.1.10",
41
41
"@radix-ui/react-tooltip": "^1.2.7",
42
42
+
"@supabase/supabase-js": "^2.75.0",
42
43
"@tanstack/react-query": "^5.83.0",
43
44
"class-variance-authority": "^0.7.1",
44
45
"clsx": "^2.1.1",
+2
src/App.tsx
···
4
4
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
5
5
import { BrowserRouter, Routes, Route } from "react-router-dom";
6
6
import Index from "./pages/Index";
7
7
+
import Docs from "./pages/Docs";
7
8
import NotFound from "./pages/NotFound";
8
9
9
10
const queryClient = new QueryClient();
···
16
17
<BrowserRouter>
17
18
<Routes>
18
19
<Route path="/" element={<Index />} />
20
20
+
<Route path="/docs" element={<Docs />} />
19
21
{/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL "*" ROUTE */}
20
22
<Route path="*" element={<NotFound />} />
21
23
</Routes>
+9
-1
src/components/SEOTester.tsx
···
1
1
import React, { useState, useEffect } from 'react';
2
2
+
import { Link } from 'react-router-dom';
2
3
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
3
4
import { Button } from '@/components/ui/button';
4
5
import { Input } from '@/components/ui/input';
···
6
7
import { Separator } from '@/components/ui/separator';
7
8
import { Progress } from '@/components/ui/progress';
8
9
import { useToast } from '@/hooks/use-toast';
9
9
-
import { Search, ExternalLink, Image, FileText, Tag, Globe, AlertCircle, CheckCircle, Zap, TrendingUp, Eye, Share2, Target, Terminal, Code, Bug, Cpu, Database, Monitor, Server } from 'lucide-react';
10
10
+
import { Search, ExternalLink, Image, FileText, Tag, Globe, AlertCircle, CheckCircle, Zap, TrendingUp, Eye, Share2, Target, Terminal, Code, Bug, Cpu, Database, Monitor, Server, Book } from 'lucide-react';
10
11
11
12
interface SEOData {
12
13
title?: string;
···
285
286
<div className="w-2 h-2 rounded-full bg-success animate-pulse"></div>
286
287
<span className="text-muted-foreground font-mono">dev-tools</span>
287
288
</div>
289
289
+
<Separator orientation="vertical" className="h-4" />
290
290
+
<Link to="/docs">
291
291
+
<Button variant="ghost" size="sm" className="text-xs font-mono">
292
292
+
<Book className="h-3 w-3 mr-1" />
293
293
+
API Docs
294
294
+
</Button>
295
295
+
</Link>
288
296
</div>
289
297
290
298
<div className="text-left">
+17
src/integrations/supabase/client.ts
···
1
1
+
// This file is automatically generated. Do not edit it directly.
2
2
+
import { createClient } from '@supabase/supabase-js';
3
3
+
import type { Database } from './types';
4
4
+
5
5
+
const SUPABASE_URL = import.meta.env.VITE_SUPABASE_URL;
6
6
+
const SUPABASE_PUBLISHABLE_KEY = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY;
7
7
+
8
8
+
// Import the supabase client like this:
9
9
+
// import { supabase } from "@/integrations/supabase/client";
10
10
+
11
11
+
export const supabase = createClient<Database>(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, {
12
12
+
auth: {
13
13
+
storage: localStorage,
14
14
+
persistSession: true,
15
15
+
autoRefreshToken: true,
16
16
+
}
17
17
+
});
+155
src/integrations/supabase/types.ts
···
1
1
+
export type Json =
2
2
+
| string
3
3
+
| number
4
4
+
| boolean
5
5
+
| null
6
6
+
| { [key: string]: Json | undefined }
7
7
+
| Json[]
8
8
+
9
9
+
export type Database = {
10
10
+
// Allows to automatically instantiate createClient with right options
11
11
+
// instead of createClient<Database, { PostgrestVersion: 'XX' }>(URL, KEY)
12
12
+
__InternalSupabase: {
13
13
+
PostgrestVersion: "13.0.5"
14
14
+
}
15
15
+
public: {
16
16
+
Tables: {
17
17
+
[_ in never]: never
18
18
+
}
19
19
+
Views: {
20
20
+
[_ in never]: never
21
21
+
}
22
22
+
Functions: {
23
23
+
[_ in never]: never
24
24
+
}
25
25
+
Enums: {
26
26
+
[_ in never]: never
27
27
+
}
28
28
+
CompositeTypes: {
29
29
+
[_ in never]: never
30
30
+
}
31
31
+
}
32
32
+
}
33
33
+
34
34
+
type DatabaseWithoutInternals = Omit<Database, "__InternalSupabase">
35
35
+
36
36
+
type DefaultSchema = DatabaseWithoutInternals[Extract<keyof Database, "public">]
37
37
+
38
38
+
export type Tables<
39
39
+
DefaultSchemaTableNameOrOptions extends
40
40
+
| keyof (DefaultSchema["Tables"] & DefaultSchema["Views"])
41
41
+
| { schema: keyof DatabaseWithoutInternals },
42
42
+
TableName extends DefaultSchemaTableNameOrOptions extends {
43
43
+
schema: keyof DatabaseWithoutInternals
44
44
+
}
45
45
+
? keyof (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] &
46
46
+
DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"])
47
47
+
: never = never,
48
48
+
> = DefaultSchemaTableNameOrOptions extends {
49
49
+
schema: keyof DatabaseWithoutInternals
50
50
+
}
51
51
+
? (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] &
52
52
+
DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"])[TableName] extends {
53
53
+
Row: infer R
54
54
+
}
55
55
+
? R
56
56
+
: never
57
57
+
: DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema["Tables"] &
58
58
+
DefaultSchema["Views"])
59
59
+
? (DefaultSchema["Tables"] &
60
60
+
DefaultSchema["Views"])[DefaultSchemaTableNameOrOptions] extends {
61
61
+
Row: infer R
62
62
+
}
63
63
+
? R
64
64
+
: never
65
65
+
: never
66
66
+
67
67
+
export type TablesInsert<
68
68
+
DefaultSchemaTableNameOrOptions extends
69
69
+
| keyof DefaultSchema["Tables"]
70
70
+
| { schema: keyof DatabaseWithoutInternals },
71
71
+
TableName extends DefaultSchemaTableNameOrOptions extends {
72
72
+
schema: keyof DatabaseWithoutInternals
73
73
+
}
74
74
+
? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"]
75
75
+
: never = never,
76
76
+
> = DefaultSchemaTableNameOrOptions extends {
77
77
+
schema: keyof DatabaseWithoutInternals
78
78
+
}
79
79
+
? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends {
80
80
+
Insert: infer I
81
81
+
}
82
82
+
? I
83
83
+
: never
84
84
+
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"]
85
85
+
? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends {
86
86
+
Insert: infer I
87
87
+
}
88
88
+
? I
89
89
+
: never
90
90
+
: never
91
91
+
92
92
+
export type TablesUpdate<
93
93
+
DefaultSchemaTableNameOrOptions extends
94
94
+
| keyof DefaultSchema["Tables"]
95
95
+
| { schema: keyof DatabaseWithoutInternals },
96
96
+
TableName extends DefaultSchemaTableNameOrOptions extends {
97
97
+
schema: keyof DatabaseWithoutInternals
98
98
+
}
99
99
+
? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"]
100
100
+
: never = never,
101
101
+
> = DefaultSchemaTableNameOrOptions extends {
102
102
+
schema: keyof DatabaseWithoutInternals
103
103
+
}
104
104
+
? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends {
105
105
+
Update: infer U
106
106
+
}
107
107
+
? U
108
108
+
: never
109
109
+
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"]
110
110
+
? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends {
111
111
+
Update: infer U
112
112
+
}
113
113
+
? U
114
114
+
: never
115
115
+
: never
116
116
+
117
117
+
export type Enums<
118
118
+
DefaultSchemaEnumNameOrOptions extends
119
119
+
| keyof DefaultSchema["Enums"]
120
120
+
| { schema: keyof DatabaseWithoutInternals },
121
121
+
EnumName extends DefaultSchemaEnumNameOrOptions extends {
122
122
+
schema: keyof DatabaseWithoutInternals
123
123
+
}
124
124
+
? keyof DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"]
125
125
+
: never = never,
126
126
+
> = DefaultSchemaEnumNameOrOptions extends {
127
127
+
schema: keyof DatabaseWithoutInternals
128
128
+
}
129
129
+
? DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"][EnumName]
130
130
+
: DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema["Enums"]
131
131
+
? DefaultSchema["Enums"][DefaultSchemaEnumNameOrOptions]
132
132
+
: never
133
133
+
134
134
+
export type CompositeTypes<
135
135
+
PublicCompositeTypeNameOrOptions extends
136
136
+
| keyof DefaultSchema["CompositeTypes"]
137
137
+
| { schema: keyof DatabaseWithoutInternals },
138
138
+
CompositeTypeName extends PublicCompositeTypeNameOrOptions extends {
139
139
+
schema: keyof DatabaseWithoutInternals
140
140
+
}
141
141
+
? keyof DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"]
142
142
+
: never = never,
143
143
+
> = PublicCompositeTypeNameOrOptions extends {
144
144
+
schema: keyof DatabaseWithoutInternals
145
145
+
}
146
146
+
? DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName]
147
147
+
: PublicCompositeTypeNameOrOptions extends keyof DefaultSchema["CompositeTypes"]
148
148
+
? DefaultSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions]
149
149
+
: never
150
150
+
151
151
+
export const Constants = {
152
152
+
public: {
153
153
+
Enums: {},
154
154
+
},
155
155
+
} as const
+380
src/pages/Docs.tsx
···
1
1
+
import React, { useState } from 'react';
2
2
+
import { Card, CardContent, CardHeader } from '@/components/ui/card';
3
3
+
import { Button } from '@/components/ui/button';
4
4
+
import { Separator } from '@/components/ui/separator';
5
5
+
import { Badge } from '@/components/ui/badge';
6
6
+
import { Code, Terminal, Book, ChevronRight, Copy, Check, Home } from 'lucide-react';
7
7
+
import { useToast } from '@/hooks/use-toast';
8
8
+
import { Link } from 'react-router-dom';
9
9
+
10
10
+
const Docs = () => {
11
11
+
const [copiedSection, setCopiedSection] = useState<string | null>(null);
12
12
+
const { toast } = useToast();
13
13
+
14
14
+
const copyToClipboard = (text: string, section: string) => {
15
15
+
navigator.clipboard.writeText(text);
16
16
+
setCopiedSection(section);
17
17
+
setTimeout(() => setCopiedSection(null), 2000);
18
18
+
toast({
19
19
+
title: "Copied!",
20
20
+
description: "Code copied to clipboard",
21
21
+
});
22
22
+
};
23
23
+
24
24
+
const apiUrl = 'https://gjhfnqiknusundbktwxs.supabase.co/functions/v1/analyze-seo';
25
25
+
26
26
+
return (
27
27
+
<div className="min-h-screen bg-background">
28
28
+
<div className="absolute inset-0 opacity-5">
29
29
+
<div className="absolute inset-0" style={{
30
30
+
backgroundImage: `radial-gradient(circle at 1px 1px, rgb(255,255,255) 1px, transparent 0)`,
31
31
+
backgroundSize: '20px 20px'
32
32
+
}}></div>
33
33
+
</div>
34
34
+
35
35
+
<div className="container mx-auto px-4 py-8 relative z-10">
36
36
+
<div className="max-w-4xl mx-auto">
37
37
+
{/* Header */}
38
38
+
<div className="mb-8 animate-fade-in">
39
39
+
<Link to="/" className="inline-flex items-center gap-2 text-sm font-mono text-muted-foreground hover:text-foreground mb-4">
40
40
+
<Home className="h-4 w-4" />
41
41
+
Back to SEO Tester
42
42
+
</Link>
43
43
+
44
44
+
<div className="flex items-center gap-3 mb-4 p-4 bg-muted/50 rounded-lg border border-border/50">
45
45
+
<Terminal className="h-5 w-5 text-primary" />
46
46
+
<div className="flex items-center gap-1 text-xs font-mono">
47
47
+
<span className="text-primary">$</span>
48
48
+
<span className="text-muted-foreground">api-documentation</span>
49
49
+
</div>
50
50
+
</div>
51
51
+
52
52
+
<h1 className="text-3xl font-bold text-foreground font-mono flex items-center gap-2">
53
53
+
<Book className="h-8 w-8 text-primary" />
54
54
+
SEO Analyzer API
55
55
+
</h1>
56
56
+
<p className="text-sm text-muted-foreground font-mono mt-2">
57
57
+
→ RESTful API for programmatic SEO analysis
58
58
+
</p>
59
59
+
</div>
60
60
+
61
61
+
{/* Quick Start */}
62
62
+
<Card className="mb-6 border border-border bg-card">
63
63
+
<CardHeader className="pb-3">
64
64
+
<div className="flex items-center justify-between">
65
65
+
<div className="flex items-center gap-2">
66
66
+
<Code className="h-4 w-4 text-primary" />
67
67
+
<span className="font-mono text-sm">Quick Start</span>
68
68
+
</div>
69
69
+
<Badge variant="outline" className="font-mono text-xs">GET STARTED</Badge>
70
70
+
</div>
71
71
+
</CardHeader>
72
72
+
<CardContent className="space-y-4">
73
73
+
<div>
74
74
+
<div className="flex items-center justify-between mb-2">
75
75
+
<span className="text-xs font-mono text-muted-foreground">ENDPOINT</span>
76
76
+
</div>
77
77
+
<div className="bg-muted/30 p-3 rounded font-mono text-sm border border-border/50 flex items-center justify-between">
78
78
+
<code className="text-primary break-all">{apiUrl}</code>
79
79
+
<Button
80
80
+
size="sm"
81
81
+
variant="ghost"
82
82
+
onClick={() => copyToClipboard(apiUrl, 'endpoint')}
83
83
+
className="ml-2"
84
84
+
>
85
85
+
{copiedSection === 'endpoint' ? (
86
86
+
<Check className="h-4 w-4 text-green-500" />
87
87
+
) : (
88
88
+
<Copy className="h-4 w-4" />
89
89
+
)}
90
90
+
</Button>
91
91
+
</div>
92
92
+
</div>
93
93
+
94
94
+
<div>
95
95
+
<div className="flex items-center gap-2 mb-2">
96
96
+
<Badge variant="default" className="bg-green-600 text-xs">POST</Badge>
97
97
+
<span className="text-xs font-mono text-muted-foreground">METHOD</span>
98
98
+
</div>
99
99
+
</div>
100
100
+
</CardContent>
101
101
+
</Card>
102
102
+
103
103
+
{/* Request Format */}
104
104
+
<Card className="mb-6 border border-border bg-card">
105
105
+
<CardHeader className="pb-3">
106
106
+
<div className="flex items-center gap-2">
107
107
+
<ChevronRight className="h-4 w-4 text-primary" />
108
108
+
<span className="font-mono text-sm">Request Format</span>
109
109
+
</div>
110
110
+
</CardHeader>
111
111
+
<CardContent className="space-y-4">
112
112
+
<div>
113
113
+
<div className="text-xs font-mono text-muted-foreground mb-2">HEADERS</div>
114
114
+
<div className="bg-muted/30 p-3 rounded font-mono text-sm border border-border/50">
115
115
+
<div className="text-muted-foreground">Content-Type: <span className="text-foreground">application/json</span></div>
116
116
+
</div>
117
117
+
</div>
118
118
+
119
119
+
<div>
120
120
+
<div className="flex items-center justify-between mb-2">
121
121
+
<span className="text-xs font-mono text-muted-foreground">REQUEST BODY</span>
122
122
+
<Button
123
123
+
size="sm"
124
124
+
variant="ghost"
125
125
+
onClick={() => copyToClipboard('{\n "url": "https://example.com"\n}', 'request')}
126
126
+
>
127
127
+
{copiedSection === 'request' ? (
128
128
+
<Check className="h-4 w-4 text-green-500" />
129
129
+
) : (
130
130
+
<Copy className="h-4 w-4" />
131
131
+
)}
132
132
+
</Button>
133
133
+
</div>
134
134
+
<pre className="bg-muted/30 p-4 rounded font-mono text-sm border border-border/50 overflow-x-auto">
135
135
+
{`{
136
136
+
"url": "https://example.com"
137
137
+
}`}
138
138
+
</pre>
139
139
+
</div>
140
140
+
</CardContent>
141
141
+
</Card>
142
142
+
143
143
+
{/* Response Format */}
144
144
+
<Card className="mb-6 border border-border bg-card">
145
145
+
<CardHeader className="pb-3">
146
146
+
<div className="flex items-center gap-2">
147
147
+
<ChevronRight className="h-4 w-4 text-primary" />
148
148
+
<span className="font-mono text-sm">Response Format</span>
149
149
+
</div>
150
150
+
</CardHeader>
151
151
+
<CardContent>
152
152
+
<div className="flex items-center justify-between mb-2">
153
153
+
<span className="text-xs font-mono text-muted-foreground">SUCCESS RESPONSE (200)</span>
154
154
+
<Button
155
155
+
size="sm"
156
156
+
variant="ghost"
157
157
+
onClick={() => copyToClipboard(`{
158
158
+
"success": true,
159
159
+
"data": {
160
160
+
"title": "Page Title",
161
161
+
"description": "Meta description",
162
162
+
"ogTitle": "OG Title",
163
163
+
"ogDescription": "OG Description",
164
164
+
"ogImage": "https://example.com/image.jpg",
165
165
+
"ogType": "website",
166
166
+
"twitterCard": "summary_large_image",
167
167
+
"h1": "Main Heading",
168
168
+
"canonical": "https://example.com",
169
169
+
"lang": "en",
170
170
+
"viewport": "width=device-width, initial-scale=1",
171
171
+
"charset": "UTF-8",
172
172
+
"metaRobots": "index,follow"
173
173
+
},
174
174
+
"score": {
175
175
+
"total": 85,
176
176
+
"breakdown": {
177
177
+
"basic": 35,
178
178
+
"social": 30,
179
179
+
"technical": 20
180
180
+
}
181
181
+
}
182
182
+
}`, 'response')}
183
183
+
>
184
184
+
{copiedSection === 'response' ? (
185
185
+
<Check className="h-4 w-4 text-green-500" />
186
186
+
) : (
187
187
+
<Copy className="h-4 w-4" />
188
188
+
)}
189
189
+
</Button>
190
190
+
</div>
191
191
+
<pre className="bg-muted/30 p-4 rounded font-mono text-xs border border-border/50 overflow-x-auto max-h-96">
192
192
+
{`{
193
193
+
"success": true,
194
194
+
"data": {
195
195
+
"title": "Page Title",
196
196
+
"description": "Meta description",
197
197
+
"ogTitle": "OG Title",
198
198
+
"ogDescription": "OG Description",
199
199
+
"ogImage": "https://example.com/image.jpg",
200
200
+
"ogType": "website",
201
201
+
"twitterCard": "summary_large_image",
202
202
+
"twitterTitle": "Twitter Title",
203
203
+
"twitterDescription": "Twitter Description",
204
204
+
"twitterImage": "https://example.com/image.jpg",
205
205
+
"h1": "Main Heading",
206
206
+
"canonical": "https://example.com",
207
207
+
"keywords": "keyword1, keyword2",
208
208
+
"lang": "en",
209
209
+
"viewport": "width=device-width, initial-scale=1",
210
210
+
"charset": "UTF-8",
211
211
+
"metaRobots": "index,follow",
212
212
+
"url": "https://example.com"
213
213
+
},
214
214
+
"score": {
215
215
+
"total": 85,
216
216
+
"breakdown": {
217
217
+
"basic": 35,
218
218
+
"social": 30,
219
219
+
"technical": 20
220
220
+
}
221
221
+
}
222
222
+
}`}
223
223
+
</pre>
224
224
+
</CardContent>
225
225
+
</Card>
226
226
+
227
227
+
{/* Code Examples */}
228
228
+
<Card className="mb-6 border border-border bg-card">
229
229
+
<CardHeader className="pb-3">
230
230
+
<div className="flex items-center gap-2">
231
231
+
<Code className="h-4 w-4 text-primary" />
232
232
+
<span className="font-mono text-sm">Code Examples</span>
233
233
+
</div>
234
234
+
</CardHeader>
235
235
+
<CardContent className="space-y-6">
236
236
+
{/* JavaScript/Fetch */}
237
237
+
<div>
238
238
+
<div className="flex items-center justify-between mb-2">
239
239
+
<span className="text-xs font-mono text-muted-foreground">JAVASCRIPT (FETCH)</span>
240
240
+
<Button
241
241
+
size="sm"
242
242
+
variant="ghost"
243
243
+
onClick={() => copyToClipboard(`fetch('${apiUrl}', {
244
244
+
method: 'POST',
245
245
+
headers: {
246
246
+
'Content-Type': 'application/json',
247
247
+
},
248
248
+
body: JSON.stringify({
249
249
+
url: 'https://example.com'
250
250
+
})
251
251
+
})
252
252
+
.then(response => response.json())
253
253
+
.then(data => console.log(data))
254
254
+
.catch(error => console.error('Error:', error));`, 'js-fetch')}
255
255
+
>
256
256
+
{copiedSection === 'js-fetch' ? (
257
257
+
<Check className="h-4 w-4 text-green-500" />
258
258
+
) : (
259
259
+
<Copy className="h-4 w-4" />
260
260
+
)}
261
261
+
</Button>
262
262
+
</div>
263
263
+
<pre className="bg-muted/30 p-4 rounded font-mono text-xs border border-border/50 overflow-x-auto">
264
264
+
{`fetch('${apiUrl}', {
265
265
+
method: 'POST',
266
266
+
headers: {
267
267
+
'Content-Type': 'application/json',
268
268
+
},
269
269
+
body: JSON.stringify({
270
270
+
url: 'https://example.com'
271
271
+
})
272
272
+
})
273
273
+
.then(response => response.json())
274
274
+
.then(data => console.log(data))
275
275
+
.catch(error => console.error('Error:', error));`}
276
276
+
</pre>
277
277
+
</div>
278
278
+
279
279
+
<Separator />
280
280
+
281
281
+
{/* cURL */}
282
282
+
<div>
283
283
+
<div className="flex items-center justify-between mb-2">
284
284
+
<span className="text-xs font-mono text-muted-foreground">CURL</span>
285
285
+
<Button
286
286
+
size="sm"
287
287
+
variant="ghost"
288
288
+
onClick={() => copyToClipboard(`curl -X POST '${apiUrl}' \\
289
289
+
-H 'Content-Type: application/json' \\
290
290
+
-d '{"url": "https://example.com"}'`, 'curl')}
291
291
+
>
292
292
+
{copiedSection === 'curl' ? (
293
293
+
<Check className="h-4 w-4 text-green-500" />
294
294
+
) : (
295
295
+
<Copy className="h-4 w-4" />
296
296
+
)}
297
297
+
</Button>
298
298
+
</div>
299
299
+
<pre className="bg-muted/30 p-4 rounded font-mono text-xs border border-border/50 overflow-x-auto">
300
300
+
{`curl -X POST '${apiUrl}' \\
301
301
+
-H 'Content-Type: application/json' \\
302
302
+
-d '{"url": "https://example.com"}'`}
303
303
+
</pre>
304
304
+
</div>
305
305
+
306
306
+
<Separator />
307
307
+
308
308
+
{/* Python */}
309
309
+
<div>
310
310
+
<div className="flex items-center justify-between mb-2">
311
311
+
<span className="text-xs font-mono text-muted-foreground">PYTHON</span>
312
312
+
<Button
313
313
+
size="sm"
314
314
+
variant="ghost"
315
315
+
onClick={() => copyToClipboard(`import requests
316
316
+
317
317
+
url = "${apiUrl}"
318
318
+
payload = {"url": "https://example.com"}
319
319
+
headers = {"Content-Type": "application/json"}
320
320
+
321
321
+
response = requests.post(url, json=payload, headers=headers)
322
322
+
print(response.json())`, 'python')}
323
323
+
>
324
324
+
{copiedSection === 'python' ? (
325
325
+
<Check className="h-4 w-4 text-green-500" />
326
326
+
) : (
327
327
+
<Copy className="h-4 w-4" />
328
328
+
)}
329
329
+
</Button>
330
330
+
</div>
331
331
+
<pre className="bg-muted/30 p-4 rounded font-mono text-xs border border-border/50 overflow-x-auto">
332
332
+
{`import requests
333
333
+
334
334
+
url = "${apiUrl}"
335
335
+
payload = {"url": "https://example.com"}
336
336
+
headers = {"Content-Type": "application/json"}
337
337
+
338
338
+
response = requests.post(url, json=payload, headers=headers)
339
339
+
print(response.json())`}
340
340
+
</pre>
341
341
+
</div>
342
342
+
</CardContent>
343
343
+
</Card>
344
344
+
345
345
+
{/* Error Responses */}
346
346
+
<Card className="border border-border bg-card">
347
347
+
<CardHeader className="pb-3">
348
348
+
<div className="flex items-center gap-2">
349
349
+
<Terminal className="h-4 w-4 text-destructive" />
350
350
+
<span className="font-mono text-sm">Error Responses</span>
351
351
+
</div>
352
352
+
</CardHeader>
353
353
+
<CardContent className="space-y-4">
354
354
+
<div>
355
355
+
<Badge variant="destructive" className="text-xs mb-2">400 BAD REQUEST</Badge>
356
356
+
<pre className="bg-muted/30 p-3 rounded font-mono text-xs border border-border/50">
357
357
+
{`{
358
358
+
"error": "URL parameter is required"
359
359
+
}`}
360
360
+
</pre>
361
361
+
</div>
362
362
+
363
363
+
<div>
364
364
+
<Badge variant="destructive" className="text-xs mb-2">500 INTERNAL ERROR</Badge>
365
365
+
<pre className="bg-muted/30 p-3 rounded font-mono text-xs border border-border/50">
366
366
+
{`{
367
367
+
"success": false,
368
368
+
"error": "Failed to fetch website"
369
369
+
}`}
370
370
+
</pre>
371
371
+
</div>
372
372
+
</CardContent>
373
373
+
</Card>
374
374
+
</div>
375
375
+
</div>
376
376
+
</div>
377
377
+
);
378
378
+
};
379
379
+
380
380
+
export default Docs;
+1
supabase/config.toml
···
1
1
+
project_id = "gjhfnqiknusundbktwxs"
+191
supabase/functions/analyze-seo/index.ts
···
1
1
+
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
2
2
+
3
3
+
const corsHeaders = {
4
4
+
'Access-Control-Allow-Origin': '*',
5
5
+
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
6
6
+
};
7
7
+
8
8
+
interface SEOData {
9
9
+
title?: string;
10
10
+
description?: string;
11
11
+
ogTitle?: string;
12
12
+
ogDescription?: string;
13
13
+
ogImage?: string;
14
14
+
ogType?: string;
15
15
+
twitterCard?: string;
16
16
+
twitterTitle?: string;
17
17
+
twitterDescription?: string;
18
18
+
twitterImage?: string;
19
19
+
canonical?: string;
20
20
+
keywords?: string;
21
21
+
url: string;
22
22
+
h1?: string;
23
23
+
metaRobots?: string;
24
24
+
lang?: string;
25
25
+
viewport?: string;
26
26
+
charset?: string;
27
27
+
}
28
28
+
29
29
+
interface SEOScore {
30
30
+
total: number;
31
31
+
breakdown: {
32
32
+
basic: number;
33
33
+
social: number;
34
34
+
technical: number;
35
35
+
};
36
36
+
}
37
37
+
38
38
+
const extractMetaData = (html: string, url: string): SEOData => {
39
39
+
const parser = new DOMParser();
40
40
+
const doc = parser.parseFromString(html, 'text/html');
41
41
+
42
42
+
const getMetaContent = (name: string, property?: string) => {
43
43
+
if (property) {
44
44
+
const element = doc.querySelector(`meta[property="${property}"]`);
45
45
+
return element?.getAttribute('content') || '';
46
46
+
}
47
47
+
const element = doc.querySelector(`meta[name="${name}"]`) ||
48
48
+
doc.querySelector(`meta[property="${name}"]`);
49
49
+
return element?.getAttribute('content') || '';
50
50
+
};
51
51
+
52
52
+
const title = doc.querySelector('title')?.textContent || '';
53
53
+
const canonical = doc.querySelector('link[rel="canonical"]')?.getAttribute('href') || '';
54
54
+
const h1 = doc.querySelector('h1')?.textContent || '';
55
55
+
const htmlElement = doc.querySelector('html');
56
56
+
const lang = htmlElement?.getAttribute('lang') || '';
57
57
+
58
58
+
return {
59
59
+
title,
60
60
+
description: getMetaContent('description'),
61
61
+
ogTitle: getMetaContent('', 'og:title'),
62
62
+
ogDescription: getMetaContent('', 'og:description'),
63
63
+
ogImage: getMetaContent('', 'og:image'),
64
64
+
ogType: getMetaContent('', 'og:type'),
65
65
+
twitterCard: getMetaContent('twitter:card'),
66
66
+
twitterTitle: getMetaContent('twitter:title'),
67
67
+
twitterDescription: getMetaContent('twitter:description'),
68
68
+
twitterImage: getMetaContent('twitter:image'),
69
69
+
canonical,
70
70
+
keywords: getMetaContent('keywords'),
71
71
+
h1,
72
72
+
metaRobots: getMetaContent('robots'),
73
73
+
lang,
74
74
+
viewport: getMetaContent('viewport'),
75
75
+
charset: doc.querySelector('meta[charset]')?.getAttribute('charset') || '',
76
76
+
url
77
77
+
};
78
78
+
};
79
79
+
80
80
+
const calculateSEOScore = (data: SEOData): SEOScore => {
81
81
+
let basicScore = 0;
82
82
+
let socialScore = 0;
83
83
+
let technicalScore = 0;
84
84
+
85
85
+
// Basic SEO (40 points max)
86
86
+
if (data.title) basicScore += 15;
87
87
+
if (data.description) basicScore += 15;
88
88
+
if (data.h1) basicScore += 10;
89
89
+
90
90
+
// Social Media (30 points max)
91
91
+
if (data.ogTitle || data.title) socialScore += 8;
92
92
+
if (data.ogDescription || data.description) socialScore += 8;
93
93
+
if (data.ogImage) socialScore += 14;
94
94
+
95
95
+
// Technical SEO (30 points max)
96
96
+
if (data.canonical) technicalScore += 10;
97
97
+
if (data.lang) technicalScore += 5;
98
98
+
if (data.viewport) technicalScore += 5;
99
99
+
if (data.charset) technicalScore += 5;
100
100
+
if (!data.metaRobots || !data.metaRobots.includes('noindex')) technicalScore += 5;
101
101
+
102
102
+
const total = basicScore + socialScore + technicalScore;
103
103
+
104
104
+
return {
105
105
+
total,
106
106
+
breakdown: {
107
107
+
basic: basicScore,
108
108
+
social: socialScore,
109
109
+
technical: technicalScore
110
110
+
}
111
111
+
};
112
112
+
};
113
113
+
114
114
+
serve(async (req) => {
115
115
+
// Handle CORS preflight requests
116
116
+
if (req.method === 'OPTIONS') {
117
117
+
return new Response(null, { headers: corsHeaders });
118
118
+
}
119
119
+
120
120
+
try {
121
121
+
const { url } = await req.json();
122
122
+
123
123
+
if (!url) {
124
124
+
return new Response(
125
125
+
JSON.stringify({ error: 'URL parameter is required' }),
126
126
+
{
127
127
+
status: 400,
128
128
+
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
129
129
+
}
130
130
+
);
131
131
+
}
132
132
+
133
133
+
console.log('Analyzing SEO for URL:', url);
134
134
+
135
135
+
// Validate URL
136
136
+
try {
137
137
+
new URL(url);
138
138
+
} catch {
139
139
+
return new Response(
140
140
+
JSON.stringify({ error: 'Invalid URL format' }),
141
141
+
{
142
142
+
status: 400,
143
143
+
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
144
144
+
}
145
145
+
);
146
146
+
}
147
147
+
148
148
+
// Fetch website content
149
149
+
const proxyUrl = `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`;
150
150
+
const response = await fetch(proxyUrl);
151
151
+
152
152
+
if (!response.ok) {
153
153
+
throw new Error(`Failed to fetch website: ${response.status}`);
154
154
+
}
155
155
+
156
156
+
const data = await response.json();
157
157
+
158
158
+
if (!data.contents) {
159
159
+
throw new Error('No content received from the website');
160
160
+
}
161
161
+
162
162
+
// Extract and analyze SEO data
163
163
+
const seoData = extractMetaData(data.contents, url);
164
164
+
const seoScore = calculateSEOScore(seoData);
165
165
+
166
166
+
console.log('SEO analysis completed successfully');
167
167
+
168
168
+
return new Response(
169
169
+
JSON.stringify({
170
170
+
success: true,
171
171
+
data: seoData,
172
172
+
score: seoScore,
173
173
+
}),
174
174
+
{
175
175
+
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
176
176
+
}
177
177
+
);
178
178
+
} catch (error) {
179
179
+
console.error('Error in analyze-seo function:', error);
180
180
+
return new Response(
181
181
+
JSON.stringify({
182
182
+
success: false,
183
183
+
error: error instanceof Error ? error.message : 'Internal server error',
184
184
+
}),
185
185
+
{
186
186
+
status: 500,
187
187
+
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
188
188
+
}
189
189
+
);
190
190
+
}
191
191
+
});