dynamic canonical, meta robot added
This commit is contained in:
parent
d6778250b6
commit
50f2150907
189
package-lock.json
generated
189
package-lock.json
generated
@ -10,7 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@microsoft/clarity": "^1.0.0",
|
"@microsoft/clarity": "^1.0.0",
|
||||||
"@next/font": "13.1.6",
|
"@next/font": "13.1.6",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.13.2",
|
||||||
"imagesloaded": "^5.0.0",
|
"imagesloaded": "^5.0.0",
|
||||||
"isotope-layout": "^3.0.6",
|
"isotope-layout": "^3.0.6",
|
||||||
"next": "13.1.6",
|
"next": "13.1.6",
|
||||||
@ -21,9 +21,11 @@
|
|||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-google-recaptcha": "^3.1.0",
|
"react-google-recaptcha": "^3.1.0",
|
||||||
"react-visibility-sensor": "^5.1.1",
|
"react-visibility-sensor": "^5.1.1",
|
||||||
|
"selenium-webdriver": "^4.39.0",
|
||||||
"sitemap": "^8.0.0",
|
"sitemap": "^8.0.0",
|
||||||
"swiper": "^9.0.4",
|
"swiper": "^9.0.4",
|
||||||
"wowjs": "^1.1.3"
|
"wowjs": "^1.1.3",
|
||||||
|
"xml2js": "^0.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"serve": "^14.2.0"
|
"serve": "^14.2.0"
|
||||||
@ -38,6 +40,12 @@
|
|||||||
"node": ">=6.9.0"
|
"node": ">=6.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@bazel/runfiles": {
|
||||||
|
"version": "6.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@bazel/runfiles/-/runfiles-6.5.0.tgz",
|
||||||
|
"integrity": "sha512-RzahvqTkfpY2jsDxo8YItPX+/iZ6hbiikw1YhE0bA9EKBR5Og8Pa6FHn9PO9M0zaXRVsr0GFQLKbB/0rzy9SzA==",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
},
|
||||||
"node_modules/@microsoft/clarity": {
|
"node_modules/@microsoft/clarity": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@microsoft/clarity/-/clarity-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@microsoft/clarity/-/clarity-1.0.0.tgz",
|
||||||
@ -514,9 +522,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.11.0",
|
"version": "1.13.2",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
|
||||||
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
|
"integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.6",
|
"follow-redirects": "^1.15.6",
|
||||||
@ -807,6 +815,12 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/core-util-is": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/countup.js": {
|
"node_modules/countup.js": {
|
||||||
"version": "2.8.2",
|
"version": "2.8.2",
|
||||||
"resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.8.2.tgz",
|
"resolved": "https://registry.npmjs.org/countup.js/-/countup.js-2.8.2.tgz",
|
||||||
@ -1203,6 +1217,18 @@
|
|||||||
"integrity": "sha512-jQ5Ql18hdCQ4qS+RCrbLfz1n+Pags27q5TwMKvZyhp5hh2UULUYZUy1keqj6k6SYsdqIYjnmz7xyyEY0V67B8Q==",
|
"integrity": "sha512-jQ5Ql18hdCQ4qS+RCrbLfz1n+Pags27q5TwMKvZyhp5hh2UULUYZUy1keqj6k6SYsdqIYjnmz7xyyEY0V67B8Q==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/immediate": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz",
|
||||||
|
"integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
"node_modules/ini": {
|
"node_modules/ini": {
|
||||||
"version": "1.3.8",
|
"version": "1.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
|
||||||
@ -1284,6 +1310,12 @@
|
|||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/isarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/isexe": {
|
"node_modules/isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
@ -1317,6 +1349,27 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/jszip": {
|
||||||
|
"version": "3.10.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz",
|
||||||
|
"integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==",
|
||||||
|
"license": "(MIT OR GPL-3.0-or-later)",
|
||||||
|
"dependencies": {
|
||||||
|
"lie": "~3.3.0",
|
||||||
|
"pako": "~1.0.2",
|
||||||
|
"readable-stream": "~2.3.6",
|
||||||
|
"setimmediate": "^1.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lie": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"immediate": "~3.0.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/loose-envify": {
|
"node_modules/loose-envify": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||||
@ -1565,6 +1618,12 @@
|
|||||||
"get-size": "^2.0.2"
|
"get-size": "^2.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pako": {
|
||||||
|
"version": "1.0.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
|
||||||
|
"integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
|
||||||
|
"license": "(MIT AND Zlib)"
|
||||||
|
},
|
||||||
"node_modules/path-is-inside": {
|
"node_modules/path-is-inside": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
|
||||||
@ -1619,6 +1678,12 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/process-nextick-args": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/prop-types": {
|
"node_modules/prop-types": {
|
||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
@ -1847,6 +1912,21 @@
|
|||||||
"react-dom": ">=16.0.0"
|
"react-dom": ">=16.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/readable-stream": {
|
||||||
|
"version": "2.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
|
||||||
|
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"core-util-is": "~1.0.0",
|
||||||
|
"inherits": "~2.0.3",
|
||||||
|
"isarray": "~1.0.0",
|
||||||
|
"process-nextick-args": "~2.0.0",
|
||||||
|
"safe-buffer": "~5.1.1",
|
||||||
|
"string_decoder": "~1.1.1",
|
||||||
|
"util-deprecate": "~1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/registry-auth-token": {
|
"node_modules/registry-auth-token": {
|
||||||
"version": "3.3.2",
|
"version": "3.3.2",
|
||||||
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz",
|
"resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz",
|
||||||
@ -1885,7 +1965,6 @@
|
|||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/sax": {
|
"node_modules/sax": {
|
||||||
@ -1903,6 +1982,31 @@
|
|||||||
"loose-envify": "^1.1.0"
|
"loose-envify": "^1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/selenium-webdriver": {
|
||||||
|
"version": "4.39.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.39.0.tgz",
|
||||||
|
"integrity": "sha512-NAs9jCU+UeZ/ZmRb8R6zOp7N8eMklefdBYASnaRmCNXdgFE8w3OCxxZmLixkwqnGDHY5VF7hCulfw1Mls43N/A==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/SeleniumHQ"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/selenium"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@bazel/runfiles": "^6.5.0",
|
||||||
|
"jszip": "^3.10.1",
|
||||||
|
"tmp": "^0.2.5",
|
||||||
|
"ws": "^8.18.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 20.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/serve": {
|
"node_modules/serve": {
|
||||||
"version": "14.2.4",
|
"version": "14.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/serve/-/serve-14.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/serve/-/serve-14.2.4.tgz",
|
||||||
@ -1968,6 +2072,12 @@
|
|||||||
"node": ">= 0.6"
|
"node": ">= 0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/setimmediate": {
|
||||||
|
"version": "1.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
|
||||||
|
"integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/shebang-command": {
|
"node_modules/shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
@ -2032,6 +2142,15 @@
|
|||||||
"integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==",
|
"integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/string_decoder": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/string-width": {
|
"node_modules/string-width": {
|
||||||
"version": "5.1.2",
|
"version": "5.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||||
@ -2144,6 +2263,15 @@
|
|||||||
"node": ">= 4.7.0"
|
"node": ">= 4.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tmp": {
|
||||||
|
"version": "0.2.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
|
||||||
|
"integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.14"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tslib": {
|
"node_modules/tslib": {
|
||||||
"version": "2.8.1",
|
"version": "2.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||||
@ -2199,6 +2327,12 @@
|
|||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/vary": {
|
"node_modules/vary": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||||
@ -2275,6 +2409,49 @@
|
|||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ws": {
|
||||||
|
"version": "8.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
|
||||||
|
"integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"bufferutil": "^4.0.1",
|
||||||
|
"utf-8-validate": ">=5.0.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"bufferutil": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"utf-8-validate": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xml2js": {
|
||||||
|
"version": "0.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
|
||||||
|
"integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"sax": ">=0.6.0",
|
||||||
|
"xmlbuilder": "~11.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xmlbuilder": {
|
||||||
|
"version": "11.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
|
||||||
|
"integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,12 +8,13 @@
|
|||||||
"export": "next export",
|
"export": "next export",
|
||||||
"start": "npx serve out",
|
"start": "npx serve out",
|
||||||
"sitemap": "node scripts/generate-sitemap.cjs",
|
"sitemap": "node scripts/generate-sitemap.cjs",
|
||||||
|
"seo-audit": "node scripts/seo-test-selenium.cjs",
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@microsoft/clarity": "^1.0.0",
|
"@microsoft/clarity": "^1.0.0",
|
||||||
"@next/font": "13.1.6",
|
"@next/font": "13.1.6",
|
||||||
"axios": "^1.11.0",
|
"axios": "^1.13.2",
|
||||||
"imagesloaded": "^5.0.0",
|
"imagesloaded": "^5.0.0",
|
||||||
"isotope-layout": "^3.0.6",
|
"isotope-layout": "^3.0.6",
|
||||||
"next": "13.1.6",
|
"next": "13.1.6",
|
||||||
@ -24,9 +25,11 @@
|
|||||||
"react-dom": "18.2.0",
|
"react-dom": "18.2.0",
|
||||||
"react-google-recaptcha": "^3.1.0",
|
"react-google-recaptcha": "^3.1.0",
|
||||||
"react-visibility-sensor": "^5.1.1",
|
"react-visibility-sensor": "^5.1.1",
|
||||||
|
"selenium-webdriver": "^4.39.0",
|
||||||
"sitemap": "^8.0.0",
|
"sitemap": "^8.0.0",
|
||||||
"swiper": "^9.0.4",
|
"swiper": "^9.0.4",
|
||||||
"wowjs": "^1.1.3"
|
"wowjs": "^1.1.3",
|
||||||
|
"xml2js": "^0.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"serve": "^14.2.0"
|
"serve": "^14.2.0"
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export default function Document() {
|
|||||||
<Head>
|
<Head>
|
||||||
|
|
||||||
{/* ✅ Canonical Tag */}
|
{/* ✅ Canonical Tag */}
|
||||||
<link rel="canonical" href="https://metatroncubesolutions.com/" />
|
{/* <link rel="canonical" href="https://metatroncubesolutions.com/" /> */}
|
||||||
|
|
||||||
{/* ✅ Google Tag Manager (script) */}
|
{/* ✅ Google Tag Manager (script) */}
|
||||||
<script
|
<script
|
||||||
|
|||||||
266
scripts/seo-test-selenium.cjs
Normal file
266
scripts/seo-test-selenium.cjs
Normal file
@ -0,0 +1,266 @@
|
|||||||
|
// 🚀 Full SEO + Broken Link + 404 + Accessibility + Image Alt CSV Export
|
||||||
|
// Run with: node seo_full_audit.js
|
||||||
|
|
||||||
|
const { Builder, By } = require("selenium-webdriver");
|
||||||
|
const chrome = require("selenium-webdriver/chrome");
|
||||||
|
const axios = require("axios");
|
||||||
|
const xml2js = require("xml2js");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
// CSV file for Image Alt issues
|
||||||
|
const csvPath = path.join(__dirname, "image_alt_issues.csv");
|
||||||
|
fs.writeFileSync(csvPath, "Page URL,Image Src,Alt Text,Issue Type\n", "utf8");
|
||||||
|
|
||||||
|
// ==========================
|
||||||
|
// 1️⃣ Fetch URLs from sitemap.xml
|
||||||
|
// ==========================
|
||||||
|
async function getUrlsFromSitemap(sitemapUrl) {
|
||||||
|
try {
|
||||||
|
const res = await axios.get(sitemapUrl);
|
||||||
|
const parsed = await xml2js.parseStringPromise(res.data);
|
||||||
|
return parsed.urlset.url.map((u) => u.loc[0]);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("❌ Failed to load sitemap:", err.message);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================
|
||||||
|
// 2️⃣ Check HTTP Status
|
||||||
|
// ==========================
|
||||||
|
async function checkLinkStatus(url) {
|
||||||
|
try {
|
||||||
|
const res = await axios.get(url, {
|
||||||
|
timeout: 10000,
|
||||||
|
validateStatus: () => true,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (
|
||||||
|
res.status === 200 &&
|
||||||
|
(
|
||||||
|
/404/i.test(res.data.match(/<title[^>]*>(.*?)<\/title>/)?.[1] ?? "")
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return "Soft 404";
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.status;
|
||||||
|
} catch (err) {
|
||||||
|
return err.response ? err.response.status : "❌ No Response";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================
|
||||||
|
// 3️⃣ Main SEO + Accessibility + Image Alt Audit
|
||||||
|
// ==========================
|
||||||
|
async function checkSEO(url, siteDomain) {
|
||||||
|
const options = new chrome.Options();
|
||||||
|
options.addArguments("--headless", "--no-sandbox", "--disable-gpu");
|
||||||
|
|
||||||
|
const driver = await new Builder()
|
||||||
|
.forBrowser("chrome")
|
||||||
|
.setChromeOptions(options)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const pageStatus = await checkLinkStatus(url);
|
||||||
|
if (pageStatus === 404 || pageStatus === "Soft 404") {
|
||||||
|
console.log(`\n🚫 ${url} → ❌ Page not found (${pageStatus})`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await driver.get(url);
|
||||||
|
const pageSource = await driver.getPageSource();
|
||||||
|
|
||||||
|
// Basic SEO Elements
|
||||||
|
const title = await driver.getTitle();
|
||||||
|
const descElem = await driver.findElements(By.css('meta[name="description"]'));
|
||||||
|
const canonicalElem = await driver.findElements(By.css('link[rel="canonical"]'));
|
||||||
|
const robotsElem = await driver.findElements(By.css('meta[name="robots"]'));
|
||||||
|
const viewportElem = await driver.findElements(By.css('meta[name="viewport"]'));
|
||||||
|
const charset = await driver.findElements(By.css('meta[charset]'));
|
||||||
|
const htmlTag = await driver.findElement(By.css("html"));
|
||||||
|
const langAttr = await htmlTag.getAttribute("lang").catch(() => "");
|
||||||
|
const h1Tags = await driver.findElements(By.css("h1"));
|
||||||
|
const h2Tags = await driver.findElements(By.css("h2"));
|
||||||
|
|
||||||
|
// Meta Description
|
||||||
|
let descContent = descElem.length > 0 ? await descElem[0].getAttribute("content") : "";
|
||||||
|
const descLength = descContent.length;
|
||||||
|
const descStatus =
|
||||||
|
descLength === 0
|
||||||
|
? "❌ Missing"
|
||||||
|
: descLength < 50
|
||||||
|
? `⚠️ Too short (${descLength})`
|
||||||
|
: descLength > 160
|
||||||
|
? `⚠️ Too long (${descLength})`
|
||||||
|
: "✅ Perfect";
|
||||||
|
|
||||||
|
// Title length check
|
||||||
|
const titleLength = title.length;
|
||||||
|
const titleStatus =
|
||||||
|
titleLength === 0
|
||||||
|
? "❌ Missing"
|
||||||
|
: titleLength < 30
|
||||||
|
? `⚠️ Too short (${titleLength})`
|
||||||
|
: titleLength > 65
|
||||||
|
? `⚠️ Too long (${titleLength})`
|
||||||
|
: "✅ Perfect";
|
||||||
|
|
||||||
|
// Canonical
|
||||||
|
const canonicalURL =
|
||||||
|
canonicalElem.length > 0 ? await canonicalElem[0].getAttribute("href") : "❌ Missing";
|
||||||
|
|
||||||
|
// 🖼️ Image Accessibility Audit
|
||||||
|
const imgs = await driver.findElements(By.css("img"));
|
||||||
|
let missingAlt = 0;
|
||||||
|
let emptyAlt = 0;
|
||||||
|
let duplicateAlt = [];
|
||||||
|
const altTextMap = new Map();
|
||||||
|
|
||||||
|
for (const img of imgs) {
|
||||||
|
const src = await img.getAttribute("src");
|
||||||
|
const alt = (await img.getAttribute("alt"))?.trim() ?? null;
|
||||||
|
|
||||||
|
if (alt === null) {
|
||||||
|
missingAlt++;
|
||||||
|
fs.appendFileSync(csvPath, `"${url}","${src}","","Missing Alt"\n`, "utf8");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (alt === "") {
|
||||||
|
emptyAlt++;
|
||||||
|
fs.appendFileSync(csvPath, `"${url}","${src}","(empty)","Empty Alt"\n`, "utf8");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (altTextMap.has(alt)) {
|
||||||
|
altTextMap.set(alt, altTextMap.get(alt) + 1);
|
||||||
|
} else {
|
||||||
|
altTextMap.set(alt, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [altText, count] of altTextMap.entries()) {
|
||||||
|
if (altText && count > 1) {
|
||||||
|
duplicateAlt.push({ altText, count });
|
||||||
|
fs.appendFileSync(
|
||||||
|
csvPath,
|
||||||
|
`"${url}","","${altText}","Duplicate Alt (${count} times)"\n`,
|
||||||
|
"utf8"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect tracking & schema tags
|
||||||
|
const hasGTM = pageSource.includes("googletagmanager.com/gtm.js");
|
||||||
|
const hasClarity = pageSource.includes("clarity.ms/tag");
|
||||||
|
const hasFBPixel = pageSource.includes("fbevents.js") || pageSource.includes("fbq(");
|
||||||
|
const hasAnalytics = pageSource.includes("www.googletagmanager.com/gtag/js");
|
||||||
|
|
||||||
|
const ogTags = await driver.findElements(By.css("meta[property^='og:']"));
|
||||||
|
const twitterTags = await driver.findElements(By.css("meta[name^='twitter:']"));
|
||||||
|
const schemaScripts = await driver.findElements(By.css('script[type="application/ld+json"]'));
|
||||||
|
|
||||||
|
// Links check
|
||||||
|
const anchorTags = await driver.findElements(By.css("a[href]"));
|
||||||
|
const brokenLinks = [];
|
||||||
|
for (const a of anchorTags) {
|
||||||
|
const href = await a.getAttribute("href");
|
||||||
|
if (!href || href.startsWith("#") || href.startsWith("mailto:")) continue;
|
||||||
|
|
||||||
|
const fullUrl = href.startsWith("http")
|
||||||
|
? href
|
||||||
|
: `${siteDomain}${href.startsWith("/") ? href : `/${href}`}`;
|
||||||
|
|
||||||
|
if (fullUrl.includes(siteDomain)) {
|
||||||
|
const status = await checkLinkStatus(fullUrl);
|
||||||
|
if (status === 404 || status === "Soft 404" || status === "❌ No Response") {
|
||||||
|
brokenLinks.push({ link: fullUrl, status });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lazy loading check
|
||||||
|
const images = await driver.findElements(By.css("img, video, iframe"));
|
||||||
|
const lazyLoadCount = await Promise.all(
|
||||||
|
images.map(async (img) => {
|
||||||
|
const loading = await img.getAttribute("loading");
|
||||||
|
return loading === "lazy";
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const lazyLoaded = lazyLoadCount.filter((v) => v).length;
|
||||||
|
|
||||||
|
// Console Summary
|
||||||
|
console.log(`\n🔍 Checking: ${url}`);
|
||||||
|
console.log("-------------------------------------------");
|
||||||
|
console.log("Title:", titleStatus);
|
||||||
|
console.log("Meta Description:", descStatus);
|
||||||
|
console.log("Canonical URL:", canonicalURL);
|
||||||
|
console.log("Meta Robots:", robotsElem.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||||
|
console.log("Viewport:", viewportElem.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||||
|
console.log("Charset:", charset.length > 0 ? "✅ Found" : "❌ Missing");
|
||||||
|
console.log("HTML lang:", langAttr ? `✅ ${langAttr}` : "⚠️ Missing");
|
||||||
|
console.log("H1 Tags:", h1Tags.length > 0 ? `✅ ${h1Tags.length}` : "❌ Missing");
|
||||||
|
console.log("H2 Tags:", h2Tags.length > 0 ? `ℹ️ ${h2Tags.length}` : "⚠️ None");
|
||||||
|
console.log("Images:", imgs.length);
|
||||||
|
console.log(
|
||||||
|
"Missing Alt:",
|
||||||
|
missingAlt > 0 ? `❌ ${missingAlt}` : "✅ None"
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"Empty Alt:",
|
||||||
|
emptyAlt > 0 ? `⚠️ ${emptyAlt}` : "✅ None"
|
||||||
|
);
|
||||||
|
console.log(
|
||||||
|
"Duplicate Alt:",
|
||||||
|
duplicateAlt.length > 0 ? `⚠️ ${duplicateAlt.length}` : "✅ None"
|
||||||
|
);
|
||||||
|
console.log("Lazy Loaded Images:", lazyLoaded > 0 ? `✅ ${lazyLoaded}` : "⚠️ None");
|
||||||
|
console.log("Open Graph Tags:", ogTags.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||||
|
console.log("Twitter Tags:", twitterTags.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||||
|
console.log("Schema Markup:", schemaScripts.length > 0 ? "✅ Found" : "⚠️ Missing");
|
||||||
|
console.log("Google Analytics:", hasAnalytics ? "✅ Found" : "⚠️ Missing");
|
||||||
|
console.log("GTM:", hasGTM ? "✅ Found" : "⚠️ Missing");
|
||||||
|
console.log("Clarity:", hasClarity ? "✅ Found" : "⚠️ Missing");
|
||||||
|
console.log("Facebook Pixel:", hasFBPixel ? "✅ Found" : "⚠️ Missing");
|
||||||
|
|
||||||
|
if (brokenLinks.length > 0) {
|
||||||
|
console.log("\n❌ Broken Links:");
|
||||||
|
brokenLinks.forEach((b) => console.log(` → ${b.link} [${b.status}]`));
|
||||||
|
} else {
|
||||||
|
console.log("✅ No broken links found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`❌ Error on ${url}:`, err.message);
|
||||||
|
} finally {
|
||||||
|
await driver.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================
|
||||||
|
// 4️⃣ Run Full Site Audit
|
||||||
|
// ==========================
|
||||||
|
(async () => {
|
||||||
|
const sitemapUrl = "http://localhost:3000/sitemap.xml";
|
||||||
|
const siteDomain = "http://localhost:3000";
|
||||||
|
|
||||||
|
console.log("📄 Fetching URLs from sitemap...");
|
||||||
|
const urls = await getUrlsFromSitemap(sitemapUrl);
|
||||||
|
|
||||||
|
if (urls.length === 0) {
|
||||||
|
console.error("❌ No URLs found in sitemap.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`✅ Found ${urls.length} URLs in sitemap.`);
|
||||||
|
console.log("🚀 Starting Full SEO + Accessibility + Broken Link Audit...");
|
||||||
|
|
||||||
|
for (const url of urls) {
|
||||||
|
await checkSEO(url, siteDomain);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\n✅ Full SEO Audit Completed!");
|
||||||
|
console.log(` CSV Report: ${csvPath}`);
|
||||||
|
})();
|
||||||
@ -1,27 +1,39 @@
|
|||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
|
import { useRouter } from "next/router";
|
||||||
|
|
||||||
const ConsenHead = ({ title, description }) => {
|
const ConsenHead = ({ title, description }) => {
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const siteUrl = "https://metatroncubesolutions.com";
|
||||||
|
const cleanPath = router.asPath.split("?")[0];
|
||||||
|
const canonicalUrl = `${siteUrl}${cleanPath === "/" ? "" : cleanPath}`;
|
||||||
|
|
||||||
const defaultTitle = "Metatroncube: Leaders in Web & Mobile Dev, SEO, Digital Marketing";
|
const defaultTitle = "Metatroncube: Leaders in Web & Mobile Dev, SEO, Digital Marketing";
|
||||||
const defaultDescription =
|
const defaultDescription =
|
||||||
"Metatroncube Software Solutions: Your go-to agency for cutting-edge web & app development, SEO, digital marketing, and graphic design services";
|
"Metatroncube Software Solutions: Your go-to agency for cutting-edge web & app development, SEO, digital marketing, and graphic design services";
|
||||||
|
|
||||||
console.log("title", title)
|
// console.log("title", title)
|
||||||
console.log("description", description)
|
// console.log("description", description)
|
||||||
return (
|
return (
|
||||||
<Head>
|
<Head>
|
||||||
|
|
||||||
{/* Google Tag Manager */}
|
{/* Google Tag Manager */}
|
||||||
|
|
||||||
{/* <script dangerouslySetInnerHTML={{ __html: ` (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
{/* <script dangerouslySetInnerHTML={{ __html: ` (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||||
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||||
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||||
})(window,document,'script','dataLayer','GTM-N29NTKG9');`, }}/> */}
|
})(window,document,'script','dataLayer','GTM-N29NTKG9');`, }}/> */}
|
||||||
|
|
||||||
{/* End Google Tag Manager */}
|
{/* End Google Tag Manager */}
|
||||||
<meta charSet="UTF-8" />
|
<meta charSet="UTF-8" />
|
||||||
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
|
<meta httpEquiv="x-ua-compatible" content="ie=edge" />
|
||||||
<title>{title || defaultTitle}</title>
|
<title>{title || defaultTitle}</title>
|
||||||
<meta name="description" content={description || defaultDescription} />
|
<meta name="description" content={description || defaultDescription} />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
<link rel="canonical" href={canonicalUrl} />
|
||||||
|
|
||||||
{/* Favicon */}
|
{/* Favicon */}
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user