devskill 2.0.6 → 2.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1437) hide show
  1. package/meta.ts +13 -1
  2. package/package.json +1 -1
  3. package/scripts/cli.ts +55 -10
  4. package/skills/add-educational-comments/LICENSE.md +21 -0
  5. package/skills/add-educational-comments/SKILL.md +128 -0
  6. package/skills/add-educational-comments/SYNC.md +5 -0
  7. package/skills/agent-governance/LICENSE.md +21 -0
  8. package/skills/agent-governance/SKILL.md +569 -0
  9. package/skills/agent-governance/SYNC.md +5 -0
  10. package/skills/agentic-eval/LICENSE.md +21 -0
  11. package/skills/agentic-eval/SKILL.md +189 -0
  12. package/skills/agentic-eval/SYNC.md +5 -0
  13. package/skills/ai-prompt-engineering-safety-review/LICENSE.md +21 -0
  14. package/skills/ai-prompt-engineering-safety-review/SKILL.md +230 -0
  15. package/skills/ai-prompt-engineering-safety-review/SYNC.md +5 -0
  16. package/skills/algorithmic-art/LICENSE.txt +202 -0
  17. package/skills/algorithmic-art/SKILL.md +405 -0
  18. package/skills/algorithmic-art/SYNC.md +5 -0
  19. package/skills/algorithmic-art/templates/generator_template.js +223 -0
  20. package/skills/algorithmic-art/templates/viewer.html +599 -0
  21. package/skills/appinsights-instrumentation/LICENSE.md +21 -0
  22. package/skills/appinsights-instrumentation/LICENSE.txt +21 -0
  23. package/skills/appinsights-instrumentation/SKILL.md +48 -0
  24. package/skills/appinsights-instrumentation/SYNC.md +5 -0
  25. package/skills/appinsights-instrumentation/examples/appinsights.bicep +30 -0
  26. package/skills/appinsights-instrumentation/references/ASPNETCORE.md +29 -0
  27. package/skills/appinsights-instrumentation/references/AUTO.md +13 -0
  28. package/skills/appinsights-instrumentation/references/NODEJS.md +28 -0
  29. package/skills/appinsights-instrumentation/references/PYTHON.md +48 -0
  30. package/skills/appinsights-instrumentation/scripts/appinsights.ps1 +20 -0
  31. package/skills/apple-appstore-reviewer/LICENSE.md +21 -0
  32. package/skills/apple-appstore-reviewer/SKILL.md +305 -0
  33. package/skills/apple-appstore-reviewer/SYNC.md +5 -0
  34. package/skills/arch-linux-triage/LICENSE.md +21 -0
  35. package/skills/arch-linux-triage/SKILL.md +31 -0
  36. package/skills/arch-linux-triage/SYNC.md +5 -0
  37. package/skills/architecture-blueprint-generator/LICENSE.md +21 -0
  38. package/skills/architecture-blueprint-generator/SKILL.md +322 -0
  39. package/skills/architecture-blueprint-generator/SYNC.md +5 -0
  40. package/skills/aspire/LICENSE.md +21 -0
  41. package/skills/aspire/SKILL.md +231 -0
  42. package/skills/aspire/SYNC.md +5 -0
  43. package/skills/aspire/references/architecture.md +341 -0
  44. package/skills/aspire/references/cli-reference.md +307 -0
  45. package/skills/aspire/references/dashboard.md +226 -0
  46. package/skills/aspire/references/deployment.md +237 -0
  47. package/skills/aspire/references/integrations-catalog.md +68 -0
  48. package/skills/aspire/references/mcp-server.md +195 -0
  49. package/skills/aspire/references/polyglot-apis.md +296 -0
  50. package/skills/aspire/references/testing.md +281 -0
  51. package/skills/aspire/references/troubleshooting.md +194 -0
  52. package/skills/aspnet-minimal-api-openapi/LICENSE.md +21 -0
  53. package/skills/aspnet-minimal-api-openapi/SKILL.md +41 -0
  54. package/skills/aspnet-minimal-api-openapi/SYNC.md +5 -0
  55. package/skills/automate-this/LICENSE.md +21 -0
  56. package/skills/automate-this/SKILL.md +244 -0
  57. package/skills/automate-this/SYNC.md +5 -0
  58. package/skills/autoresearch/LICENSE.md +21 -0
  59. package/skills/autoresearch/SKILL.md +275 -0
  60. package/skills/autoresearch/SYNC.md +5 -0
  61. package/skills/aws-cdk-python-setup/LICENSE.md +21 -0
  62. package/skills/aws-cdk-python-setup/SKILL.md +111 -0
  63. package/skills/aws-cdk-python-setup/SYNC.md +5 -0
  64. package/skills/az-cost-optimize/LICENSE.md +21 -0
  65. package/skills/az-cost-optimize/SKILL.md +305 -0
  66. package/skills/az-cost-optimize/SYNC.md +5 -0
  67. package/skills/azure-deployment-preflight/LICENSE.md +21 -0
  68. package/skills/azure-deployment-preflight/SKILL.md +216 -0
  69. package/skills/azure-deployment-preflight/SYNC.md +5 -0
  70. package/skills/azure-deployment-preflight/references/ERROR-HANDLING.md +392 -0
  71. package/skills/azure-deployment-preflight/references/REPORT-TEMPLATE.md +352 -0
  72. package/skills/azure-deployment-preflight/references/VALIDATION-COMMANDS.md +379 -0
  73. package/skills/azure-devops-cli/LICENSE.md +21 -0
  74. package/skills/azure-devops-cli/SKILL.md +94 -0
  75. package/skills/azure-devops-cli/SYNC.md +5 -0
  76. package/skills/azure-devops-cli/references/advanced-usage.md +197 -0
  77. package/skills/azure-devops-cli/references/boards-and-iterations.md +258 -0
  78. package/skills/azure-devops-cli/references/org-and-security.md +469 -0
  79. package/skills/azure-devops-cli/references/pipelines-and-builds.md +245 -0
  80. package/skills/azure-devops-cli/references/repos-and-prs.md +333 -0
  81. package/skills/azure-devops-cli/references/variables-and-agents.md +212 -0
  82. package/skills/azure-devops-cli/references/workflows-and-patterns.md +668 -0
  83. package/skills/azure-pricing/LICENSE.md +21 -0
  84. package/skills/azure-pricing/SKILL.md +189 -0
  85. package/skills/azure-pricing/SYNC.md +5 -0
  86. package/skills/azure-pricing/references/COPILOT-STUDIO-RATES.md +135 -0
  87. package/skills/azure-pricing/references/COST-ESTIMATOR.md +142 -0
  88. package/skills/azure-pricing/references/REGIONS.md +84 -0
  89. package/skills/azure-pricing/references/SERVICE-NAMES.md +106 -0
  90. package/skills/azure-resource-health-diagnose/LICENSE.md +21 -0
  91. package/skills/azure-resource-health-diagnose/SKILL.md +290 -0
  92. package/skills/azure-resource-health-diagnose/SYNC.md +5 -0
  93. package/skills/azure-resource-visualizer/LICENSE.md +21 -0
  94. package/skills/azure-resource-visualizer/LICENSE.txt +21 -0
  95. package/skills/azure-resource-visualizer/SKILL.md +233 -0
  96. package/skills/azure-resource-visualizer/SYNC.md +5 -0
  97. package/skills/azure-resource-visualizer/assets/template-architecture.md +41 -0
  98. package/skills/azure-role-selector/LICENSE.md +21 -0
  99. package/skills/azure-role-selector/LICENSE.txt +21 -0
  100. package/skills/azure-role-selector/SKILL.md +6 -0
  101. package/skills/azure-role-selector/SYNC.md +5 -0
  102. package/skills/azure-static-web-apps/LICENSE.md +21 -0
  103. package/skills/azure-static-web-apps/SKILL.md +315 -0
  104. package/skills/azure-static-web-apps/SYNC.md +5 -0
  105. package/skills/bigquery-pipeline-audit/LICENSE.md +21 -0
  106. package/skills/bigquery-pipeline-audit/SKILL.md +129 -0
  107. package/skills/bigquery-pipeline-audit/SYNC.md +5 -0
  108. package/skills/boost-prompt/LICENSE.md +21 -0
  109. package/skills/boost-prompt/SKILL.md +25 -0
  110. package/skills/boost-prompt/SYNC.md +5 -0
  111. package/skills/brand-guidelines/LICENSE.txt +202 -0
  112. package/skills/brand-guidelines/SKILL.md +73 -0
  113. package/skills/brand-guidelines/SYNC.md +5 -0
  114. package/skills/breakdown-epic-arch/LICENSE.md +21 -0
  115. package/skills/breakdown-epic-arch/SKILL.md +66 -0
  116. package/skills/breakdown-epic-arch/SYNC.md +5 -0
  117. package/skills/breakdown-epic-pm/LICENSE.md +21 -0
  118. package/skills/breakdown-epic-pm/SKILL.md +58 -0
  119. package/skills/breakdown-epic-pm/SYNC.md +5 -0
  120. package/skills/breakdown-feature-implementation/LICENSE.md +21 -0
  121. package/skills/breakdown-feature-implementation/SKILL.md +128 -0
  122. package/skills/breakdown-feature-implementation/SYNC.md +5 -0
  123. package/skills/breakdown-feature-prd/LICENSE.md +21 -0
  124. package/skills/breakdown-feature-prd/SKILL.md +61 -0
  125. package/skills/breakdown-feature-prd/SYNC.md +5 -0
  126. package/skills/breakdown-plan/LICENSE.md +21 -0
  127. package/skills/breakdown-plan/SKILL.md +509 -0
  128. package/skills/breakdown-plan/SYNC.md +5 -0
  129. package/skills/breakdown-test/LICENSE.md +21 -0
  130. package/skills/breakdown-test/SKILL.md +365 -0
  131. package/skills/breakdown-test/SYNC.md +5 -0
  132. package/skills/canvas-design/LICENSE.txt +202 -0
  133. package/skills/canvas-design/SKILL.md +130 -0
  134. package/skills/canvas-design/SYNC.md +5 -0
  135. package/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  136. package/skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  137. package/skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  138. package/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
  139. package/skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  140. package/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
  141. package/skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
  142. package/skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  143. package/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  144. package/skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  145. package/skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  146. package/skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  147. package/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  148. package/skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  149. package/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
  150. package/skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
  151. package/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
  152. package/skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
  153. package/skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
  154. package/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
  155. package/skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
  156. package/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
  157. package/skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
  158. package/skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  159. package/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  160. package/skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  161. package/skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  162. package/skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  163. package/skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  164. package/skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  165. package/skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  166. package/skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  167. package/skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  168. package/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  169. package/skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  170. package/skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  171. package/skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  172. package/skills/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
  173. package/skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
  174. package/skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  175. package/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  176. package/skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  177. package/skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
  178. package/skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
  179. package/skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
  180. package/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  181. package/skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  182. package/skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
  183. package/skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  184. package/skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
  185. package/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
  186. package/skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
  187. package/skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
  188. package/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
  189. package/skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
  190. package/skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  191. package/skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  192. package/skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
  193. package/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
  194. package/skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
  195. package/skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  196. package/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
  197. package/skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
  198. package/skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  199. package/skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  200. package/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
  201. package/skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  202. package/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
  203. package/skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  204. package/skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  205. package/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
  206. package/skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
  207. package/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
  208. package/skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
  209. package/skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
  210. package/skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  211. package/skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
  212. package/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
  213. package/skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
  214. package/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
  215. package/skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  216. package/skills/centos-linux-triage/LICENSE.md +21 -0
  217. package/skills/centos-linux-triage/SKILL.md +31 -0
  218. package/skills/centos-linux-triage/SYNC.md +5 -0
  219. package/skills/chrome-devtools/LICENSE.md +21 -0
  220. package/skills/chrome-devtools/SKILL.md +97 -0
  221. package/skills/chrome-devtools/SYNC.md +5 -0
  222. package/skills/claude-api/LICENSE.txt +202 -0
  223. package/skills/claude-api/SKILL.md +246 -0
  224. package/skills/claude-api/SYNC.md +5 -0
  225. package/skills/claude-api/csharp/claude-api.md +400 -0
  226. package/skills/claude-api/curl/examples.md +193 -0
  227. package/skills/claude-api/go/claude-api.md +404 -0
  228. package/skills/claude-api/java/claude-api.md +430 -0
  229. package/skills/claude-api/php/claude-api.md +241 -0
  230. package/skills/claude-api/python/agent-sdk/README.md +345 -0
  231. package/skills/claude-api/python/agent-sdk/patterns.md +359 -0
  232. package/skills/claude-api/python/claude-api/README.md +410 -0
  233. package/skills/claude-api/python/claude-api/batches.md +185 -0
  234. package/skills/claude-api/python/claude-api/files-api.md +165 -0
  235. package/skills/claude-api/python/claude-api/streaming.md +162 -0
  236. package/skills/claude-api/python/claude-api/tool-use.md +590 -0
  237. package/skills/claude-api/ruby/claude-api.md +92 -0
  238. package/skills/claude-api/shared/error-codes.md +206 -0
  239. package/skills/claude-api/shared/live-sources.md +121 -0
  240. package/skills/claude-api/shared/models.md +119 -0
  241. package/skills/claude-api/shared/tool-use-concepts.md +305 -0
  242. package/skills/claude-api/typescript/agent-sdk/README.md +296 -0
  243. package/skills/claude-api/typescript/agent-sdk/patterns.md +209 -0
  244. package/skills/claude-api/typescript/claude-api/README.md +321 -0
  245. package/skills/claude-api/typescript/claude-api/batches.md +106 -0
  246. package/skills/claude-api/typescript/claude-api/files-api.md +98 -0
  247. package/skills/claude-api/typescript/claude-api/streaming.md +178 -0
  248. package/skills/claude-api/typescript/claude-api/tool-use.md +527 -0
  249. package/skills/cli-mastery/LICENSE.md +21 -0
  250. package/skills/cli-mastery/SKILL.md +43 -0
  251. package/skills/cli-mastery/SYNC.md +5 -0
  252. package/skills/cli-mastery/references/final-exam.md +24 -0
  253. package/skills/cli-mastery/references/module-1-slash-commands.md +88 -0
  254. package/skills/cli-mastery/references/module-2-keyboard-shortcuts.md +38 -0
  255. package/skills/cli-mastery/references/module-3-modes.md +33 -0
  256. package/skills/cli-mastery/references/module-4-agents.md +42 -0
  257. package/skills/cli-mastery/references/module-5-skills.md +33 -0
  258. package/skills/cli-mastery/references/module-6-mcp.md +50 -0
  259. package/skills/cli-mastery/references/module-7-advanced.md +38 -0
  260. package/skills/cli-mastery/references/module-8-configuration.md +34 -0
  261. package/skills/cli-mastery/references/scenarios.md +44 -0
  262. package/skills/cloud-design-patterns/LICENSE.md +21 -0
  263. package/skills/cloud-design-patterns/SKILL.md +62 -0
  264. package/skills/cloud-design-patterns/SYNC.md +5 -0
  265. package/skills/cloud-design-patterns/references/architecture-design.md +127 -0
  266. package/skills/cloud-design-patterns/references/azure-service-mappings.md +13 -0
  267. package/skills/cloud-design-patterns/references/best-practices.md +34 -0
  268. package/skills/cloud-design-patterns/references/deployment-operational.md +91 -0
  269. package/skills/cloud-design-patterns/references/event-driven.md +21 -0
  270. package/skills/cloud-design-patterns/references/messaging-integration.md +127 -0
  271. package/skills/cloud-design-patterns/references/performance.md +180 -0
  272. package/skills/cloud-design-patterns/references/reliability-resilience.md +156 -0
  273. package/skills/cloud-design-patterns/references/security.md +55 -0
  274. package/skills/code-exemplars-blueprint-generator/LICENSE.md +21 -0
  275. package/skills/code-exemplars-blueprint-generator/SKILL.md +126 -0
  276. package/skills/code-exemplars-blueprint-generator/SYNC.md +5 -0
  277. package/skills/codeql/LICENSE.md +21 -0
  278. package/skills/codeql/SKILL.md +405 -0
  279. package/skills/codeql/SYNC.md +5 -0
  280. package/skills/codeql/references/alert-management.md +170 -0
  281. package/skills/codeql/references/cli-commands.md +283 -0
  282. package/skills/codeql/references/compiled-languages.md +284 -0
  283. package/skills/codeql/references/sarif-output.md +265 -0
  284. package/skills/codeql/references/troubleshooting.md +259 -0
  285. package/skills/codeql/references/workflow-configuration.md +398 -0
  286. package/skills/comment-code-generate-a-tutorial/LICENSE.md +21 -0
  287. package/skills/comment-code-generate-a-tutorial/SKILL.md +26 -0
  288. package/skills/comment-code-generate-a-tutorial/SYNC.md +5 -0
  289. package/skills/containerize-aspnet-framework/LICENSE.md +21 -0
  290. package/skills/containerize-aspnet-framework/SKILL.md +454 -0
  291. package/skills/containerize-aspnet-framework/SYNC.md +5 -0
  292. package/skills/containerize-aspnetcore/LICENSE.md +21 -0
  293. package/skills/containerize-aspnetcore/SKILL.md +392 -0
  294. package/skills/containerize-aspnetcore/SYNC.md +5 -0
  295. package/skills/context-map/LICENSE.md +21 -0
  296. package/skills/context-map/SKILL.md +52 -0
  297. package/skills/context-map/SYNC.md +5 -0
  298. package/skills/conventional-commit/LICENSE.md +21 -0
  299. package/skills/conventional-commit/SKILL.md +72 -0
  300. package/skills/conventional-commit/SYNC.md +5 -0
  301. package/skills/convert-plaintext-to-md/LICENSE.md +21 -0
  302. package/skills/convert-plaintext-to-md/SKILL.md +362 -0
  303. package/skills/convert-plaintext-to-md/SYNC.md +5 -0
  304. package/skills/copilot-cli-quickstart/LICENSE.md +21 -0
  305. package/skills/copilot-cli-quickstart/SKILL.md +774 -0
  306. package/skills/copilot-cli-quickstart/SYNC.md +5 -0
  307. package/skills/copilot-instructions-blueprint-generator/LICENSE.md +21 -0
  308. package/skills/copilot-instructions-blueprint-generator/SKILL.md +294 -0
  309. package/skills/copilot-instructions-blueprint-generator/SYNC.md +5 -0
  310. package/skills/copilot-sdk/LICENSE.md +21 -0
  311. package/skills/copilot-sdk/SKILL.md +914 -0
  312. package/skills/copilot-sdk/SYNC.md +5 -0
  313. package/skills/copilot-spaces/LICENSE.md +21 -0
  314. package/skills/copilot-spaces/SKILL.md +205 -0
  315. package/skills/copilot-spaces/SYNC.md +5 -0
  316. package/skills/copilot-usage-metrics/LICENSE.md +21 -0
  317. package/skills/copilot-usage-metrics/SKILL.md +52 -0
  318. package/skills/copilot-usage-metrics/SYNC.md +5 -0
  319. package/skills/copilot-usage-metrics/get-enterprise-metrics.sh +22 -0
  320. package/skills/copilot-usage-metrics/get-enterprise-user-metrics.sh +22 -0
  321. package/skills/copilot-usage-metrics/get-org-metrics.sh +22 -0
  322. package/skills/copilot-usage-metrics/get-org-user-metrics.sh +22 -0
  323. package/skills/cosmosdb-datamodeling/LICENSE.md +21 -0
  324. package/skills/cosmosdb-datamodeling/SKILL.md +1045 -0
  325. package/skills/cosmosdb-datamodeling/SYNC.md +5 -0
  326. package/skills/create-agentsmd/LICENSE.md +21 -0
  327. package/skills/create-agentsmd/SKILL.md +249 -0
  328. package/skills/create-agentsmd/SYNC.md +5 -0
  329. package/skills/create-architectural-decision-record/LICENSE.md +21 -0
  330. package/skills/create-architectural-decision-record/SKILL.md +97 -0
  331. package/skills/create-architectural-decision-record/SYNC.md +5 -0
  332. package/skills/create-github-action-workflow-specification/LICENSE.md +21 -0
  333. package/skills/create-github-action-workflow-specification/SKILL.md +276 -0
  334. package/skills/create-github-action-workflow-specification/SYNC.md +5 -0
  335. package/skills/create-github-issue-feature-from-specification/LICENSE.md +21 -0
  336. package/skills/create-github-issue-feature-from-specification/SKILL.md +28 -0
  337. package/skills/create-github-issue-feature-from-specification/SYNC.md +5 -0
  338. package/skills/create-github-issues-feature-from-implementation-plan/LICENSE.md +21 -0
  339. package/skills/create-github-issues-feature-from-implementation-plan/SKILL.md +28 -0
  340. package/skills/create-github-issues-feature-from-implementation-plan/SYNC.md +5 -0
  341. package/skills/create-github-issues-for-unmet-specification-requirements/LICENSE.md +21 -0
  342. package/skills/create-github-issues-for-unmet-specification-requirements/SKILL.md +35 -0
  343. package/skills/create-github-issues-for-unmet-specification-requirements/SYNC.md +5 -0
  344. package/skills/create-github-pull-request-from-specification/LICENSE.md +21 -0
  345. package/skills/create-github-pull-request-from-specification/SKILL.md +24 -0
  346. package/skills/create-github-pull-request-from-specification/SYNC.md +5 -0
  347. package/skills/create-implementation-plan/LICENSE.md +21 -0
  348. package/skills/create-implementation-plan/SKILL.md +157 -0
  349. package/skills/create-implementation-plan/SYNC.md +5 -0
  350. package/skills/create-llms/LICENSE.md +21 -0
  351. package/skills/create-llms/SKILL.md +210 -0
  352. package/skills/create-llms/SYNC.md +5 -0
  353. package/skills/create-readme/LICENSE.md +21 -0
  354. package/skills/create-readme/SKILL.md +21 -0
  355. package/skills/create-readme/SYNC.md +5 -0
  356. package/skills/create-specification/LICENSE.md +21 -0
  357. package/skills/create-specification/SKILL.md +127 -0
  358. package/skills/create-specification/SYNC.md +5 -0
  359. package/skills/create-spring-boot-java-project/LICENSE.md +21 -0
  360. package/skills/create-spring-boot-java-project/SKILL.md +163 -0
  361. package/skills/create-spring-boot-java-project/SYNC.md +5 -0
  362. package/skills/create-spring-boot-kotlin-project/LICENSE.md +21 -0
  363. package/skills/create-spring-boot-kotlin-project/SKILL.md +147 -0
  364. package/skills/create-spring-boot-kotlin-project/SYNC.md +5 -0
  365. package/skills/create-technical-spike/LICENSE.md +21 -0
  366. package/skills/create-technical-spike/SKILL.md +230 -0
  367. package/skills/create-technical-spike/SYNC.md +5 -0
  368. package/skills/create-tldr-page/LICENSE.md +21 -0
  369. package/skills/create-tldr-page/SKILL.md +210 -0
  370. package/skills/create-tldr-page/SYNC.md +5 -0
  371. package/skills/creating-oracle-to-postgres-master-migration-plan/LICENSE.md +21 -0
  372. package/skills/creating-oracle-to-postgres-master-migration-plan/SKILL.md +83 -0
  373. package/skills/creating-oracle-to-postgres-master-migration-plan/SYNC.md +5 -0
  374. package/skills/creating-oracle-to-postgres-migration-bug-report/LICENSE.md +21 -0
  375. package/skills/creating-oracle-to-postgres-migration-bug-report/SKILL.md +43 -0
  376. package/skills/creating-oracle-to-postgres-migration-bug-report/SYNC.md +5 -0
  377. package/skills/creating-oracle-to-postgres-migration-bug-report/references/BUG-REPORT-TEMPLATE.md +79 -0
  378. package/skills/creating-oracle-to-postgres-migration-integration-tests/LICENSE.md +21 -0
  379. package/skills/creating-oracle-to-postgres-migration-integration-tests/SKILL.md +60 -0
  380. package/skills/creating-oracle-to-postgres-migration-integration-tests/SYNC.md +5 -0
  381. package/skills/csharp-async/LICENSE.md +21 -0
  382. package/skills/csharp-async/SKILL.md +49 -0
  383. package/skills/csharp-async/SYNC.md +5 -0
  384. package/skills/csharp-docs/LICENSE.md +21 -0
  385. package/skills/csharp-docs/SKILL.md +62 -0
  386. package/skills/csharp-docs/SYNC.md +5 -0
  387. package/skills/csharp-mcp-server-generator/LICENSE.md +21 -0
  388. package/skills/csharp-mcp-server-generator/SKILL.md +59 -0
  389. package/skills/csharp-mcp-server-generator/SYNC.md +5 -0
  390. package/skills/csharp-mstest/LICENSE.md +21 -0
  391. package/skills/csharp-mstest/SKILL.md +478 -0
  392. package/skills/csharp-mstest/SYNC.md +5 -0
  393. package/skills/csharp-nunit/LICENSE.md +21 -0
  394. package/skills/csharp-nunit/SKILL.md +71 -0
  395. package/skills/csharp-nunit/SYNC.md +5 -0
  396. package/skills/csharp-tunit/LICENSE.md +21 -0
  397. package/skills/csharp-tunit/SKILL.md +100 -0
  398. package/skills/csharp-tunit/SYNC.md +5 -0
  399. package/skills/csharp-xunit/LICENSE.md +21 -0
  400. package/skills/csharp-xunit/SKILL.md +68 -0
  401. package/skills/csharp-xunit/SYNC.md +5 -0
  402. package/skills/datanalysis-credit-risk/LICENSE.md +21 -0
  403. package/skills/datanalysis-credit-risk/SKILL.md +113 -0
  404. package/skills/datanalysis-credit-risk/SYNC.md +5 -0
  405. package/skills/datanalysis-credit-risk/references/analysis.py +1223 -0
  406. package/skills/datanalysis-credit-risk/references/func.py +228 -0
  407. package/skills/datanalysis-credit-risk/scripts/example.py +391 -0
  408. package/skills/dataverse-python-advanced-patterns/LICENSE.md +21 -0
  409. package/skills/dataverse-python-advanced-patterns/SKILL.md +17 -0
  410. package/skills/dataverse-python-advanced-patterns/SYNC.md +5 -0
  411. package/skills/dataverse-python-production-code/LICENSE.md +21 -0
  412. package/skills/dataverse-python-production-code/SKILL.md +116 -0
  413. package/skills/dataverse-python-production-code/SYNC.md +5 -0
  414. package/skills/dataverse-python-quickstart/LICENSE.md +21 -0
  415. package/skills/dataverse-python-quickstart/SKILL.md +14 -0
  416. package/skills/dataverse-python-quickstart/SYNC.md +5 -0
  417. package/skills/dataverse-python-usecase-builder/LICENSE.md +21 -0
  418. package/skills/dataverse-python-usecase-builder/SKILL.md +246 -0
  419. package/skills/dataverse-python-usecase-builder/SYNC.md +5 -0
  420. package/skills/debian-linux-triage/LICENSE.md +21 -0
  421. package/skills/debian-linux-triage/SKILL.md +31 -0
  422. package/skills/debian-linux-triage/SYNC.md +5 -0
  423. package/skills/declarative-agents/LICENSE.md +21 -0
  424. package/skills/declarative-agents/SKILL.md +94 -0
  425. package/skills/declarative-agents/SYNC.md +5 -0
  426. package/skills/dependabot/LICENSE.md +21 -0
  427. package/skills/dependabot/SKILL.md +422 -0
  428. package/skills/dependabot/SYNC.md +5 -0
  429. package/skills/dependabot/references/dependabot-yml-reference.md +374 -0
  430. package/skills/dependabot/references/example-configs.md +409 -0
  431. package/skills/dependabot/references/pr-commands.md +91 -0
  432. package/skills/devops-rollout-plan/LICENSE.md +21 -0
  433. package/skills/devops-rollout-plan/SKILL.md +117 -0
  434. package/skills/devops-rollout-plan/SYNC.md +5 -0
  435. package/skills/doc-coauthoring/SKILL.md +375 -0
  436. package/skills/doc-coauthoring/SYNC.md +5 -0
  437. package/skills/documentation-writer/LICENSE.md +21 -0
  438. package/skills/documentation-writer/SKILL.md +45 -0
  439. package/skills/documentation-writer/SYNC.md +5 -0
  440. package/skills/docx/LICENSE.txt +30 -0
  441. package/skills/docx/SKILL.md +590 -0
  442. package/skills/docx/SYNC.md +5 -0
  443. package/skills/docx/scripts/__init__.py +1 -0
  444. package/skills/docx/scripts/accept_changes.py +135 -0
  445. package/skills/docx/scripts/comment.py +318 -0
  446. package/skills/docx/scripts/office/helpers/__init__.py +0 -0
  447. package/skills/docx/scripts/office/helpers/merge_runs.py +199 -0
  448. package/skills/docx/scripts/office/helpers/simplify_redlines.py +197 -0
  449. package/skills/docx/scripts/office/pack.py +159 -0
  450. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  451. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  452. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  453. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  454. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  455. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  456. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  457. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  458. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  459. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  460. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  461. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  462. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  463. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  464. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  465. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  466. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  467. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  468. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  469. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  470. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  471. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  472. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  473. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  474. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  475. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  476. package/skills/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  477. package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  478. package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  479. package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  480. package/skills/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  481. package/skills/docx/scripts/office/schemas/mce/mc.xsd +75 -0
  482. package/skills/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  483. package/skills/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  484. package/skills/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  485. package/skills/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  486. package/skills/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  487. package/skills/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  488. package/skills/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  489. package/skills/docx/scripts/office/soffice.py +183 -0
  490. package/skills/docx/scripts/office/unpack.py +132 -0
  491. package/skills/docx/scripts/office/validate.py +111 -0
  492. package/skills/docx/scripts/office/validators/__init__.py +15 -0
  493. package/skills/docx/scripts/office/validators/base.py +847 -0
  494. package/skills/docx/scripts/office/validators/docx.py +446 -0
  495. package/skills/docx/scripts/office/validators/pptx.py +275 -0
  496. package/skills/docx/scripts/office/validators/redlining.py +247 -0
  497. package/skills/docx/scripts/templates/comments.xml +3 -0
  498. package/skills/docx/scripts/templates/commentsExtended.xml +3 -0
  499. package/skills/docx/scripts/templates/commentsExtensible.xml +3 -0
  500. package/skills/docx/scripts/templates/commentsIds.xml +3 -0
  501. package/skills/docx/scripts/templates/people.xml +3 -0
  502. package/skills/dotnet-best-practices/LICENSE.md +21 -0
  503. package/skills/dotnet-best-practices/SKILL.md +85 -0
  504. package/skills/dotnet-best-practices/SYNC.md +5 -0
  505. package/skills/dotnet-design-pattern-review/LICENSE.md +21 -0
  506. package/skills/dotnet-design-pattern-review/SKILL.md +42 -0
  507. package/skills/dotnet-design-pattern-review/SYNC.md +5 -0
  508. package/skills/dotnet-timezone/LICENSE.md +21 -0
  509. package/skills/dotnet-timezone/SKILL.md +109 -0
  510. package/skills/dotnet-timezone/SYNC.md +5 -0
  511. package/skills/dotnet-timezone/references/code-patterns.md +153 -0
  512. package/skills/dotnet-timezone/references/timezone-index.md +87 -0
  513. package/skills/dotnet-upgrade/LICENSE.md +21 -0
  514. package/skills/dotnet-upgrade/SKILL.md +116 -0
  515. package/skills/dotnet-upgrade/SYNC.md +5 -0
  516. package/skills/doublecheck/LICENSE.md +21 -0
  517. package/skills/doublecheck/SKILL.md +277 -0
  518. package/skills/doublecheck/SYNC.md +5 -0
  519. package/skills/doublecheck/assets/verification-report-template.md +92 -0
  520. package/skills/editorconfig/LICENSE.md +21 -0
  521. package/skills/editorconfig/SKILL.md +63 -0
  522. package/skills/editorconfig/SYNC.md +5 -0
  523. package/skills/ef-core/LICENSE.md +21 -0
  524. package/skills/ef-core/SKILL.md +75 -0
  525. package/skills/ef-core/SYNC.md +5 -0
  526. package/skills/entra-agent-user/LICENSE.md +21 -0
  527. package/skills/entra-agent-user/SKILL.md +270 -0
  528. package/skills/entra-agent-user/SYNC.md +5 -0
  529. package/skills/eval-driven-dev/LICENSE.md +21 -0
  530. package/skills/eval-driven-dev/SKILL.md +862 -0
  531. package/skills/eval-driven-dev/SYNC.md +5 -0
  532. package/skills/eval-driven-dev/references/pixie-api.md +195 -0
  533. package/skills/excalidraw-diagram-generator/LICENSE.md +21 -0
  534. package/skills/excalidraw-diagram-generator/SKILL.md +613 -0
  535. package/skills/excalidraw-diagram-generator/SYNC.md +5 -0
  536. package/skills/excalidraw-diagram-generator/references/element-types.md +497 -0
  537. package/skills/excalidraw-diagram-generator/references/excalidraw-schema.md +350 -0
  538. package/skills/excalidraw-diagram-generator/scripts/README.md +193 -0
  539. package/skills/excalidraw-diagram-generator/scripts/add-arrow.py +312 -0
  540. package/skills/excalidraw-diagram-generator/scripts/add-icon-to-diagram.py +404 -0
  541. package/skills/excalidraw-diagram-generator/scripts/split-excalidraw-library.py +183 -0
  542. package/skills/excalidraw-diagram-generator/templates/business-flow-swimlane-template.excalidraw +334 -0
  543. package/skills/excalidraw-diagram-generator/templates/class-diagram-template.excalidraw +558 -0
  544. package/skills/excalidraw-diagram-generator/templates/data-flow-diagram-template.excalidraw +279 -0
  545. package/skills/excalidraw-diagram-generator/templates/er-diagram-template.excalidraw +662 -0
  546. package/skills/excalidraw-diagram-generator/templates/flowchart-template.excalidraw +179 -0
  547. package/skills/excalidraw-diagram-generator/templates/mindmap-template.excalidraw +244 -0
  548. package/skills/excalidraw-diagram-generator/templates/relationship-template.excalidraw +145 -0
  549. package/skills/excalidraw-diagram-generator/templates/sequence-diagram-template.excalidraw +509 -0
  550. package/skills/fabric-lakehouse/LICENSE.md +21 -0
  551. package/skills/fabric-lakehouse/SKILL.md +106 -0
  552. package/skills/fabric-lakehouse/SYNC.md +5 -0
  553. package/skills/fabric-lakehouse/references/getdata.md +36 -0
  554. package/skills/fabric-lakehouse/references/pyspark.md +189 -0
  555. package/skills/fedora-linux-triage/LICENSE.md +21 -0
  556. package/skills/fedora-linux-triage/SKILL.md +31 -0
  557. package/skills/fedora-linux-triage/SYNC.md +5 -0
  558. package/skills/finalize-agent-prompt/LICENSE.md +21 -0
  559. package/skills/finalize-agent-prompt/SKILL.md +26 -0
  560. package/skills/finalize-agent-prompt/SYNC.md +5 -0
  561. package/skills/finnish-humanizer/LICENSE.md +21 -0
  562. package/skills/finnish-humanizer/SKILL.md +145 -0
  563. package/skills/finnish-humanizer/SYNC.md +5 -0
  564. package/skills/finnish-humanizer/references/patterns.md +338 -0
  565. package/skills/first-ask/LICENSE.md +21 -0
  566. package/skills/first-ask/SKILL.md +30 -0
  567. package/skills/first-ask/SYNC.md +5 -0
  568. package/skills/flowstudio-power-automate-build/LICENSE.md +21 -0
  569. package/skills/flowstudio-power-automate-build/SKILL.md +460 -0
  570. package/skills/flowstudio-power-automate-build/SYNC.md +5 -0
  571. package/skills/flowstudio-power-automate-build/references/action-patterns-connectors.md +542 -0
  572. package/skills/flowstudio-power-automate-build/references/action-patterns-core.md +542 -0
  573. package/skills/flowstudio-power-automate-build/references/action-patterns-data.md +735 -0
  574. package/skills/flowstudio-power-automate-build/references/build-patterns.md +108 -0
  575. package/skills/flowstudio-power-automate-build/references/flow-schema.md +225 -0
  576. package/skills/flowstudio-power-automate-build/references/trigger-types.md +211 -0
  577. package/skills/flowstudio-power-automate-debug/LICENSE.md +21 -0
  578. package/skills/flowstudio-power-automate-debug/SKILL.md +322 -0
  579. package/skills/flowstudio-power-automate-debug/SYNC.md +5 -0
  580. package/skills/flowstudio-power-automate-debug/references/common-errors.md +188 -0
  581. package/skills/flowstudio-power-automate-debug/references/debug-workflow.md +157 -0
  582. package/skills/flowstudio-power-automate-mcp/LICENSE.md +21 -0
  583. package/skills/flowstudio-power-automate-mcp/SKILL.md +450 -0
  584. package/skills/flowstudio-power-automate-mcp/SYNC.md +5 -0
  585. package/skills/flowstudio-power-automate-mcp/references/MCP-BOOTSTRAP.md +53 -0
  586. package/skills/flowstudio-power-automate-mcp/references/action-types.md +79 -0
  587. package/skills/flowstudio-power-automate-mcp/references/connection-references.md +115 -0
  588. package/skills/flowstudio-power-automate-mcp/references/tool-reference.md +445 -0
  589. package/skills/fluentui-blazor/LICENSE.md +21 -0
  590. package/skills/fluentui-blazor/SKILL.md +231 -0
  591. package/skills/fluentui-blazor/SYNC.md +5 -0
  592. package/skills/fluentui-blazor/references/DATAGRID.md +162 -0
  593. package/skills/fluentui-blazor/references/LAYOUT-AND-NAVIGATION.md +173 -0
  594. package/skills/fluentui-blazor/references/SETUP.md +129 -0
  595. package/skills/fluentui-blazor/references/THEMING.md +103 -0
  596. package/skills/folder-structure-blueprint-generator/LICENSE.md +21 -0
  597. package/skills/folder-structure-blueprint-generator/SKILL.md +405 -0
  598. package/skills/folder-structure-blueprint-generator/SYNC.md +5 -0
  599. package/skills/frontend-design/LICENSE.txt +177 -0
  600. package/skills/frontend-design/SKILL.md +42 -0
  601. package/skills/frontend-design/SYNC.md +5 -0
  602. package/skills/game-engine/LICENSE.md +21 -0
  603. package/skills/game-engine/SKILL.md +139 -0
  604. package/skills/game-engine/SYNC.md +5 -0
  605. package/skills/game-engine/assets/2d-maze-game.md +528 -0
  606. package/skills/game-engine/assets/2d-platform-game.md +1855 -0
  607. package/skills/game-engine/assets/gameBase-template-repo.md +310 -0
  608. package/skills/game-engine/assets/paddle-game-template.md +1528 -0
  609. package/skills/game-engine/assets/simple-2d-engine.md +507 -0
  610. package/skills/game-engine/references/3d-web-games.md +754 -0
  611. package/skills/game-engine/references/algorithms.md +843 -0
  612. package/skills/game-engine/references/basics.md +343 -0
  613. package/skills/game-engine/references/game-control-mechanisms.md +617 -0
  614. package/skills/game-engine/references/game-engine-core-principles.md +695 -0
  615. package/skills/game-engine/references/game-publishing.md +352 -0
  616. package/skills/game-engine/references/techniques.md +894 -0
  617. package/skills/game-engine/references/terminology.md +354 -0
  618. package/skills/game-engine/references/web-apis.md +1394 -0
  619. package/skills/gen-specs-as-issues/LICENSE.md +21 -0
  620. package/skills/gen-specs-as-issues/SKILL.md +165 -0
  621. package/skills/gen-specs-as-issues/SYNC.md +5 -0
  622. package/skills/generate-custom-instructions-from-codebase/LICENSE.md +21 -0
  623. package/skills/generate-custom-instructions-from-codebase/SKILL.md +240 -0
  624. package/skills/generate-custom-instructions-from-codebase/SYNC.md +5 -0
  625. package/skills/geofeed-tuner/LICENSE.md +21 -0
  626. package/skills/geofeed-tuner/SKILL.md +864 -0
  627. package/skills/geofeed-tuner/SYNC.md +5 -0
  628. package/skills/geofeed-tuner/assets/example/01-user-input-rfc8805-feed.csv +5 -0
  629. package/skills/geofeed-tuner/assets/iso3166-1.json +1249 -0
  630. package/skills/geofeed-tuner/assets/iso3166-2.json +20188 -0
  631. package/skills/geofeed-tuner/assets/small-territories.json +106 -0
  632. package/skills/geofeed-tuner/references/rfc8805.txt +735 -0
  633. package/skills/geofeed-tuner/references/snippets-python3.md +85 -0
  634. package/skills/geofeed-tuner/scripts/templates/index.html +2305 -0
  635. package/skills/gh-cli/LICENSE.md +21 -0
  636. package/skills/gh-cli/SKILL.md +2187 -0
  637. package/skills/gh-cli/SYNC.md +5 -0
  638. package/skills/git-commit/LICENSE.md +21 -0
  639. package/skills/git-commit/SKILL.md +124 -0
  640. package/skills/git-commit/SYNC.md +5 -0
  641. package/skills/git-flow-branch-creator/LICENSE.md +21 -0
  642. package/skills/git-flow-branch-creator/SKILL.md +292 -0
  643. package/skills/git-flow-branch-creator/SYNC.md +5 -0
  644. package/skills/github-copilot-starter/LICENSE.md +21 -0
  645. package/skills/github-copilot-starter/SKILL.md +402 -0
  646. package/skills/github-copilot-starter/SYNC.md +5 -0
  647. package/skills/github-issues/LICENSE.md +21 -0
  648. package/skills/github-issues/SKILL.md +201 -0
  649. package/skills/github-issues/SYNC.md +5 -0
  650. package/skills/github-issues/references/dependencies.md +71 -0
  651. package/skills/github-issues/references/images.md +116 -0
  652. package/skills/github-issues/references/issue-fields.md +191 -0
  653. package/skills/github-issues/references/issue-types.md +72 -0
  654. package/skills/github-issues/references/projects.md +273 -0
  655. package/skills/github-issues/references/search.md +231 -0
  656. package/skills/github-issues/references/sub-issues.md +137 -0
  657. package/skills/github-issues/references/templates.md +90 -0
  658. package/skills/go-mcp-server-generator/LICENSE.md +21 -0
  659. package/skills/go-mcp-server-generator/SKILL.md +334 -0
  660. package/skills/go-mcp-server-generator/SYNC.md +5 -0
  661. package/skills/gtm-0-to-1-launch/LICENSE.md +21 -0
  662. package/skills/gtm-0-to-1-launch/SKILL.md +321 -0
  663. package/skills/gtm-0-to-1-launch/SYNC.md +5 -0
  664. package/skills/gtm-ai-gtm/LICENSE.md +21 -0
  665. package/skills/gtm-ai-gtm/SKILL.md +569 -0
  666. package/skills/gtm-ai-gtm/SYNC.md +5 -0
  667. package/skills/gtm-board-and-investor-communication/LICENSE.md +21 -0
  668. package/skills/gtm-board-and-investor-communication/SKILL.md +456 -0
  669. package/skills/gtm-board-and-investor-communication/SYNC.md +5 -0
  670. package/skills/gtm-developer-ecosystem/LICENSE.md +21 -0
  671. package/skills/gtm-developer-ecosystem/SKILL.md +310 -0
  672. package/skills/gtm-developer-ecosystem/SYNC.md +5 -0
  673. package/skills/gtm-enterprise-account-planning/LICENSE.md +21 -0
  674. package/skills/gtm-enterprise-account-planning/SKILL.md +429 -0
  675. package/skills/gtm-enterprise-account-planning/SYNC.md +5 -0
  676. package/skills/gtm-enterprise-onboarding/LICENSE.md +21 -0
  677. package/skills/gtm-enterprise-onboarding/SKILL.md +457 -0
  678. package/skills/gtm-enterprise-onboarding/SYNC.md +5 -0
  679. package/skills/gtm-operating-cadence/LICENSE.md +21 -0
  680. package/skills/gtm-operating-cadence/SKILL.md +420 -0
  681. package/skills/gtm-operating-cadence/SYNC.md +5 -0
  682. package/skills/gtm-partnership-architecture/LICENSE.md +21 -0
  683. package/skills/gtm-partnership-architecture/SKILL.md +470 -0
  684. package/skills/gtm-partnership-architecture/SYNC.md +5 -0
  685. package/skills/gtm-positioning-strategy/LICENSE.md +21 -0
  686. package/skills/gtm-positioning-strategy/SKILL.md +438 -0
  687. package/skills/gtm-positioning-strategy/SYNC.md +5 -0
  688. package/skills/gtm-product-led-growth/LICENSE.md +21 -0
  689. package/skills/gtm-product-led-growth/SKILL.md +339 -0
  690. package/skills/gtm-product-led-growth/SYNC.md +5 -0
  691. package/skills/gtm-technical-product-pricing/LICENSE.md +21 -0
  692. package/skills/gtm-technical-product-pricing/SKILL.md +353 -0
  693. package/skills/gtm-technical-product-pricing/SYNC.md +5 -0
  694. package/skills/image-manipulation-image-magick/LICENSE.md +21 -0
  695. package/skills/image-manipulation-image-magick/SKILL.md +252 -0
  696. package/skills/image-manipulation-image-magick/SYNC.md +5 -0
  697. package/skills/import-infrastructure-as-code/LICENSE.md +21 -0
  698. package/skills/import-infrastructure-as-code/SKILL.md +367 -0
  699. package/skills/import-infrastructure-as-code/SYNC.md +5 -0
  700. package/skills/internal-comms/LICENSE.txt +202 -0
  701. package/skills/internal-comms/SKILL.md +32 -0
  702. package/skills/internal-comms/SYNC.md +5 -0
  703. package/skills/internal-comms/examples/3p-updates.md +47 -0
  704. package/skills/internal-comms/examples/company-newsletter.md +65 -0
  705. package/skills/internal-comms/examples/faq-answers.md +30 -0
  706. package/skills/internal-comms/examples/general-comms.md +16 -0
  707. package/skills/issue-fields-migration/LICENSE.md +21 -0
  708. package/skills/issue-fields-migration/SKILL.md +533 -0
  709. package/skills/issue-fields-migration/SYNC.md +5 -0
  710. package/skills/issue-fields-migration/references/issue-fields-api.md +129 -0
  711. package/skills/issue-fields-migration/references/labels-api.md +74 -0
  712. package/skills/issue-fields-migration/references/projects-api.md +116 -0
  713. package/skills/java-add-graalvm-native-image-support/LICENSE.md +21 -0
  714. package/skills/java-add-graalvm-native-image-support/SKILL.md +449 -0
  715. package/skills/java-add-graalvm-native-image-support/SYNC.md +5 -0
  716. package/skills/java-docs/LICENSE.md +21 -0
  717. package/skills/java-docs/SKILL.md +23 -0
  718. package/skills/java-docs/SYNC.md +5 -0
  719. package/skills/java-junit/LICENSE.md +21 -0
  720. package/skills/java-junit/SKILL.md +63 -0
  721. package/skills/java-junit/SYNC.md +5 -0
  722. package/skills/java-mcp-server-generator/LICENSE.md +21 -0
  723. package/skills/java-mcp-server-generator/SKILL.md +756 -0
  724. package/skills/java-mcp-server-generator/SYNC.md +5 -0
  725. package/skills/java-refactoring-extract-method/LICENSE.md +21 -0
  726. package/skills/java-refactoring-extract-method/SKILL.md +104 -0
  727. package/skills/java-refactoring-extract-method/SYNC.md +5 -0
  728. package/skills/java-refactoring-remove-parameter/LICENSE.md +21 -0
  729. package/skills/java-refactoring-remove-parameter/SKILL.md +84 -0
  730. package/skills/java-refactoring-remove-parameter/SYNC.md +5 -0
  731. package/skills/java-springboot/LICENSE.md +21 -0
  732. package/skills/java-springboot/SKILL.md +65 -0
  733. package/skills/java-springboot/SYNC.md +5 -0
  734. package/skills/javascript-typescript-jest/LICENSE.md +21 -0
  735. package/skills/javascript-typescript-jest/SKILL.md +44 -0
  736. package/skills/javascript-typescript-jest/SYNC.md +5 -0
  737. package/skills/kotlin-mcp-server-generator/LICENSE.md +21 -0
  738. package/skills/kotlin-mcp-server-generator/SKILL.md +449 -0
  739. package/skills/kotlin-mcp-server-generator/SYNC.md +5 -0
  740. package/skills/kotlin-springboot/LICENSE.md +21 -0
  741. package/skills/kotlin-springboot/SKILL.md +70 -0
  742. package/skills/kotlin-springboot/SYNC.md +5 -0
  743. package/skills/legacy-circuit-mockups/LICENSE.md +21 -0
  744. package/skills/legacy-circuit-mockups/SKILL.md +276 -0
  745. package/skills/legacy-circuit-mockups/SYNC.md +5 -0
  746. package/skills/legacy-circuit-mockups/references/28256-eeprom.md +190 -0
  747. package/skills/legacy-circuit-mockups/references/555.md +861 -0
  748. package/skills/legacy-circuit-mockups/references/6502.md +221 -0
  749. package/skills/legacy-circuit-mockups/references/6522.md +211 -0
  750. package/skills/legacy-circuit-mockups/references/6C62256.md +177 -0
  751. package/skills/legacy-circuit-mockups/references/7400-series.md +177 -0
  752. package/skills/legacy-circuit-mockups/references/assembly-compiler.md +258 -0
  753. package/skills/legacy-circuit-mockups/references/assembly-language.md +226 -0
  754. package/skills/legacy-circuit-mockups/references/basic-electronic-components.md +86 -0
  755. package/skills/legacy-circuit-mockups/references/breadboard.md +214 -0
  756. package/skills/legacy-circuit-mockups/references/common-breadboard-components.md +281 -0
  757. package/skills/legacy-circuit-mockups/references/connecting-electronic-components.md +310 -0
  758. package/skills/legacy-circuit-mockups/references/emulator-28256-eeprom.md +245 -0
  759. package/skills/legacy-circuit-mockups/references/emulator-6502.md +251 -0
  760. package/skills/legacy-circuit-mockups/references/emulator-6522.md +288 -0
  761. package/skills/legacy-circuit-mockups/references/emulator-6C62256.md +233 -0
  762. package/skills/legacy-circuit-mockups/references/emulator-lcd.md +266 -0
  763. package/skills/legacy-circuit-mockups/references/lcd.md +208 -0
  764. package/skills/legacy-circuit-mockups/references/minipro.md +211 -0
  765. package/skills/legacy-circuit-mockups/references/t48eeprom-programmer.md +174 -0
  766. package/skills/make-repo-contribution/LICENSE.md +21 -0
  767. package/skills/make-repo-contribution/SKILL.md +90 -0
  768. package/skills/make-repo-contribution/SYNC.md +5 -0
  769. package/skills/make-repo-contribution/assets/issue-template.md +37 -0
  770. package/skills/make-repo-contribution/assets/pr-template.md +36 -0
  771. package/skills/make-skill-template/LICENSE.md +21 -0
  772. package/skills/make-skill-template/SKILL.md +147 -0
  773. package/skills/make-skill-template/SYNC.md +5 -0
  774. package/skills/markdown-to-html/LICENSE.md +21 -0
  775. package/skills/markdown-to-html/SKILL.md +916 -0
  776. package/skills/markdown-to-html/SYNC.md +5 -0
  777. package/skills/markdown-to-html/references/basic-markdown-to-html.md +420 -0
  778. package/skills/markdown-to-html/references/basic-markdown.md +496 -0
  779. package/skills/markdown-to-html/references/code-blocks-to-html.md +165 -0
  780. package/skills/markdown-to-html/references/code-blocks.md +70 -0
  781. package/skills/markdown-to-html/references/collapsed-sections-to-html.md +136 -0
  782. package/skills/markdown-to-html/references/collapsed-sections.md +48 -0
  783. package/skills/markdown-to-html/references/gomarkdown.md +253 -0
  784. package/skills/markdown-to-html/references/hugo.md +394 -0
  785. package/skills/markdown-to-html/references/jekyll.md +321 -0
  786. package/skills/markdown-to-html/references/marked.md +121 -0
  787. package/skills/markdown-to-html/references/pandoc.md +226 -0
  788. package/skills/markdown-to-html/references/tables-to-html.md +169 -0
  789. package/skills/markdown-to-html/references/tables.md +72 -0
  790. package/skills/markdown-to-html/references/writing-mathematical-expressions-to-html.md +350 -0
  791. package/skills/markdown-to-html/references/writing-mathematical-expressions.md +76 -0
  792. package/skills/mcp-builder/LICENSE.txt +202 -0
  793. package/skills/mcp-builder/SKILL.md +236 -0
  794. package/skills/mcp-builder/SYNC.md +5 -0
  795. package/skills/mcp-builder/reference/evaluation.md +602 -0
  796. package/skills/mcp-builder/reference/mcp_best_practices.md +249 -0
  797. package/skills/mcp-builder/reference/node_mcp_server.md +970 -0
  798. package/skills/mcp-builder/reference/python_mcp_server.md +719 -0
  799. package/skills/mcp-builder/scripts/connections.py +151 -0
  800. package/skills/mcp-builder/scripts/evaluation.py +373 -0
  801. package/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
  802. package/skills/mcp-builder/scripts/requirements.txt +2 -0
  803. package/skills/mcp-cli/LICENSE.md +21 -0
  804. package/skills/mcp-cli/SKILL.md +78 -0
  805. package/skills/mcp-cli/SYNC.md +5 -0
  806. package/skills/mcp-copilot-studio-server-generator/LICENSE.md +21 -0
  807. package/skills/mcp-copilot-studio-server-generator/SKILL.md +118 -0
  808. package/skills/mcp-copilot-studio-server-generator/SYNC.md +5 -0
  809. package/skills/mcp-create-adaptive-cards/LICENSE.md +21 -0
  810. package/skills/mcp-create-adaptive-cards/SKILL.md +532 -0
  811. package/skills/mcp-create-adaptive-cards/SYNC.md +5 -0
  812. package/skills/mcp-create-declarative-agent/LICENSE.md +21 -0
  813. package/skills/mcp-create-declarative-agent/SKILL.md +315 -0
  814. package/skills/mcp-create-declarative-agent/SYNC.md +5 -0
  815. package/skills/mcp-deploy-manage-agents/LICENSE.md +21 -0
  816. package/skills/mcp-deploy-manage-agents/SKILL.md +341 -0
  817. package/skills/mcp-deploy-manage-agents/SYNC.md +5 -0
  818. package/skills/meeting-minutes/LICENSE.md +21 -0
  819. package/skills/meeting-minutes/SKILL.md +235 -0
  820. package/skills/meeting-minutes/SYNC.md +5 -0
  821. package/skills/memory-merger/LICENSE.md +21 -0
  822. package/skills/memory-merger/SKILL.md +108 -0
  823. package/skills/memory-merger/SYNC.md +5 -0
  824. package/skills/mentoring-juniors/LICENSE.md +21 -0
  825. package/skills/mentoring-juniors/SKILL.md +310 -0
  826. package/skills/mentoring-juniors/SYNC.md +5 -0
  827. package/skills/microsoft-agent-framework/LICENSE.md +21 -0
  828. package/skills/microsoft-agent-framework/SKILL.md +65 -0
  829. package/skills/microsoft-agent-framework/SYNC.md +5 -0
  830. package/skills/microsoft-agent-framework/references/dotnet.md +24 -0
  831. package/skills/microsoft-agent-framework/references/python.md +24 -0
  832. package/skills/microsoft-code-reference/LICENSE.md +21 -0
  833. package/skills/microsoft-code-reference/SKILL.md +99 -0
  834. package/skills/microsoft-code-reference/SYNC.md +5 -0
  835. package/skills/microsoft-docs/LICENSE.md +21 -0
  836. package/skills/microsoft-docs/SKILL.md +134 -0
  837. package/skills/microsoft-docs/SYNC.md +5 -0
  838. package/skills/microsoft-skill-creator/LICENSE.md +21 -0
  839. package/skills/microsoft-skill-creator/SKILL.md +250 -0
  840. package/skills/microsoft-skill-creator/SYNC.md +5 -0
  841. package/skills/microsoft-skill-creator/references/skill-templates.md +345 -0
  842. package/skills/migrating-oracle-to-postgres-stored-procedures/LICENSE.md +21 -0
  843. package/skills/migrating-oracle-to-postgres-stored-procedures/SKILL.md +42 -0
  844. package/skills/migrating-oracle-to-postgres-stored-procedures/SYNC.md +5 -0
  845. package/skills/mkdocs-translations/LICENSE.md +21 -0
  846. package/skills/mkdocs-translations/SKILL.md +108 -0
  847. package/skills/mkdocs-translations/SYNC.md +5 -0
  848. package/skills/model-recommendation/LICENSE.md +21 -0
  849. package/skills/model-recommendation/SKILL.md +672 -0
  850. package/skills/model-recommendation/SYNC.md +5 -0
  851. package/skills/msstore-cli/LICENSE.md +21 -0
  852. package/skills/msstore-cli/SKILL.md +600 -0
  853. package/skills/msstore-cli/SYNC.md +5 -0
  854. package/skills/multi-stage-dockerfile/LICENSE.md +21 -0
  855. package/skills/multi-stage-dockerfile/SKILL.md +46 -0
  856. package/skills/multi-stage-dockerfile/SYNC.md +5 -0
  857. package/skills/my-issues/LICENSE.md +21 -0
  858. package/skills/my-issues/SKILL.md +8 -0
  859. package/skills/my-issues/SYNC.md +5 -0
  860. package/skills/my-pull-requests/LICENSE.md +21 -0
  861. package/skills/my-pull-requests/SKILL.md +14 -0
  862. package/skills/my-pull-requests/SYNC.md +5 -0
  863. package/skills/nano-banana-pro-openrouter/LICENSE.md +21 -0
  864. package/skills/nano-banana-pro-openrouter/SKILL.md +74 -0
  865. package/skills/nano-banana-pro-openrouter/SYNC.md +5 -0
  866. package/skills/nano-banana-pro-openrouter/assets/SYSTEM_TEMPLATE +14 -0
  867. package/skills/nano-banana-pro-openrouter/scripts/generate_image.py +191 -0
  868. package/skills/napkin/LICENSE.md +21 -0
  869. package/skills/napkin/SKILL.md +154 -0
  870. package/skills/napkin/SYNC.md +5 -0
  871. package/skills/napkin/assets/napkin.html +2019 -0
  872. package/skills/napkin/assets/step1-activate.svg +107 -0
  873. package/skills/napkin/assets/step2-whiteboard.svg +157 -0
  874. package/skills/napkin/assets/step3-draw.svg +143 -0
  875. package/skills/napkin/assets/step4-share.svg +98 -0
  876. package/skills/napkin/assets/step5-response.svg +112 -0
  877. package/skills/next-best-practices/SKILL.md +153 -0
  878. package/skills/next-best-practices/SYNC.md +5 -0
  879. package/skills/next-best-practices/async-patterns.md +87 -0
  880. package/skills/next-best-practices/bundling.md +180 -0
  881. package/skills/next-best-practices/data-patterns.md +297 -0
  882. package/skills/next-best-practices/debug-tricks.md +105 -0
  883. package/skills/next-best-practices/directives.md +73 -0
  884. package/skills/next-best-practices/error-handling.md +227 -0
  885. package/skills/next-best-practices/file-conventions.md +140 -0
  886. package/skills/next-best-practices/font.md +245 -0
  887. package/skills/next-best-practices/functions.md +108 -0
  888. package/skills/next-best-practices/hydration-error.md +91 -0
  889. package/skills/next-best-practices/image.md +173 -0
  890. package/skills/next-best-practices/metadata.md +301 -0
  891. package/skills/next-best-practices/parallel-routes.md +287 -0
  892. package/skills/next-best-practices/route-handlers.md +146 -0
  893. package/skills/next-best-practices/rsc-boundaries.md +159 -0
  894. package/skills/next-best-practices/runtime-selection.md +39 -0
  895. package/skills/next-best-practices/scripts.md +141 -0
  896. package/skills/next-best-practices/self-hosting.md +371 -0
  897. package/skills/next-best-practices/suspense-boundaries.md +67 -0
  898. package/skills/next-cache-components/SKILL.md +411 -0
  899. package/skills/next-cache-components/SYNC.md +5 -0
  900. package/skills/next-intl-add-language/LICENSE.md +21 -0
  901. package/skills/next-intl-add-language/SKILL.md +19 -0
  902. package/skills/next-intl-add-language/SYNC.md +5 -0
  903. package/skills/next-upgrade/SKILL.md +50 -0
  904. package/skills/next-upgrade/SYNC.md +5 -0
  905. package/skills/noob-mode/LICENSE.md +21 -0
  906. package/skills/noob-mode/SKILL.md +263 -0
  907. package/skills/noob-mode/SYNC.md +5 -0
  908. package/skills/noob-mode/references/examples.md +418 -0
  909. package/skills/noob-mode/references/glossary.md +368 -0
  910. package/skills/nuget-manager/LICENSE.md +21 -0
  911. package/skills/nuget-manager/SKILL.md +68 -0
  912. package/skills/nuget-manager/SYNC.md +5 -0
  913. package/skills/oo-component-documentation/LICENSE.md +21 -0
  914. package/skills/oo-component-documentation/SKILL.md +74 -0
  915. package/skills/oo-component-documentation/SYNC.md +5 -0
  916. package/skills/oo-component-documentation/assets/documentation-template.md +97 -0
  917. package/skills/oo-component-documentation/references/create-mode.md +32 -0
  918. package/skills/oo-component-documentation/references/update-mode.md +32 -0
  919. package/skills/openapi-to-application-code/LICENSE.md +21 -0
  920. package/skills/openapi-to-application-code/SKILL.md +112 -0
  921. package/skills/openapi-to-application-code/SYNC.md +5 -0
  922. package/skills/pdf/LICENSE.txt +30 -0
  923. package/skills/pdf/SKILL.md +314 -0
  924. package/skills/pdf/SYNC.md +5 -0
  925. package/skills/pdf/forms.md +294 -0
  926. package/skills/pdf/reference.md +612 -0
  927. package/skills/pdf/scripts/check_bounding_boxes.py +65 -0
  928. package/skills/pdf/scripts/check_fillable_fields.py +11 -0
  929. package/skills/pdf/scripts/convert_pdf_to_images.py +33 -0
  930. package/skills/pdf/scripts/create_validation_image.py +37 -0
  931. package/skills/pdf/scripts/extract_form_field_info.py +122 -0
  932. package/skills/pdf/scripts/extract_form_structure.py +115 -0
  933. package/skills/pdf/scripts/fill_fillable_fields.py +98 -0
  934. package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
  935. package/skills/pdftk-server/LICENSE.md +21 -0
  936. package/skills/pdftk-server/SKILL.md +162 -0
  937. package/skills/pdftk-server/SYNC.md +5 -0
  938. package/skills/pdftk-server/references/download.md +75 -0
  939. package/skills/pdftk-server/references/pdftk-cli-examples.md +193 -0
  940. package/skills/pdftk-server/references/pdftk-man-page.md +232 -0
  941. package/skills/pdftk-server/references/pdftk-server-license.md +25 -0
  942. package/skills/pdftk-server/references/third-party-materials.md +103 -0
  943. package/skills/penpot-uiux-design/LICENSE.md +21 -0
  944. package/skills/penpot-uiux-design/SKILL.md +342 -0
  945. package/skills/penpot-uiux-design/SYNC.md +5 -0
  946. package/skills/penpot-uiux-design/references/accessibility.md +329 -0
  947. package/skills/penpot-uiux-design/references/component-patterns.md +339 -0
  948. package/skills/penpot-uiux-design/references/platform-guidelines.md +367 -0
  949. package/skills/penpot-uiux-design/references/setup-troubleshooting.md +328 -0
  950. package/skills/php-mcp-server-generator/LICENSE.md +21 -0
  951. package/skills/php-mcp-server-generator/SKILL.md +522 -0
  952. package/skills/php-mcp-server-generator/SYNC.md +5 -0
  953. package/skills/planning-oracle-to-postgres-migration-integration-testing/LICENSE.md +21 -0
  954. package/skills/planning-oracle-to-postgres-migration-integration-testing/SKILL.md +44 -0
  955. package/skills/planning-oracle-to-postgres-migration-integration-testing/SYNC.md +5 -0
  956. package/skills/plantuml-ascii/LICENSE.md +21 -0
  957. package/skills/plantuml-ascii/SKILL.md +305 -0
  958. package/skills/plantuml-ascii/SYNC.md +5 -0
  959. package/skills/playwright-automation-fill-in-form/LICENSE.md +21 -0
  960. package/skills/playwright-automation-fill-in-form/SKILL.md +28 -0
  961. package/skills/playwright-automation-fill-in-form/SYNC.md +5 -0
  962. package/skills/playwright-explore-website/LICENSE.md +21 -0
  963. package/skills/playwright-explore-website/SKILL.md +17 -0
  964. package/skills/playwright-explore-website/SYNC.md +5 -0
  965. package/skills/playwright-generate-test/LICENSE.md +21 -0
  966. package/skills/playwright-generate-test/SKILL.md +17 -0
  967. package/skills/playwright-generate-test/SYNC.md +5 -0
  968. package/skills/polyglot-test-agent/LICENSE.md +21 -0
  969. package/skills/polyglot-test-agent/SKILL.md +161 -0
  970. package/skills/polyglot-test-agent/SYNC.md +5 -0
  971. package/skills/polyglot-test-agent/unit-test-generation.prompt.md +155 -0
  972. package/skills/postgresql-code-review/LICENSE.md +21 -0
  973. package/skills/postgresql-code-review/SKILL.md +212 -0
  974. package/skills/postgresql-code-review/SYNC.md +5 -0
  975. package/skills/postgresql-optimization/LICENSE.md +21 -0
  976. package/skills/postgresql-optimization/SKILL.md +404 -0
  977. package/skills/postgresql-optimization/SYNC.md +5 -0
  978. package/skills/power-apps-code-app-scaffold/LICENSE.md +21 -0
  979. package/skills/power-apps-code-app-scaffold/SKILL.md +146 -0
  980. package/skills/power-apps-code-app-scaffold/SYNC.md +5 -0
  981. package/skills/power-bi-dax-optimization/LICENSE.md +21 -0
  982. package/skills/power-bi-dax-optimization/SKILL.md +173 -0
  983. package/skills/power-bi-dax-optimization/SYNC.md +5 -0
  984. package/skills/power-bi-model-design-review/LICENSE.md +21 -0
  985. package/skills/power-bi-model-design-review/SKILL.md +403 -0
  986. package/skills/power-bi-model-design-review/SYNC.md +5 -0
  987. package/skills/power-bi-performance-troubleshooting/LICENSE.md +21 -0
  988. package/skills/power-bi-performance-troubleshooting/SKILL.md +382 -0
  989. package/skills/power-bi-performance-troubleshooting/SYNC.md +5 -0
  990. package/skills/power-bi-report-design-consultation/LICENSE.md +21 -0
  991. package/skills/power-bi-report-design-consultation/SKILL.md +351 -0
  992. package/skills/power-bi-report-design-consultation/SYNC.md +5 -0
  993. package/skills/power-platform-mcp-connector-suite/LICENSE.md +21 -0
  994. package/skills/power-platform-mcp-connector-suite/SKILL.md +156 -0
  995. package/skills/power-platform-mcp-connector-suite/SYNC.md +5 -0
  996. package/skills/powerbi-modeling/LICENSE.md +21 -0
  997. package/skills/powerbi-modeling/SKILL.md +153 -0
  998. package/skills/powerbi-modeling/SYNC.md +5 -0
  999. package/skills/powerbi-modeling/references/MEASURES-DAX.md +195 -0
  1000. package/skills/powerbi-modeling/references/PERFORMANCE.md +215 -0
  1001. package/skills/powerbi-modeling/references/RELATIONSHIPS.md +147 -0
  1002. package/skills/powerbi-modeling/references/RLS.md +226 -0
  1003. package/skills/powerbi-modeling/references/STAR-SCHEMA.md +103 -0
  1004. package/skills/pptx/LICENSE.txt +30 -0
  1005. package/skills/pptx/SKILL.md +232 -0
  1006. package/skills/pptx/SYNC.md +5 -0
  1007. package/skills/pptx/editing.md +205 -0
  1008. package/skills/pptx/pptxgenjs.md +420 -0
  1009. package/skills/pptx/scripts/__init__.py +0 -0
  1010. package/skills/pptx/scripts/add_slide.py +195 -0
  1011. package/skills/pptx/scripts/clean.py +286 -0
  1012. package/skills/pptx/scripts/office/helpers/__init__.py +0 -0
  1013. package/skills/pptx/scripts/office/helpers/merge_runs.py +199 -0
  1014. package/skills/pptx/scripts/office/helpers/simplify_redlines.py +197 -0
  1015. package/skills/pptx/scripts/office/pack.py +159 -0
  1016. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  1017. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  1018. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  1019. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  1020. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  1021. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  1022. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  1023. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  1024. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  1025. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  1026. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  1027. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  1028. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  1029. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  1030. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  1031. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  1032. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  1033. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  1034. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  1035. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  1036. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  1037. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  1038. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  1039. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  1040. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  1041. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  1042. package/skills/pptx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  1043. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  1044. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  1045. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  1046. package/skills/pptx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  1047. package/skills/pptx/scripts/office/schemas/mce/mc.xsd +75 -0
  1048. package/skills/pptx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  1049. package/skills/pptx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  1050. package/skills/pptx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  1051. package/skills/pptx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  1052. package/skills/pptx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  1053. package/skills/pptx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  1054. package/skills/pptx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  1055. package/skills/pptx/scripts/office/soffice.py +183 -0
  1056. package/skills/pptx/scripts/office/unpack.py +132 -0
  1057. package/skills/pptx/scripts/office/validate.py +111 -0
  1058. package/skills/pptx/scripts/office/validators/__init__.py +15 -0
  1059. package/skills/pptx/scripts/office/validators/base.py +847 -0
  1060. package/skills/pptx/scripts/office/validators/docx.py +446 -0
  1061. package/skills/pptx/scripts/office/validators/pptx.py +275 -0
  1062. package/skills/pptx/scripts/office/validators/redlining.py +247 -0
  1063. package/skills/pptx/scripts/thumbnail.py +289 -0
  1064. package/skills/prd/LICENSE.md +21 -0
  1065. package/skills/prd/SKILL.md +143 -0
  1066. package/skills/prd/SYNC.md +5 -0
  1067. package/skills/premium-frontend-ui/LICENSE.md +21 -0
  1068. package/skills/premium-frontend-ui/SKILL.md +110 -0
  1069. package/skills/premium-frontend-ui/SYNC.md +5 -0
  1070. package/skills/project-workflow-analysis-blueprint-generator/LICENSE.md +21 -0
  1071. package/skills/project-workflow-analysis-blueprint-generator/SKILL.md +293 -0
  1072. package/skills/project-workflow-analysis-blueprint-generator/SYNC.md +5 -0
  1073. package/skills/prompt-builder/LICENSE.md +21 -0
  1074. package/skills/prompt-builder/SKILL.md +141 -0
  1075. package/skills/prompt-builder/SYNC.md +5 -0
  1076. package/skills/publish-to-pages/LICENSE.md +21 -0
  1077. package/skills/publish-to-pages/SKILL.md +107 -0
  1078. package/skills/publish-to-pages/SYNC.md +5 -0
  1079. package/skills/publish-to-pages/scripts/convert-pdf.py +176 -0
  1080. package/skills/publish-to-pages/scripts/convert-pptx.py +376 -0
  1081. package/skills/publish-to-pages/scripts/publish.sh +51 -0
  1082. package/skills/pytest-coverage/LICENSE.md +21 -0
  1083. package/skills/pytest-coverage/SKILL.md +28 -0
  1084. package/skills/pytest-coverage/SYNC.md +5 -0
  1085. package/skills/python-mcp-server-generator/LICENSE.md +21 -0
  1086. package/skills/python-mcp-server-generator/SKILL.md +105 -0
  1087. package/skills/python-mcp-server-generator/SYNC.md +5 -0
  1088. package/skills/quasi-coder/LICENSE.md +21 -0
  1089. package/skills/quasi-coder/SKILL.md +369 -0
  1090. package/skills/quasi-coder/SYNC.md +5 -0
  1091. package/skills/readme-blueprint-generator/LICENSE.md +21 -0
  1092. package/skills/readme-blueprint-generator/SKILL.md +78 -0
  1093. package/skills/readme-blueprint-generator/SYNC.md +5 -0
  1094. package/skills/refactor/LICENSE.md +21 -0
  1095. package/skills/refactor/SKILL.md +645 -0
  1096. package/skills/refactor/SYNC.md +5 -0
  1097. package/skills/refactor-method-complexity-reduce/LICENSE.md +21 -0
  1098. package/skills/refactor-method-complexity-reduce/SKILL.md +98 -0
  1099. package/skills/refactor-method-complexity-reduce/SYNC.md +5 -0
  1100. package/skills/refactor-plan/LICENSE.md +21 -0
  1101. package/skills/refactor-plan/SKILL.md +65 -0
  1102. package/skills/refactor-plan/SYNC.md +5 -0
  1103. package/skills/remember/LICENSE.md +21 -0
  1104. package/skills/remember/SKILL.md +126 -0
  1105. package/skills/remember/SYNC.md +5 -0
  1106. package/skills/remember-interactive-programming/LICENSE.md +21 -0
  1107. package/skills/remember-interactive-programming/SKILL.md +13 -0
  1108. package/skills/remember-interactive-programming/SYNC.md +5 -0
  1109. package/skills/repo-story-time/LICENSE.md +21 -0
  1110. package/skills/repo-story-time/SKILL.md +154 -0
  1111. package/skills/repo-story-time/SYNC.md +5 -0
  1112. package/skills/review-and-refactor/LICENSE.md +21 -0
  1113. package/skills/review-and-refactor/SKILL.md +15 -0
  1114. package/skills/review-and-refactor/SYNC.md +5 -0
  1115. package/skills/reviewing-oracle-to-postgres-migration/LICENSE.md +21 -0
  1116. package/skills/reviewing-oracle-to-postgres-migration/SKILL.md +67 -0
  1117. package/skills/reviewing-oracle-to-postgres-migration/SYNC.md +5 -0
  1118. package/skills/reviewing-oracle-to-postgres-migration/references/REFERENCE.md +13 -0
  1119. package/skills/reviewing-oracle-to-postgres-migration/references/empty-strings-handling.md +69 -0
  1120. package/skills/reviewing-oracle-to-postgres-migration/references/no-data-found-exceptions.md +99 -0
  1121. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-parentheses-from-clause.md +190 -0
  1122. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-sorting.md +51 -0
  1123. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-timestamp-timezone.md +187 -0
  1124. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-to-char-numeric.md +145 -0
  1125. package/skills/reviewing-oracle-to-postgres-migration/references/oracle-to-postgres-type-coercion.md +182 -0
  1126. package/skills/reviewing-oracle-to-postgres-migration/references/postgres-concurrent-transactions.md +259 -0
  1127. package/skills/reviewing-oracle-to-postgres-migration/references/postgres-refcursor-handling.md +148 -0
  1128. package/skills/ruby-mcp-server-generator/LICENSE.md +21 -0
  1129. package/skills/ruby-mcp-server-generator/SKILL.md +660 -0
  1130. package/skills/ruby-mcp-server-generator/SYNC.md +5 -0
  1131. package/skills/rust-mcp-server-generator/LICENSE.md +21 -0
  1132. package/skills/rust-mcp-server-generator/SKILL.md +577 -0
  1133. package/skills/rust-mcp-server-generator/SYNC.md +5 -0
  1134. package/skills/sandbox-npm-install/LICENSE.md +21 -0
  1135. package/skills/sandbox-npm-install/SKILL.md +80 -0
  1136. package/skills/sandbox-npm-install/SYNC.md +5 -0
  1137. package/skills/sandbox-npm-install/scripts/install.sh +193 -0
  1138. package/skills/scaffolding-oracle-to-postgres-migration-test-project/LICENSE.md +21 -0
  1139. package/skills/scaffolding-oracle-to-postgres-migration-test-project/SKILL.md +54 -0
  1140. package/skills/scaffolding-oracle-to-postgres-migration-test-project/SYNC.md +5 -0
  1141. package/skills/scoutqa-test/LICENSE.md +21 -0
  1142. package/skills/scoutqa-test/SKILL.md +375 -0
  1143. package/skills/scoutqa-test/SYNC.md +5 -0
  1144. package/skills/secret-scanning/LICENSE.md +21 -0
  1145. package/skills/secret-scanning/SKILL.md +224 -0
  1146. package/skills/secret-scanning/SYNC.md +5 -0
  1147. package/skills/secret-scanning/references/alerts-and-remediation.md +245 -0
  1148. package/skills/secret-scanning/references/custom-patterns.md +158 -0
  1149. package/skills/secret-scanning/references/push-protection.md +164 -0
  1150. package/skills/semantic-kernel/LICENSE.md +21 -0
  1151. package/skills/semantic-kernel/SKILL.md +56 -0
  1152. package/skills/semantic-kernel/SYNC.md +5 -0
  1153. package/skills/semantic-kernel/references/dotnet.md +15 -0
  1154. package/skills/semantic-kernel/references/python.md +15 -0
  1155. package/skills/shadcn/LICENSE.md +21 -0
  1156. package/skills/shadcn/SKILL.md +242 -0
  1157. package/skills/shadcn/SYNC.md +5 -0
  1158. package/skills/shadcn/agents/openai.yml +5 -0
  1159. package/skills/shadcn/assets/shadcn-small.png +0 -0
  1160. package/skills/shadcn/assets/shadcn.png +0 -0
  1161. package/skills/shadcn/cli.md +257 -0
  1162. package/skills/shadcn/customization.md +202 -0
  1163. package/skills/shadcn/evals/evals.json +47 -0
  1164. package/skills/shadcn/mcp.md +94 -0
  1165. package/skills/shadcn/rules/base-vs-radix.md +306 -0
  1166. package/skills/shadcn/rules/composition.md +195 -0
  1167. package/skills/shadcn/rules/forms.md +192 -0
  1168. package/skills/shadcn/rules/icons.md +101 -0
  1169. package/skills/shadcn/rules/styling.md +162 -0
  1170. package/skills/shuffle-json-data/LICENSE.md +21 -0
  1171. package/skills/shuffle-json-data/SKILL.md +150 -0
  1172. package/skills/shuffle-json-data/SYNC.md +5 -0
  1173. package/skills/skill-creator/LICENSE.txt +202 -0
  1174. package/skills/skill-creator/SKILL.md +485 -0
  1175. package/skills/skill-creator/SYNC.md +5 -0
  1176. package/skills/skill-creator/agents/analyzer.md +274 -0
  1177. package/skills/skill-creator/agents/comparator.md +202 -0
  1178. package/skills/skill-creator/agents/grader.md +223 -0
  1179. package/skills/skill-creator/assets/eval_review.html +146 -0
  1180. package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  1181. package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  1182. package/skills/skill-creator/references/schemas.md +430 -0
  1183. package/skills/skill-creator/scripts/__init__.py +0 -0
  1184. package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  1185. package/skills/skill-creator/scripts/generate_report.py +326 -0
  1186. package/skills/skill-creator/scripts/improve_description.py +247 -0
  1187. package/skills/skill-creator/scripts/package_skill.py +136 -0
  1188. package/skills/skill-creator/scripts/quick_validate.py +103 -0
  1189. package/skills/skill-creator/scripts/run_eval.py +310 -0
  1190. package/skills/skill-creator/scripts/run_loop.py +328 -0
  1191. package/skills/skill-creator/scripts/utils.py +47 -0
  1192. package/skills/slack-gif-creator/LICENSE.txt +202 -0
  1193. package/skills/slack-gif-creator/SKILL.md +254 -0
  1194. package/skills/slack-gif-creator/SYNC.md +5 -0
  1195. package/skills/slack-gif-creator/core/easing.py +234 -0
  1196. package/skills/slack-gif-creator/core/frame_composer.py +176 -0
  1197. package/skills/slack-gif-creator/core/gif_builder.py +269 -0
  1198. package/skills/slack-gif-creator/core/validators.py +136 -0
  1199. package/skills/slack-gif-creator/requirements.txt +4 -0
  1200. package/skills/snowflake-semanticview/LICENSE.md +21 -0
  1201. package/skills/snowflake-semanticview/SKILL.md +83 -0
  1202. package/skills/snowflake-semanticview/SYNC.md +5 -0
  1203. package/skills/sponsor-finder/LICENSE.md +21 -0
  1204. package/skills/sponsor-finder/SKILL.md +258 -0
  1205. package/skills/sponsor-finder/SYNC.md +5 -0
  1206. package/skills/spring-boot-testing/LICENSE.md +21 -0
  1207. package/skills/spring-boot-testing/SKILL.md +189 -0
  1208. package/skills/spring-boot-testing/SYNC.md +5 -0
  1209. package/skills/spring-boot-testing/references/assertj-basics.md +207 -0
  1210. package/skills/spring-boot-testing/references/assertj-collections.md +183 -0
  1211. package/skills/spring-boot-testing/references/context-caching.md +115 -0
  1212. package/skills/spring-boot-testing/references/datajpatest.md +197 -0
  1213. package/skills/spring-boot-testing/references/instancio.md +230 -0
  1214. package/skills/spring-boot-testing/references/mockitobean.md +232 -0
  1215. package/skills/spring-boot-testing/references/mockmvc-classic.md +206 -0
  1216. package/skills/spring-boot-testing/references/mockmvc-tester.md +311 -0
  1217. package/skills/spring-boot-testing/references/restclienttest.md +227 -0
  1218. package/skills/spring-boot-testing/references/resttestclient.md +278 -0
  1219. package/skills/spring-boot-testing/references/sb4-migration.md +181 -0
  1220. package/skills/spring-boot-testing/references/test-slices-overview.md +203 -0
  1221. package/skills/spring-boot-testing/references/testcontainers-jdbc.md +234 -0
  1222. package/skills/spring-boot-testing/references/webmvctest.md +177 -0
  1223. package/skills/sql-code-review/LICENSE.md +21 -0
  1224. package/skills/sql-code-review/SKILL.md +301 -0
  1225. package/skills/sql-code-review/SYNC.md +5 -0
  1226. package/skills/sql-optimization/LICENSE.md +21 -0
  1227. package/skills/sql-optimization/SKILL.md +296 -0
  1228. package/skills/sql-optimization/SYNC.md +5 -0
  1229. package/skills/structured-autonomy-generate/LICENSE.md +21 -0
  1230. package/skills/structured-autonomy-generate/SKILL.md +125 -0
  1231. package/skills/structured-autonomy-generate/SYNC.md +5 -0
  1232. package/skills/structured-autonomy-implement/LICENSE.md +21 -0
  1233. package/skills/structured-autonomy-implement/SKILL.md +19 -0
  1234. package/skills/structured-autonomy-implement/SYNC.md +5 -0
  1235. package/skills/structured-autonomy-plan/LICENSE.md +21 -0
  1236. package/skills/structured-autonomy-plan/SKILL.md +81 -0
  1237. package/skills/structured-autonomy-plan/SYNC.md +5 -0
  1238. package/skills/suggest-awesome-github-copilot-agents/LICENSE.md +21 -0
  1239. package/skills/suggest-awesome-github-copilot-agents/SKILL.md +106 -0
  1240. package/skills/suggest-awesome-github-copilot-agents/SYNC.md +5 -0
  1241. package/skills/suggest-awesome-github-copilot-instructions/LICENSE.md +21 -0
  1242. package/skills/suggest-awesome-github-copilot-instructions/SKILL.md +122 -0
  1243. package/skills/suggest-awesome-github-copilot-instructions/SYNC.md +5 -0
  1244. package/skills/suggest-awesome-github-copilot-skills/LICENSE.md +21 -0
  1245. package/skills/suggest-awesome-github-copilot-skills/SKILL.md +130 -0
  1246. package/skills/suggest-awesome-github-copilot-skills/SYNC.md +5 -0
  1247. package/skills/swift-mcp-server-generator/LICENSE.md +21 -0
  1248. package/skills/swift-mcp-server-generator/SKILL.md +669 -0
  1249. package/skills/swift-mcp-server-generator/SYNC.md +5 -0
  1250. package/skills/technology-stack-blueprint-generator/LICENSE.md +21 -0
  1251. package/skills/technology-stack-blueprint-generator/SKILL.md +242 -0
  1252. package/skills/technology-stack-blueprint-generator/SYNC.md +5 -0
  1253. package/skills/terraform-azurerm-set-diff-analyzer/LICENSE.md +21 -0
  1254. package/skills/terraform-azurerm-set-diff-analyzer/SKILL.md +48 -0
  1255. package/skills/terraform-azurerm-set-diff-analyzer/SYNC.md +5 -0
  1256. package/skills/terraform-azurerm-set-diff-analyzer/references/azurerm_set_attributes.json +154 -0
  1257. package/skills/terraform-azurerm-set-diff-analyzer/references/azurerm_set_attributes.md +145 -0
  1258. package/skills/terraform-azurerm-set-diff-analyzer/scripts/README.md +205 -0
  1259. package/skills/terraform-azurerm-set-diff-analyzer/scripts/analyze_plan.py +940 -0
  1260. package/skills/theme-factory/LICENSE.txt +202 -0
  1261. package/skills/theme-factory/SKILL.md +59 -0
  1262. package/skills/theme-factory/SYNC.md +5 -0
  1263. package/skills/theme-factory/theme-showcase.pdf +0 -0
  1264. package/skills/theme-factory/themes/arctic-frost.md +19 -0
  1265. package/skills/theme-factory/themes/botanical-garden.md +19 -0
  1266. package/skills/theme-factory/themes/desert-rose.md +19 -0
  1267. package/skills/theme-factory/themes/forest-canopy.md +19 -0
  1268. package/skills/theme-factory/themes/golden-hour.md +19 -0
  1269. package/skills/theme-factory/themes/midnight-galaxy.md +19 -0
  1270. package/skills/theme-factory/themes/modern-minimalist.md +19 -0
  1271. package/skills/theme-factory/themes/ocean-depths.md +19 -0
  1272. package/skills/theme-factory/themes/sunset-boulevard.md +19 -0
  1273. package/skills/theme-factory/themes/tech-innovation.md +19 -0
  1274. package/skills/tldr-prompt/LICENSE.md +21 -0
  1275. package/skills/tldr-prompt/SKILL.md +304 -0
  1276. package/skills/tldr-prompt/SYNC.md +5 -0
  1277. package/skills/transloadit-media-processing/LICENSE.md +21 -0
  1278. package/skills/transloadit-media-processing/SKILL.md +194 -0
  1279. package/skills/transloadit-media-processing/SYNC.md +5 -0
  1280. package/skills/typescript-mcp-server-generator/LICENSE.md +21 -0
  1281. package/skills/typescript-mcp-server-generator/SKILL.md +90 -0
  1282. package/skills/typescript-mcp-server-generator/SYNC.md +5 -0
  1283. package/skills/typespec-api-operations/LICENSE.md +21 -0
  1284. package/skills/typespec-api-operations/SKILL.md +418 -0
  1285. package/skills/typespec-api-operations/SYNC.md +5 -0
  1286. package/skills/typespec-create-agent/LICENSE.md +21 -0
  1287. package/skills/typespec-create-agent/SKILL.md +91 -0
  1288. package/skills/typespec-create-agent/SYNC.md +5 -0
  1289. package/skills/typespec-create-api-plugin/LICENSE.md +21 -0
  1290. package/skills/typespec-create-api-plugin/SKILL.md +164 -0
  1291. package/skills/typespec-create-api-plugin/SYNC.md +5 -0
  1292. package/skills/unit-test-vue-pinia/LICENSE.md +21 -0
  1293. package/skills/unit-test-vue-pinia/SKILL.md +198 -0
  1294. package/skills/unit-test-vue-pinia/SYNC.md +5 -0
  1295. package/skills/unit-test-vue-pinia/references/pinia-patterns.md +95 -0
  1296. package/skills/update-avm-modules-in-bicep/LICENSE.md +21 -0
  1297. package/skills/update-avm-modules-in-bicep/SKILL.md +60 -0
  1298. package/skills/update-avm-modules-in-bicep/SYNC.md +5 -0
  1299. package/skills/update-implementation-plan/LICENSE.md +21 -0
  1300. package/skills/update-implementation-plan/SKILL.md +157 -0
  1301. package/skills/update-implementation-plan/SYNC.md +5 -0
  1302. package/skills/update-llms/LICENSE.md +21 -0
  1303. package/skills/update-llms/SKILL.md +216 -0
  1304. package/skills/update-llms/SYNC.md +5 -0
  1305. package/skills/update-markdown-file-index/LICENSE.md +21 -0
  1306. package/skills/update-markdown-file-index/SKILL.md +76 -0
  1307. package/skills/update-markdown-file-index/SYNC.md +5 -0
  1308. package/skills/update-specification/LICENSE.md +21 -0
  1309. package/skills/update-specification/SKILL.md +127 -0
  1310. package/skills/update-specification/SYNC.md +5 -0
  1311. package/skills/vscode-ext-commands/LICENSE.md +21 -0
  1312. package/skills/vscode-ext-commands/SKILL.md +21 -0
  1313. package/skills/vscode-ext-commands/SYNC.md +5 -0
  1314. package/skills/vscode-ext-localization/LICENSE.md +21 -0
  1315. package/skills/vscode-ext-localization/SKILL.md +25 -0
  1316. package/skills/vscode-ext-localization/SYNC.md +5 -0
  1317. package/skills/vue-best-practices/SYNC.md +1 -1
  1318. package/skills/vue-jsx-best-practices/SYNC.md +1 -1
  1319. package/skills/vue-options-api-best-practices/SYNC.md +1 -1
  1320. package/skills/vue-pinia-best-practices/SYNC.md +1 -1
  1321. package/skills/vue-router-best-practices/SYNC.md +1 -1
  1322. package/skills/vue-testing-best-practices/SYNC.md +1 -1
  1323. package/skills/web-artifacts-builder/LICENSE.txt +202 -0
  1324. package/skills/web-artifacts-builder/SKILL.md +74 -0
  1325. package/skills/web-artifacts-builder/SYNC.md +5 -0
  1326. package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
  1327. package/skills/web-artifacts-builder/scripts/init-artifact.sh +322 -0
  1328. package/skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  1329. package/skills/web-coder/LICENSE.md +21 -0
  1330. package/skills/web-coder/SKILL.md +563 -0
  1331. package/skills/web-coder/SYNC.md +5 -0
  1332. package/skills/web-coder/references/accessibility.md +346 -0
  1333. package/skills/web-coder/references/architecture-patterns.md +625 -0
  1334. package/skills/web-coder/references/browsers-engines.md +358 -0
  1335. package/skills/web-coder/references/css-styling.md +696 -0
  1336. package/skills/web-coder/references/data-formats-encoding.md +411 -0
  1337. package/skills/web-coder/references/development-tools.md +502 -0
  1338. package/skills/web-coder/references/glossary.md +649 -0
  1339. package/skills/web-coder/references/html-markup.md +387 -0
  1340. package/skills/web-coder/references/http-networking.md +538 -0
  1341. package/skills/web-coder/references/javascript-programming.md +807 -0
  1342. package/skills/web-coder/references/media-graphics.md +504 -0
  1343. package/skills/web-coder/references/performance-optimization.md +546 -0
  1344. package/skills/web-coder/references/security-authentication.md +603 -0
  1345. package/skills/web-coder/references/servers-infrastructure.md +615 -0
  1346. package/skills/web-coder/references/web-apis-dom.md +654 -0
  1347. package/skills/web-coder/references/web-protocols-standards.md +265 -0
  1348. package/skills/web-design-reviewer/LICENSE.md +21 -0
  1349. package/skills/web-design-reviewer/SKILL.md +368 -0
  1350. package/skills/web-design-reviewer/SYNC.md +5 -0
  1351. package/skills/web-design-reviewer/references/framework-fixes.md +475 -0
  1352. package/skills/web-design-reviewer/references/visual-checklist.md +236 -0
  1353. package/skills/webapp-testing/LICENSE.md +21 -0
  1354. package/skills/webapp-testing/SKILL.md +133 -0
  1355. package/skills/webapp-testing/SYNC.md +5 -0
  1356. package/skills/webapp-testing/assets/test-helper.js +56 -0
  1357. package/skills/what-context-needed/LICENSE.md +21 -0
  1358. package/skills/what-context-needed/SKILL.md +39 -0
  1359. package/skills/what-context-needed/SYNC.md +5 -0
  1360. package/skills/winapp-cli/LICENSE.md +21 -0
  1361. package/skills/winapp-cli/SKILL.md +217 -0
  1362. package/skills/winapp-cli/SYNC.md +5 -0
  1363. package/skills/winmd-api-search/LICENSE.md +21 -0
  1364. package/skills/winmd-api-search/LICENSE.txt +21 -0
  1365. package/skills/winmd-api-search/SKILL.md +192 -0
  1366. package/skills/winmd-api-search/SYNC.md +5 -0
  1367. package/skills/winmd-api-search/scripts/Invoke-WinMdQuery.ps1 +505 -0
  1368. package/skills/winmd-api-search/scripts/Update-WinMdCache.ps1 +208 -0
  1369. package/skills/winmd-api-search/scripts/cache-generator/CacheGenerator.csproj +29 -0
  1370. package/skills/winmd-api-search/scripts/cache-generator/Directory.Build.props +3 -0
  1371. package/skills/winmd-api-search/scripts/cache-generator/Directory.Build.targets +3 -0
  1372. package/skills/winmd-api-search/scripts/cache-generator/Directory.Packages.props +3 -0
  1373. package/skills/winmd-api-search/scripts/cache-generator/Program.cs +1222 -0
  1374. package/skills/winui3-migration-guide/LICENSE.md +21 -0
  1375. package/skills/winui3-migration-guide/SKILL.md +277 -0
  1376. package/skills/winui3-migration-guide/SYNC.md +5 -0
  1377. package/skills/workiq-copilot/LICENSE.md +21 -0
  1378. package/skills/workiq-copilot/SKILL.md +98 -0
  1379. package/skills/workiq-copilot/SYNC.md +5 -0
  1380. package/skills/write-coding-standards-from-file/LICENSE.md +21 -0
  1381. package/skills/write-coding-standards-from-file/SKILL.md +316 -0
  1382. package/skills/write-coding-standards-from-file/SYNC.md +5 -0
  1383. package/skills/xlsx/LICENSE.txt +30 -0
  1384. package/skills/xlsx/SKILL.md +292 -0
  1385. package/skills/xlsx/SYNC.md +5 -0
  1386. package/skills/xlsx/scripts/office/helpers/__init__.py +0 -0
  1387. package/skills/xlsx/scripts/office/helpers/merge_runs.py +199 -0
  1388. package/skills/xlsx/scripts/office/helpers/simplify_redlines.py +197 -0
  1389. package/skills/xlsx/scripts/office/pack.py +159 -0
  1390. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  1391. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  1392. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  1393. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  1394. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  1395. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  1396. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  1397. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  1398. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  1399. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  1400. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  1401. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  1402. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  1403. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  1404. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  1405. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  1406. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  1407. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  1408. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  1409. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  1410. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  1411. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  1412. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  1413. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  1414. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  1415. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  1416. package/skills/xlsx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  1417. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  1418. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  1419. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  1420. package/skills/xlsx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  1421. package/skills/xlsx/scripts/office/schemas/mce/mc.xsd +75 -0
  1422. package/skills/xlsx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  1423. package/skills/xlsx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  1424. package/skills/xlsx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  1425. package/skills/xlsx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  1426. package/skills/xlsx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  1427. package/skills/xlsx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  1428. package/skills/xlsx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  1429. package/skills/xlsx/scripts/office/soffice.py +183 -0
  1430. package/skills/xlsx/scripts/office/unpack.py +132 -0
  1431. package/skills/xlsx/scripts/office/validate.py +111 -0
  1432. package/skills/xlsx/scripts/office/validators/__init__.py +15 -0
  1433. package/skills/xlsx/scripts/office/validators/base.py +847 -0
  1434. package/skills/xlsx/scripts/office/validators/docx.py +446 -0
  1435. package/skills/xlsx/scripts/office/validators/pptx.py +275 -0
  1436. package/skills/xlsx/scripts/office/validators/redlining.py +247 -0
  1437. package/skills/xlsx/scripts/recalc.py +184 -0
@@ -0,0 +1,2305 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Geofeed Tuner Report</title>
7
+ <link href="https://fonts.googleapis.com/css2?family=Raleway:wght@300;400;600;700&display=swap" rel="stylesheet">
8
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
9
+ <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
10
+ <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
11
+ <script src="https://unpkg.com/h3-js@4.1.0/dist/h3-js.umd.js"></script>
12
+ <style>
13
+ body {
14
+ background-color: #adadad;
15
+ padding: 20px;
16
+ font-family: 'Raleway', sans-serif;
17
+ }
18
+ i[class*="bi"] {
19
+ font-weight: 700;
20
+ text-shadow: 0 0 0.3px currentColor;
21
+ }
22
+ .report-container {
23
+ background-color: white;
24
+ border-radius: 15px;
25
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
26
+ padding: 30px;
27
+ margin: 0 auto 20px auto;
28
+ max-width: 1400px;
29
+ }
30
+ .metadata {
31
+ background-color: #f0f0f0;
32
+ padding: 20px;
33
+ border-radius: 5px;
34
+ margin-bottom: 30px;
35
+ }
36
+ .metadata h3 {
37
+ margin-bottom: 15px;
38
+ color: #333333;
39
+ }
40
+ .metadata-item {
41
+ display: inline-block;
42
+ margin-right: 40px;
43
+ margin-bottom: 10px;
44
+ }
45
+ .metadata-label {
46
+ font-weight: bold;
47
+ color: #696969;
48
+ }
49
+ .metadata-value {
50
+ color: #333333;
51
+ }
52
+ .status-badge {
53
+ padding: 3px 10px;
54
+ border-radius: 4px;
55
+ font-weight: bold;
56
+ font-size: 0.75em;
57
+ display: inline-flex;
58
+ align-items: center;
59
+ justify-content: center;
60
+ gap: 4px;
61
+ white-space: nowrap;
62
+ width: 150px;
63
+ }
64
+ .status-error {
65
+ background-color: #ff707f;
66
+ color: #ffffff;
67
+ border: 1px solid #ff707f;
68
+ }
69
+ .status-warning {
70
+ background-color: #ffdc73;
71
+ color: #000000;
72
+ border: 1px solid #ffdc73;
73
+ }
74
+ .status-suggestion {
75
+ background-color: #1877ec;
76
+ color: #ffffff;
77
+ border: 1px solid #1877ec;
78
+ }
79
+ .status-ok {
80
+ background-color: #28a745;
81
+ color: #ffffff;
82
+ border: 1px solid #28a745;
83
+ }
84
+ /* Checkbox styling */
85
+ input[type="checkbox"] {
86
+ width: 16px;
87
+ height: 16px;
88
+ cursor: pointer;
89
+ accent-color: #4a4a4a;
90
+ display: block;
91
+ margin: 0 auto;
92
+ }
93
+ input[type="checkbox"]:hover {
94
+ transform: scale(1.1);
95
+ }
96
+ /* Disabled checkbox with X effect */
97
+ input[type="checkbox"]:disabled {
98
+ cursor: not-allowed;
99
+ opacity: 0.6;
100
+ position: relative;
101
+ }
102
+ input[type="checkbox"]:disabled:hover {
103
+ transform: none;
104
+ }
105
+ /* Create X overlay on disabled checkbox */
106
+ .message-line input[type="checkbox"]:disabled {
107
+ appearance: none;
108
+ -webkit-appearance: none;
109
+ -moz-appearance: none;
110
+ width: 16px;
111
+ height: 16px;
112
+ border: 2px solid #dc3545;
113
+ border-radius: 3px;
114
+ background-color: #dc3545;
115
+ position: relative;
116
+ cursor: not-allowed;
117
+ }
118
+ .message-line input[type="checkbox"]:disabled::before,
119
+ .message-line input[type="checkbox"]:disabled::after {
120
+ content: '';
121
+ position: absolute;
122
+ top: 50%;
123
+ left: 50%;
124
+ width: 10px;
125
+ height: 2px;
126
+ background-color: #ffffff;
127
+ }
128
+ .message-line input[type="checkbox"]:disabled::before {
129
+ transform: translate(-50%, -50%) rotate(45deg);
130
+ }
131
+ .message-line input[type="checkbox"]:disabled::after {
132
+ transform: translate(-50%, -50%) rotate(-45deg);
133
+ }
134
+ #selectAll {
135
+ width: 17px;
136
+ height: 17px;
137
+ }
138
+ .entries-table td:first-child,
139
+ .entries-table th:first-child {
140
+ text-align: center;
141
+ vertical-align: middle;
142
+ }
143
+ .entries-table {
144
+ width: 100%;
145
+ border-collapse: collapse;
146
+ border-radius: 8px;
147
+ overflow: hidden;
148
+ table-layout: fixed;
149
+ }
150
+ .entries-table thead {
151
+ background-color: #4a4a4a;
152
+ color: white;
153
+ }
154
+ .entries-table th {
155
+ padding: 12px;
156
+ text-align: left;
157
+ border: 1px solid #d3d3d3;
158
+ font-weight: 600;
159
+ background-color: #6b6b6b;
160
+ color: #ffffff;
161
+ }
162
+ .entries-table td {
163
+ padding: 12px;
164
+ border: 1px solid #d3d3d3;
165
+ vertical-align: top;
166
+ word-wrap: break-word;
167
+ overflow-wrap: break-word;
168
+ }
169
+ .entries-table tbody tr:not(.expand-details-row) td:nth-child(3) {
170
+ text-align: center;
171
+ vertical-align: top;
172
+ }
173
+ .entries-table tbody tr:nth-child(odd) {
174
+ background-color: #f9f9f9;
175
+ }
176
+ .entries-table tbody tr:hover {
177
+ background-color: #f0f0f0;
178
+ }
179
+ .messages-list {
180
+ list-style: none;
181
+ padding: 0;
182
+ margin: 0;
183
+ }
184
+ .messages-list li {
185
+ padding: 1px 0;
186
+ border-left: 3px solid #b0b0b0;
187
+ padding-left: 10px;
188
+ color: #696969;
189
+ font-size: 0.95em;
190
+ }
191
+ h1 {
192
+ color: #ffffff;
193
+ margin-bottom: 10px;
194
+ margin-top: -30px;
195
+ margin-left: -30px;
196
+ margin-right: -30px;
197
+ border-bottom: none;
198
+ padding-bottom: 10px;
199
+ font-size: 3em;
200
+ font-weight: 700;
201
+ font-family: 'Raleway', sans-serif;
202
+ background: linear-gradient(135deg, #2a2a2a 0%, #4a4a4a 100%);
203
+ padding: 30px;
204
+ border-radius: 15px 15px 0 0;
205
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
206
+ }
207
+ .metrics-table {
208
+ width: 100%;
209
+ border-collapse: collapse;
210
+ margin: 0 auto 20px auto;
211
+ border-radius: 8px;
212
+ overflow: hidden;
213
+ }
214
+ .metrics-table td {
215
+ padding: 10px 15px;
216
+ border: 1px solid #d3d3d3;
217
+ }
218
+ .metrics-table tr:nth-child(even) {
219
+ background-color: #f9f9f9;
220
+ }
221
+ .metrics-label {
222
+ font-weight: bold;
223
+ width: 30%;
224
+ background-color: #f0f0f0;
225
+ }
226
+ .metrics-value {
227
+ width: 70%;
228
+ color: #333333;
229
+ }
230
+ .metrics-table.feed-metadata .metrics-label {
231
+ width: 20%;
232
+ }
233
+ .metrics-table.feed-metadata .metrics-value {
234
+ width: 80%;
235
+ }
236
+ .accuracy-summary-table td {
237
+ width: auto !important;
238
+ }
239
+ .accuracy-summary-table .metrics-label {
240
+ width: 15% !important;
241
+ }
242
+ .accuracy-summary-table .metrics-value {
243
+ width: 35% !important;
244
+ }
245
+ #filterCountry, #filterRegion, #filterCity, #filterStatus, #filterIpPrefix {
246
+ box-sizing: border-box;
247
+ font-family: 'Raleway', sans-serif;
248
+ }
249
+ #filterCountry::placeholder, #filterRegion::placeholder, #filterCity::placeholder, #filterIpPrefix::placeholder {
250
+ color: #aaa;
251
+ }
252
+ #resetFilters:hover, #toggleFilters:hover, #toggleExpandAll:hover, #downloadCSV:hover {
253
+ background-color: #6a6a6a;
254
+ border-color: #aaa;
255
+ }
256
+ .expand-details-row {
257
+ display: none;
258
+ }
259
+ .expand-details-row.show {
260
+ display: table-row;
261
+ }
262
+ .expand-details-row td {
263
+ border-left: none;
264
+ border-right: none;
265
+ }
266
+ .expand-details-row td:first-child {
267
+ border-left: 1px solid #d3d3d3;
268
+ padding: 0;
269
+ }
270
+ .expand-details-row td:nth-child(2) {
271
+ padding: 0;
272
+ }
273
+ .expand-details-row td:last-child {
274
+ border-right: 1px solid #d3d3d3;
275
+ }
276
+ .previous-values-row td {
277
+ background-color: #f0f0f0;
278
+ font-style: italic;
279
+ color: #555;
280
+ padding: 8px 12px;
281
+ border-top: 1px solid #d3d3d3;
282
+ border-bottom: 1px solid #d3d3d3;
283
+ }
284
+ .previous-values-row td:first-child {
285
+ border-left: 1px solid #d3d3d3;
286
+ }
287
+ .previous-values-row td:last-child {
288
+ border-right: 1px solid #d3d3d3;
289
+ }
290
+ .issues-row td {
291
+ border-top: 1px solid #d3d3d3;
292
+ border-bottom: 1px solid #d3d3d3;
293
+ }
294
+ .expandable-row {
295
+ cursor: pointer;
296
+ }
297
+ .expandable-row:focus {
298
+ outline: 2px solid #4a9eff;
299
+ outline-offset: -2px;
300
+ }
301
+ .tune-all-btn {
302
+ display: none;
303
+ padding: 3px 8px;
304
+ border: 1px solid #888;
305
+ border-radius: 3px;
306
+ background-color: #5a5a5a;
307
+ color: #ffffff;
308
+ cursor: pointer;
309
+ font-weight: 600;
310
+ font-size: 0.8em;
311
+ }
312
+ body.tuning-mode .tune-all-btn {
313
+ display: inline;
314
+ }
315
+ .issues-header {
316
+ display: flex;
317
+ justify-content: space-between;
318
+ align-items: center;
319
+ }
320
+ .message-line {
321
+ display: flex;
322
+ justify-content: space-between;
323
+ align-items: center;
324
+ margin: 5px 0;
325
+ }
326
+ .message-line input[type="checkbox"] {
327
+ display: none;
328
+ }
329
+ body.tuning-mode .message-line input[type="checkbox"] {
330
+ display: inline-block;
331
+ }
332
+ .message-line span {
333
+ flex: 1;
334
+ font-size: 0.98em;
335
+ }
336
+ .modal {
337
+ display: none;
338
+ position: fixed;
339
+ z-index: 1000;
340
+ left: 0;
341
+ top: 0;
342
+ width: 100%;
343
+ height: 100%;
344
+ background-color: rgba(0, 0, 0, 0.6);
345
+ }
346
+ .modal-content {
347
+ background-color: #ffffff;
348
+ margin: 50px auto;
349
+ padding: 0;
350
+ border: none;
351
+ width: 90%;
352
+ max-width: 1200px;
353
+ border-radius: 15px;
354
+ max-height: 90vh;
355
+ overflow: hidden;
356
+ box-shadow: 0 4px 20px rgba(0,0,0,0.3);
357
+ display: flex;
358
+ flex-direction: column;
359
+ }
360
+ .modal-content h2 {
361
+ background-color: #4a4a4a;
362
+ color: #ffffff;
363
+ padding: 20px 25px;
364
+ margin: 0;
365
+ font-size: 1.3em;
366
+ font-weight: bold;
367
+ font-family: 'Raleway', sans-serif;
368
+ border-radius: 15px 15px 0 0;
369
+ position: relative;
370
+ }
371
+ .close {
372
+ color: #ffffff;
373
+ position: absolute;
374
+ right: 20px;
375
+ top: 50%;
376
+ transform: translateY(-50%);
377
+ font-size: 32px;
378
+ font-weight: bold;
379
+ cursor: pointer;
380
+ line-height: 1;
381
+ transition: color 0.2s;
382
+ }
383
+ .close:hover,
384
+ .close:focus {
385
+ color: #ddd;
386
+ }
387
+ .matches-container {
388
+ margin-top: 0;
389
+ padding: 25px;
390
+ display: flex;
391
+ flex-wrap: nowrap;
392
+ gap: 15px;
393
+ justify-content: center;
394
+ overflow-x: auto;
395
+ background-color: #f5f5f5;
396
+ flex: 1;
397
+ overflow-y: auto;
398
+ }
399
+ .match-item {
400
+ flex: 1 1 0;
401
+ max-width: 350px;
402
+ min-width: 280px;
403
+ border: 2px solid #c0c0c0;
404
+ border-radius: 8px;
405
+ padding: 0;
406
+ background-color: white;
407
+ box-shadow: 0 2px 8px rgba(0,0,0,0.15);
408
+ cursor: pointer;
409
+ transition: all 0.2s;
410
+ overflow: hidden;
411
+ }
412
+ .match-item:hover {
413
+ box-shadow: 0 4px 12px rgba(0,0,0,0.25);
414
+ border-color: #4a9eff;
415
+ transform: translateY(-2px);
416
+ }
417
+ .match-item:active {
418
+ transform: translateY(0);
419
+ }
420
+ .match-item.selected {
421
+ border-color: #4a9eff;
422
+ border-width: 3px;
423
+ box-shadow: 0 0 15px rgba(74, 158, 255, 0.6);
424
+ }
425
+ .match-map {
426
+ height: 180px;
427
+ width: 100%;
428
+ margin: 0;
429
+ border: none;
430
+ border-radius: 0;
431
+ }
432
+ .match-info-container {
433
+ display: flex;
434
+ flex-direction: column;
435
+ gap: 6px;
436
+ padding: 12px;
437
+ background-color: #f0f0f0;
438
+ }
439
+ .match-header {
440
+ font-size: 22px;
441
+ font-weight: bold;
442
+ color: #333;
443
+ text-align: left;
444
+ font-family: 'Raleway', sans-serif;
445
+ line-height: 1.2;
446
+ }
447
+ .location-details {
448
+ font-size: 15px;
449
+ color: #666;
450
+ display: inline;
451
+ }
452
+ .location-details span {
453
+ margin-right: 15px;
454
+ }
455
+ .default-values {
456
+ display: none;
457
+ padding: 5px 0;
458
+ font-size: 13px;
459
+ margin-bottom: 10px;
460
+ }
461
+ .default-values.show {
462
+ display: block;
463
+ }
464
+ .mode-toggle-container {
465
+ display: flex;
466
+ align-items: center;
467
+ gap: 10px;
468
+ font-size: 0.72em;
469
+ }
470
+ .mode-toggle {
471
+ position: relative;
472
+ width: 240px;
473
+ height: 32px;
474
+ background-color: #888;
475
+ border-radius: 16px;
476
+ cursor: pointer;
477
+ transition: background-color 0.3s;
478
+ display: flex;
479
+ align-items: center;
480
+ justify-content: space-between;
481
+ padding: 0 8px;
482
+ }
483
+ .mode-toggle:focus {
484
+ outline: 2px solid #4a9eff;
485
+ outline-offset: 2px;
486
+ }
487
+ .mode-toggle-text {
488
+ font-size: 0.85em;
489
+ font-weight: 600;
490
+ color: #cccccc;
491
+ z-index: 1;
492
+ transition: color 0.3s;
493
+ flex: 1;
494
+ text-align: center;
495
+ }
496
+ .mode-toggle-text.active {
497
+ color: #333333;
498
+ }
499
+ .mode-toggle-slider {
500
+ position: absolute;
501
+ top: 3px;
502
+ left: 3px;
503
+ width: 116px;
504
+ height: 26px;
505
+ background-color: #ffffff;
506
+ border-radius: 13px;
507
+ transition: transform 0.3s;
508
+ box-shadow: 0 2px 4px rgba(0,0,0,0.2);
509
+ }
510
+ .mode-toggle.tuning .mode-toggle-slider {
511
+ transform: translateX(118px);
512
+ }
513
+ .mode-toggle.h3mode .mode-toggle-slider {
514
+ transform: translateX(96px);
515
+ }
516
+ .mode-toggle-label {
517
+ font-weight: 600;
518
+ color: #ffffff;
519
+ font-size: 0.9em;
520
+ }
521
+
522
+ /* Keyboard accessibility focus styles */
523
+ button:focus {
524
+ outline: 2px solid #4a9eff;
525
+ outline-offset: 2px;
526
+ }
527
+ input[type="text"]:focus,
528
+ select:focus {
529
+ outline: 2px solid #4a9eff;
530
+ outline-offset: 1px;
531
+ }
532
+ input[type="checkbox"]:focus {
533
+ outline: 2px solid #4a9eff;
534
+ outline-offset: 2px;
535
+ }
536
+ /* Pagination styles */
537
+ .pagination-container {
538
+ display: flex;
539
+ justify-content: space-between;
540
+ align-items: center;
541
+ margin-top: 20px;
542
+ padding: 15px 20px;
543
+ background-color: #f5f5f5;
544
+ border-radius: 8px;
545
+ flex-wrap: wrap;
546
+ gap: 15px;
547
+ }
548
+ .pagination-info {
549
+ color: #333333;
550
+ font-size: 0.95em;
551
+ }
552
+ .pagination-controls {
553
+ display: flex;
554
+ gap: 5px;
555
+ align-items: center;
556
+ }
557
+ .pagination-btn {
558
+ padding: 6px 12px;
559
+ border: 1px solid #888;
560
+ border-radius: 4px;
561
+ background-color: #5a5a5a;
562
+ color: #ffffff;
563
+ cursor: pointer;
564
+ font-weight: 600;
565
+ font-size: 0.9em;
566
+ transition: background-color 0.2s;
567
+ }
568
+ .pagination-btn:hover:not(:disabled) {
569
+ background-color: #4a4a4a;
570
+ }
571
+ .pagination-btn:disabled {
572
+ background-color: #888;
573
+ cursor: not-allowed;
574
+ opacity: 0.5;
575
+ }
576
+ .pagination-btn.active {
577
+ background-color: #1877ec;
578
+ border-color: #1877ec;
579
+ }
580
+ .page-size-selector {
581
+ display: flex;
582
+ align-items: center;
583
+ gap: 8px;
584
+ }
585
+ .page-size-selector select {
586
+ padding: 5px 10px;
587
+ border: 1px solid #888;
588
+ border-radius: 4px;
589
+ background-color: #5a5a5a;
590
+ color: #ffffff;
591
+ font-size: 0.9em;
592
+ cursor: pointer;
593
+ }
594
+ /* Helper classes for common inline styles */
595
+ .table-header {
596
+ background-color: #6b6b6b;
597
+ padding: 12px 15px;
598
+ font-weight: bold;
599
+ color: #ffffff;
600
+ font-size: 1.1em;
601
+ font-family: 'Raleway', sans-serif;
602
+ }
603
+ .icon-spacer {
604
+ margin-right: 8px;
605
+ }
606
+ .flex-container {
607
+ display: flex;
608
+ justify-content: space-between;
609
+ align-items: center;
610
+ }
611
+ .action-button {
612
+ padding: 5px 11px;
613
+ border: 1px solid #888;
614
+ border-radius: 3px;
615
+ background-color: #5a5a5a;
616
+ color: #ffffff;
617
+ cursor: pointer;
618
+ font-weight: 600;
619
+ font-size: 0.9em;
620
+ }
621
+ .action-button:hover {
622
+ background-color: #6a6a6a;
623
+ }
624
+ .subtitle-span {
625
+ font-size: 0.4em;
626
+ font-weight: 700;
627
+ display: block;
628
+ margin-top: 10px;
629
+ }
630
+ </style>
631
+ </head>
632
+ <body>
633
+ <div class="report-container">
634
+ <h1>Geofeed Tuner Report<br><span style="font-size: 0.4em; font-weight: 700; display: block; margin-top: 10px;">RFC 8805 Validation & Recommendations</span></h1>
635
+
636
+ <table class="metrics-table feed-metadata" style="margin-top: 30px; margin-bottom: 30px;">
637
+ <tr style="background-color: #6b6b6b;">
638
+ <td colspan="2" style="padding: 12px 15px; font-weight: bold; color: #ffffff; font-size: 1.1em; font-family: 'Raleway', sans-serif;">Feed Metadata</td>
639
+ </tr>
640
+ <tr>
641
+ <td class="metrics-label"><i class="bi bi-filetype-csv" style="margin-right: 8px;"></i>Input file</td>
642
+ <td class="metrics-value"><span id="inputFileMetrics">{{.Metadata.InputFile}}</span></td>
643
+ </tr>
644
+ <tr>
645
+ <td class="metrics-label"><i class="bi bi-calendar-event-fill" style="margin-right: 8px;"></i>Tuning timestamp</td>
646
+ <td class="metrics-value"><script>document.write(new Intl.DateTimeFormat("en", {dateStyle: "full", timeStyle: "long",}).format(new Date({{.Metadata.Timestamp}})))</script></td>
647
+ </tr>
648
+ </table>
649
+
650
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;">
651
+ <table class="metrics-table">
652
+ <tr style="background-color: #6b6b6b;">
653
+ <td colspan="2" style="padding: 12px 15px; font-weight: bold; color: #ffffff; font-size: 1.1em; font-family: 'Raleway', sans-serif;">Entries</td>
654
+ </tr>
655
+ <tr>
656
+ <td class="metrics-label"><i class="bi bi-list-ul" style="margin-right: 8px;"></i>Total entries</td>
657
+ <td class="metrics-value"><span id="totalEntriesMetrics">{{.Metadata.TotalEntries}}</span></td>
658
+ </tr>
659
+ <tr>
660
+ <td class="metrics-label"><i class="bi bi-diagram-3-fill" style="margin-right: 8px;"></i>IPv4 entries</td>
661
+ <td class="metrics-value"><span id="ipv4EntriesMetrics">{{.Metadata.IpV4Entries}}</span></td>
662
+ </tr>
663
+ <tr>
664
+ <td class="metrics-label"><i class="bi bi-diagram-3-fill" style="margin-right: 8px;"></i>IPv6 entries</td>
665
+ <td class="metrics-value"><span id="ipv6EntriesMetrics">{{.Metadata.IpV6Entries}}</span></td>
666
+ </tr>
667
+ <tr>
668
+ <td class="metrics-label"><i class="bi bi-exclamation-circle-fill" style="margin-right: 8px;"></i>Invalid entries</td>
669
+ <td class="metrics-value"><span id="invalidEntriesMetrics">{{.Metadata.InvalidEntries}}</span></td>
670
+ </tr>
671
+ </table>
672
+
673
+ <table class="metrics-table">
674
+ <tr style="background-color: #6b6b6b;">
675
+ <td colspan="2" style="padding: 12px 15px; font-weight: bold; color: #ffffff; font-size: 1.1em; font-family: 'Raleway', sans-serif;">Analysis Summary</td>
676
+ </tr>
677
+ <tr>
678
+ <td class="metrics-label"><i class="bi bi-x-circle-fill" style="margin-right: 8px;"></i>Errors</td>
679
+ <td class="metrics-value"><span id="errorCountMetrics">{{.Metadata.Errors}}</span></td>
680
+ </tr>
681
+ <tr>
682
+ <td class="metrics-label"><i class="bi bi-exclamation-triangle-fill" style="margin-right: 8px;"></i>Warnings</td>
683
+ <td class="metrics-value"><span id="warningCountMetrics">{{.Metadata.Warnings}}</span></td>
684
+ </tr>
685
+ <tr>
686
+ <td class="metrics-label"><i class="bi bi-lightbulb-fill" style="margin-right: 8px;"></i>Suggestions</td>
687
+ <td class="metrics-value"><span id="suggestionsMetrics">{{.Metadata.Suggestions}}</span></td>
688
+ </tr>
689
+ <tr>
690
+ <td class="metrics-label"><i class="bi bi-check-circle-fill" style="margin-right: 8px;"></i>OK </td>
691
+ <td class="metrics-value"><span id="okCountMetrics">{{.Metadata.OK}}</span></td>
692
+ </tr>
693
+ </table>
694
+ </div>
695
+
696
+ <div style="margin-bottom: 40px;">
697
+ <table class="metrics-table accuracy-summary-table" style="margin-top: 0; margin-bottom: 0; table-layout: fixed; width: 100%;">
698
+ <colgroup>
699
+ <col style="width: 20%;">
700
+ <col style="width: 30%;">
701
+ <col style="width: 20%;">
702
+ <col style="width: 30%;">
703
+ </colgroup>
704
+ <tr style="background-color: #6b6b6b;">
705
+ <td colspan="4" style="padding: 12px 15px; font-weight: bold; color: #ffffff; font-size: 1.1em; font-family: 'Raleway', sans-serif;">Accuracy Summary</td>
706
+ </tr>
707
+ <tr>
708
+ <td class="metrics-label"><i class="bi bi-building-fill" style="margin-right: 8px;"></i>City-level accuracy</td>
709
+ <td class="metrics-value"><span id="cityAccuracy">{{.Metadata.CityLevelAccuracy}}</span></td>
710
+ <td class="metrics-label"><i class="bi bi-map-fill" style="margin-right: 8px;"></i>Region-level accuracy</td>
711
+ <td class="metrics-value"><span id="regionAccuracy">{{.Metadata.RegionLevelAccuracy}}</span></td>
712
+ </tr>
713
+ <tr>
714
+ <td class="metrics-label"><i class="bi bi-globe-americas" style="margin-right: 8px;"></i>Country-level accuracy</td>
715
+ <td class="metrics-value"><span id="countryAccuracy">{{.Metadata.CountryLevelAccuracy}}</span></td>
716
+ <td class="metrics-label"><i class="bi bi-ban-fill" style="margin-right: 8px;"></i>Do-not-geolocate entries</td>
717
+ <td class="metrics-value"><span id="doNotGeolocate">{{.Metadata.DoNotGeolocate}}</span></td>
718
+ </tr>
719
+ </table>
720
+ </div>
721
+
722
+ <div style="overflow-x: auto;">
723
+ <table class="entries-table">
724
+ <colgroup>
725
+ <col style="width: 3%;">
726
+ <col style="width: 5%;">
727
+ <col style="width: 20%;">
728
+ <col style="width: 24%;">
729
+ <col style="width: 10%;">
730
+ <col style="width: 19%;">
731
+ <col style="width: 19%;">
732
+ </colgroup>
733
+ <thead>
734
+ <tr style="background-color: #4a4a4a;">
735
+ <th colspan="7" style="padding: 12px; font-weight: bold; color: #ffffff; font-size: 1.3em; font-family: 'Raleway', sans-serif;">
736
+ <div style="display: flex; justify-content: space-between; align-items: center;">
737
+ <span><i class="bi bi-list-ul" style="margin-right: 10px;"></i>Entries</span>
738
+ <div class="mode-toggle-container">
739
+ <div class="mode-toggle" id="modeToggle" onclick="toggleMode()" tabindex="0" onkeydown="if(event.key === 'Enter' || event.key === ' ') { event.preventDefault(); toggleMode(); }">
740
+ <span class="mode-toggle-text active" id="viewingText">Viewing Mode</span>
741
+ <div class="mode-toggle-slider"></div>
742
+ <span class="mode-toggle-text" id="tuningText">Tuning Mode</span>
743
+ </div>
744
+ </div>
745
+ </div>
746
+ </th>
747
+ </tr>
748
+ <tr>
749
+ <th colspan="7" style="background-color: #6b6b6b; padding: 8px;">
750
+ <div style="display: flex; justify-content: space-between; gap: 5px;">
751
+ <div style="display: flex; gap: 5px;">
752
+ <button id="toggleFilters" style="padding: 5px 11px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; cursor: pointer; font-weight: 600; font-size: 0.9em; width: 130px;">
753
+ <i class="bi bi-funnel-fill" style="margin-right: 5px;"></i>Show Filters
754
+ </button>
755
+ <button id="toggleExpandAll" style="padding: 5px 11px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; cursor: pointer; font-weight: 600; font-size: 0.9em; width: 145px;">
756
+ <i class="bi bi-arrows-expand" style="margin-right: 5px;"></i>Expand Rows
757
+ </button>
758
+ <button id="tuneAll" class="tune-all-btn" style="padding: 5px 11px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; cursor: pointer; font-weight: 600; font-size: 0.9em;">
759
+ <i class="bi bi-wrench" style="margin-right: 5px;"></i>Tune All
760
+ </button>
761
+ </div>
762
+ <button id="downloadCSV" style="padding: 5px 11px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; cursor: pointer; font-weight: 600; font-size: 0.9em;">
763
+ <i class="bi bi-filetype-csv" style="margin-right: 5px;"></i>Download
764
+ </button>
765
+ </div>
766
+ </th>
767
+ </tr>
768
+ <tr>
769
+ <th><input type="checkbox" id="selectAll" checked></th>
770
+ <th>Line</th>
771
+ <th>Status</th>
772
+ <th>IP Prefix</th>
773
+ <th>Country</th>
774
+ <th>Region</th>
775
+ <th>City</th>
776
+ </tr>
777
+ <tr id="filterRow" style="background-color: #6b6b6b; display: none;">
778
+ <th colspan="2" style="padding: 8px;">
779
+ <button id="resetFilters" style="padding: 5px 11px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; cursor: pointer; font-weight: 600; font-size: 0.9em; width: 100%;">Reset</button>
780
+ </th>
781
+ <th style="padding: 8px;">
782
+ <select id="filterStatus" style="padding: 5px 9px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; font-size: 0.9em; width: 100%;">
783
+ <option value="">All</option>
784
+ <option value="ERROR">ERROR</option>
785
+ <option value="WARNING">WARNING</option>
786
+ <option value="SUGGESTION">SUGGESTION</option>
787
+ <option value="OK">OK</option>
788
+ </select>
789
+ </th>
790
+ <th style="padding: 8px;">
791
+ <input type="text" id="filterIpPrefix" placeholder="IP Prefix" style="padding: 5px 9px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; font-size: 0.9em; width: 100%; box-sizing: border-box;">
792
+ </th>
793
+ <th style="padding: 8px;">
794
+ <input type="text" id="filterCountry" placeholder="Country" style="padding: 5px 9px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; font-size: 0.9em; width: 100%; box-sizing: border-box;">
795
+ </th>
796
+ <th style="padding: 8px;">
797
+ <input type="text" id="filterRegion" placeholder="Region" style="padding: 5px 9px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; font-size: 0.9em; width: 100%; box-sizing: border-box;">
798
+ </th>
799
+ <th style="padding: 8px;">
800
+ <input type="text" id="filterCity" placeholder="City" style="padding: 5px 9px; border: 1px solid #888; border-radius: 3px; background-color: #5a5a5a; color: #ffffff; font-size: 0.9em; width: 100%; box-sizing: border-box;">
801
+ </th>
802
+ </tr>
803
+ </thead>
804
+ <tbody id="entriesTableBody">
805
+ {{range .Entries}}
806
+ <tr
807
+ id="csv-r-{{.Line}}"
808
+ class="expandable-row"
809
+ data-geocoding-hint="{{.GeocodingHint}}"
810
+ data-do-not-geolocate="{{.DoNotGeolocate}}"
811
+ data-has-warning="{{.HasWarning}}"
812
+ data-has-error="{{.HasError}}"
813
+ data-has-suggestion="{{.HasSuggestion}}"
814
+ data-tunable="{{.Tunable}}"
815
+ data-tuned-country="{{.TunedEntry.CountryCode}}"
816
+ data-tuned-region="{{.TunedEntry.RegionCode}}"
817
+ data-tuned-city="{{.TunedEntry.Name}}"
818
+ data-h3-cells="{{.TunedEntry.H3Cells}}"
819
+ data-bounding-box="{{.TunedEntry.BoundingBox}}">
820
+ <td><input type="checkbox" class="row-checkbox" checked></td>
821
+ <td>{{.Line}}</td>
822
+ <td><span class="status-badge status-{{if eq .Status "ERROR"}}error{{else if eq .Status "WARNING"}}warning{{else if eq .Status "SUGGESTION"}}suggestion{{else}}ok{{end}}"><i class="bi {{if eq .Status "ERROR"}}bi-x-circle-fill{{else if eq .Status "WARNING"}}bi-exclamation-triangle-fill{{else if eq .Status "SUGGESTION"}}bi-lightbulb-fill{{else}}bi-check-circle-fill{{end}}"></i>{{.Status}}</span></td>
823
+ <td><strong>{{.IPPrefix}}</strong></td>
824
+ <td>{{.CountryCode}}</td>
825
+ <td>{{.RegionCode}}</td>
826
+ <td>{{.City}}</td>
827
+ </tr>
828
+ <tr class="expand-details-row previous-values-row">
829
+ <td></td>
830
+ <td></td>
831
+ <td></td>
832
+ <td><strong>Previous values:</strong></td>
833
+ <td class="previous-value"><span class="default-country">{{.CountryCode}}</span></td>
834
+ <td class="previous-value"><span class="default-region">{{.RegionCode}}</span></td>
835
+ <td class="previous-value"><span class="default-city">{{.City}}</span></td>
836
+ </tr>
837
+ <tr class="expand-details-row issues-row">
838
+ <td></td>
839
+ <td></td>
840
+ <td colspan="5">
841
+ <div class="issues-header">
842
+ <strong>Issues:</strong>
843
+ {{if .Tunable}}
844
+ <button class="tune-all-btn" onclick="handleTuneButtonClick(this)">Tune</button>
845
+ {{end}}
846
+ </div>
847
+ {{range .Messages}}
848
+ <div class="message-line" data-id="{{.ID}}">
849
+ <span>{{.Text}}</span>
850
+ <input type="checkbox"{{if .Checked}} checked{{else}} disabled{{end}}>
851
+ </div>
852
+ {{end}}
853
+ </td>
854
+ </tr>
855
+ {{end}}
856
+ </tbody>
857
+ </table>
858
+
859
+ <!-- Pagination Controls -->
860
+ <div class="pagination-container">
861
+ <div class="pagination-info">
862
+ <span id="paginationInfo">Showing 0-0 of 0 rows</span>
863
+ </div>
864
+ <div class="pagination-controls">
865
+ <button class="pagination-btn" id="firstPage" title="First Page">
866
+ <i class="bi bi-chevron-bar-left"></i>
867
+ </button>
868
+ <button class="pagination-btn" id="prevPage" title="Previous Page">
869
+ <i class="bi bi-chevron-left"></i>
870
+ </button>
871
+ <div id="pageNumbers" style="display: flex; gap: 5px;"></div>
872
+ <button class="pagination-btn" id="nextPage" title="Next Page">
873
+ <i class="bi bi-chevron-right"></i>
874
+ </button>
875
+ <button class="pagination-btn" id="lastPage" title="Last Page">
876
+ <i class="bi bi-chevron-bar-right"></i>
877
+ </button>
878
+ </div>
879
+ <div class="page-size-selector">
880
+ <label for="pageSize" style="color: #333333; font-size: 0.9em;">Rows per page:</label>
881
+ <select id="pageSize">
882
+ <option value="100" selected>100</option>
883
+ <option value="all">All</option>
884
+ </select>
885
+ </div>
886
+ </div>
887
+ </div>
888
+
889
+ <div style="margin-top: 30px;">
890
+ <table class="metrics-table" style="margin-bottom: 0; width: 100%; border-bottom-left-radius: 0; border-bottom-right-radius: 0;">
891
+ <tr style="background-color: #6b6b6b;">
892
+ <td style="padding: 12px 15px; font-weight: bold; color: #ffffff; font-size: 1.1em; font-family: 'Raleway', sans-serif;">
893
+ <div style="display: flex; justify-content: space-between; align-items: center;">
894
+ <span><i class="bi bi-map-fill" style="margin-right: 10px;"></i>Geographic Coverage Map</span>
895
+ <div class="mode-toggle-container" style="font-size: 1em;">
896
+ <div class="mode-toggle" id="mapModeToggle" onclick="switchMapMode()" tabindex="0" onkeydown="if(event.key==='Enter'||event.key===' '){event.preventDefault();switchMapMode();}" style="width: 170px;">
897
+ <span class="mode-toggle-text active" id="mapModeBboxText">BBox</span>
898
+ <div class="mode-toggle-slider" style="width: 81px;"></div>
899
+ <span class="mode-toggle-text" id="mapModeH3Text">H3 Cells</span>
900
+ </div>
901
+ </div>
902
+ </div>
903
+ </td>
904
+ </tr>
905
+ </table>
906
+ <div id="summaryMap" style="height: 480px; border: 1px solid #bbb; border-top: none; border-radius: 0 0 4px 4px;"></div>
907
+ </div>
908
+ </div>
909
+
910
+
911
+ <div id="locationModal" class="modal" tabindex="-1">
912
+ <div class="modal-content" tabindex="0">
913
+ <h2>
914
+ <i class="bi bi-geo-alt" style="margin-right: 10px;"></i>Location Matches
915
+ <span class="close" tabindex="0">&times;</span>
916
+ </h2>
917
+ <div id="matchesList" class="matches-container"></div>
918
+ </div>
919
+ </div>
920
+
921
+ <script>
922
+ /**
923
+ * Table cell indices for accessing column data
924
+ * @type {Object<string, number>}
925
+ */
926
+ // Constants
927
+ const CELL_INDEX = {
928
+ CHECKBOX: 0,
929
+ LINE: 1,
930
+ STATUS: 2,
931
+ IP_PREFIX: 3,
932
+ COUNTRY: 4,
933
+ REGION: 5,
934
+ CITY: 6,
935
+ MESSAGES: 7
936
+ };
937
+
938
+ /**
939
+ * Timing delays for UI interactions (in milliseconds)
940
+ * @type {Object<string, number>}
941
+ */
942
+ const TIMING = {
943
+ MAP_INIT_DELAY: 100,
944
+ MODAL_FOCUS_DELAY: 150,
945
+ MAP_RESIZE_DELAY: 200
946
+ };
947
+
948
+ /**
949
+ * Global state variables for modal and map management
950
+ * @type {Object}
951
+ */
952
+ // Global state
953
+ /** @type {Object<string, L.Map>} Maps indexed by mapId */
954
+ let maps = {};
955
+
956
+ /** @type {HTMLButtonElement|null} Currently active tune button reference */
957
+ let currentTuningButton = null;
958
+
959
+ /** @type {number} Currently selected match index in modal */
960
+ let selectedMatchIndex = 0;
961
+
962
+ /** @type {Array<HTMLElement>} Array of match item elements in modal */
963
+ let matchItems = [];
964
+
965
+ /** @type {boolean} Flag indicating if modal is currently open */
966
+ let isModalOpen = false;
967
+
968
+
969
+ let summaryMapInstance = null;
970
+ let summaryLayerGroup = null;
971
+ let currentMapMode = 'bbox';
972
+ let summaryRowData = [];
973
+
974
+ /**
975
+ * Stores CSV comment lines by line number for download functionality
976
+ * @type {Object<number, string>}
977
+ */
978
+ // Comment map: stores CSV comments by line number
979
+ const commentMap = {{.Comments}};
980
+
981
+ // Modal elements
982
+ const modal = document.getElementById('locationModal');
983
+ const modalContent = document.querySelector('.modal-content');
984
+ const closeBtn = document.querySelector('.close');
985
+
986
+ // Modal functions
987
+ closeBtn.onclick = function() {
988
+ closeModal();
989
+ };
990
+
991
+ closeBtn.addEventListener('keydown', function(e) {
992
+ if (e.key === 'Enter' || e.key === ' ') {
993
+ e.preventDefault();
994
+ closeModal();
995
+ }
996
+ });
997
+
998
+ window.onclick = function(event) {
999
+ if (event.target == modal) {
1000
+ closeModal();
1001
+ }
1002
+ };
1003
+
1004
+ /**
1005
+ * Closes the location matches modal and cleans up resources
1006
+ * @returns {void}
1007
+ */
1008
+ function closeModal() {
1009
+ if (!isModalOpen) return;
1010
+
1011
+ modal.style.display = 'none';
1012
+ isModalOpen = false;
1013
+ currentTuningButton = null;
1014
+ document.body.style.overflow = '';
1015
+
1016
+ Object.values(maps).forEach(map => {
1017
+ if (map && map.remove) {
1018
+ map.remove();
1019
+ }
1020
+ });
1021
+ maps = {};
1022
+ matchItems = [];
1023
+ }
1024
+
1025
+ // Modal keyboard navigation
1026
+ modal.addEventListener('keydown', function(event) {
1027
+ if (!isModalOpen) return;
1028
+
1029
+ if (event.key === 'Escape' || event.key === 'Esc') {
1030
+ event.preventDefault();
1031
+ closeModal();
1032
+ return;
1033
+ }
1034
+
1035
+ if (event.key === 'Enter') {
1036
+ event.preventDefault();
1037
+ if (matchItems[selectedMatchIndex]) {
1038
+ matchItems[selectedMatchIndex].click();
1039
+ }
1040
+ return;
1041
+ }
1042
+
1043
+ if (event.key === 'ArrowLeft' || event.key === 'ArrowUp') {
1044
+ event.preventDefault();
1045
+ navigateMatches(-1);
1046
+ return;
1047
+ }
1048
+
1049
+ if (event.key === 'ArrowRight' || event.key === 'ArrowDown') {
1050
+ event.preventDefault();
1051
+ navigateMatches(1);
1052
+ return;
1053
+ }
1054
+
1055
+ if (event.key === '+' || event.key === '=') {
1056
+ event.preventDefault();
1057
+ zoomCurrentMap(1);
1058
+ return;
1059
+ }
1060
+
1061
+ if (event.key === '-' || event.key === '_') {
1062
+ event.preventDefault();
1063
+ zoomCurrentMap(-1);
1064
+ return;
1065
+ }
1066
+ });
1067
+
1068
+ document.addEventListener('keydown', function(event) {
1069
+ if ((event.key === 'Escape' || event.key === 'Esc') && isModalOpen) {
1070
+ event.preventDefault();
1071
+ closeModal();
1072
+ }
1073
+ });
1074
+
1075
+ /**
1076
+ * Navigates between location match items with arrow keys
1077
+ * @param {number} direction - Navigate direction: positive (right/down) or negative (left/up)
1078
+ * @returns {void}
1079
+ */
1080
+ function navigateMatches(direction) {
1081
+ if (matchItems.length === 0) return;
1082
+
1083
+ if (matchItems[selectedMatchIndex]) {
1084
+ matchItems[selectedMatchIndex].classList.remove('selected');
1085
+ }
1086
+
1087
+ selectedMatchIndex = (selectedMatchIndex + direction + matchItems.length) % matchItems.length;
1088
+
1089
+ if (matchItems[selectedMatchIndex]) {
1090
+ matchItems[selectedMatchIndex].classList.add('selected');
1091
+ matchItems[selectedMatchIndex].scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' });
1092
+ }
1093
+ }
1094
+
1095
+ /**
1096
+ * Zooms the currently selected map in or out
1097
+ * @param {number} direction - Zoom direction: positive to zoom in, negative to zoom out
1098
+ * @returns {void}
1099
+ */
1100
+ function zoomCurrentMap(direction) {
1101
+ const mapId = `map-${selectedMatchIndex}`;
1102
+ const map = maps[mapId];
1103
+ if (map) {
1104
+ const currentZoom = map.getZoom();
1105
+ map.setZoom(currentZoom + direction);
1106
+ }
1107
+ }
1108
+
1109
+ /**
1110
+ * API endpoint for place search functionality
1111
+ * @type {string}
1112
+ */
1113
+ const API_ENDPOINT = 'https://mcp.fastah.ai/rest/geofeeds/place-search';
1114
+
1115
+ /**
1116
+ * Fetches geolocation matches from the API for given location data
1117
+ * @async
1118
+ * @param {Array<Object>} rows - Array of row objects with location data (countryCode, regionCode, cityName)
1119
+ * @returns {Promise<{results: Array<Object>}|null>} API response with matches or null on error
1120
+ */
1121
+ async function fetchPlaceMatches(rows) {
1122
+ const MAX_BATCH_SIZE = 1000;
1123
+ let allResults = [];
1124
+ let batchCount = Math.ceil(rows.length / MAX_BATCH_SIZE);
1125
+ let lastError = null;
1126
+
1127
+ for (let i = 0; i < batchCount; i++) {
1128
+ const batchRows = rows.slice(i * MAX_BATCH_SIZE, (i + 1) * MAX_BATCH_SIZE);
1129
+ try {
1130
+ const response = await fetch(API_ENDPOINT, {
1131
+ method: 'POST',
1132
+ headers: {
1133
+ 'Accept': 'application/json',
1134
+ 'Content-Type': 'application/json'
1135
+ },
1136
+ body: JSON.stringify({ rows: batchRows })
1137
+ });
1138
+
1139
+ if (!response.ok) {
1140
+ throw new Error(`API request failed: ${response.status} ${response.statusText}`);
1141
+ }
1142
+
1143
+ const data = await response.json();
1144
+ if (data && data.results) {
1145
+ allResults = allResults.concat(data.results);
1146
+ } else {
1147
+ lastError = 'No results in API response';
1148
+ }
1149
+ } catch (error) {
1150
+ console.error('Error calling place search API:', error);
1151
+ lastError = error.message;
1152
+ }
1153
+ }
1154
+
1155
+ if (allResults.length === 0 && lastError) {
1156
+ alert(`Failed to fetch location data: ${lastError}`);
1157
+ return null;
1158
+ }
1159
+
1160
+ return { results: allResults };
1161
+ }
1162
+
1163
+ /**
1164
+ * Prepares geofeed row data for API request
1165
+ * @param {HTMLTableRowElement} dataRow - The table row element to extract data from
1166
+ * @returns {Object|null} Object with countryCode, regionCode, cityName, maxResults and searchMode, or null if required data missing
1167
+ */
1168
+ function prepareRowForApi(dataRow) {
1169
+ const cells = dataRow.querySelectorAll('td');
1170
+ if (cells.length <= CELL_INDEX.STATUS) return null;
1171
+
1172
+ const countryCode = cells[CELL_INDEX.COUNTRY].textContent.trim();
1173
+ const regionCode = cells[CELL_INDEX.REGION].textContent.trim();
1174
+ const cityName = cells[CELL_INDEX.CITY].textContent.trim();
1175
+
1176
+ if (!countryCode) {
1177
+ return null;
1178
+ }
1179
+
1180
+ return {
1181
+ rowKey: crypto.randomUUID(),
1182
+ countryCode: countryCode,
1183
+ regionCode: regionCode || '',
1184
+ cityName: cityName || '',
1185
+ searchMode: 'auto'
1186
+ };
1187
+ }
1188
+
1189
+ /**
1190
+ * Handles tune button click - fetches location matches for selected issues
1191
+ * @async
1192
+ * @param {HTMLButtonElement} button - The tune button that was clicked
1193
+ * @returns {Promise<void>}
1194
+ */
1195
+ async function handleTuneButtonClick(button) {
1196
+ currentTuningButton = button;
1197
+
1198
+ const issuesContainer = button.closest('td');
1199
+ const checkedBoxes = issuesContainer.querySelectorAll('.message-line input[type="checkbox"]:checked');
1200
+
1201
+ const selectedIssues = Array.from(checkedBoxes).map(cb => {
1202
+ const messageLine = cb.closest('.message-line');
1203
+ return {
1204
+ id: messageLine.getAttribute('data-id'),
1205
+ message: messageLine.querySelector('span').textContent
1206
+ };
1207
+ });
1208
+
1209
+ if (selectedIssues.length === 0) {
1210
+ alert('Please select at least one issue to tune.');
1211
+ return;
1212
+ }
1213
+
1214
+ const detailsRow = button.closest('tr');
1215
+
1216
+ // Find the data row - it's before the expand-details-rows
1217
+ let dataRow = detailsRow.previousElementSibling;
1218
+ while (dataRow && dataRow.classList.contains('expand-details-row')) {
1219
+ dataRow = dataRow.previousElementSibling;
1220
+ }
1221
+
1222
+ if (!dataRow || !dataRow.classList.contains('expandable-row')) {
1223
+ console.error('Could not find data row');
1224
+ return;
1225
+ }
1226
+
1227
+ const rowData = prepareRowForApi(dataRow);
1228
+ if (!rowData) {
1229
+ alert('Missing required location data for API call');
1230
+ return;
1231
+ }
1232
+
1233
+ const apiResponse = await fetchPlaceMatches([rowData]);
1234
+
1235
+ if (!apiResponse || !apiResponse.results || apiResponse.results.length === 0) {
1236
+ alert('No results returned from API');
1237
+ return;
1238
+ }
1239
+
1240
+ const result = apiResponse.results[0];
1241
+
1242
+ if (result.matches && result.matches.length > 0) {
1243
+ showLocationPopup(result.matches, selectedIssues);
1244
+ } else {
1245
+ alert('No location matches found for this entry');
1246
+ }
1247
+ }
1248
+
1249
+ /**
1250
+ * Displays the location matches popup modal with maps and selectable options
1251
+ * @param {Array<Object>} matches - Array of location match objects from API
1252
+ * @param {Array<Object>} [selectedIssues=[]] - Array of selected issues for tracking
1253
+ * @returns {void}
1254
+ */
1255
+ function showLocationPopup(matches, selectedIssues = []) {
1256
+ if (!matches || matches.length === 0) {
1257
+ return;
1258
+ }
1259
+
1260
+ const matchesList = document.getElementById('matchesList');
1261
+ matchesList.innerHTML = '';
1262
+
1263
+ maps = {};
1264
+ matchItems = [];
1265
+ selectedMatchIndex = 0;
1266
+
1267
+ matches.forEach((match, index) => {
1268
+ const matchItem = document.createElement('div');
1269
+ matchItem.className = 'match-item';
1270
+ if (index === 0) {
1271
+ matchItem.classList.add('selected');
1272
+ }
1273
+ const mapId = `map-${index}`;
1274
+
1275
+ // Determine primary location text: city > region > country
1276
+ let primaryLocation = match.placeName;
1277
+ let locationType = 'city';
1278
+
1279
+ if (!primaryLocation || primaryLocation.trim() === '') {
1280
+ primaryLocation = match.stateCode;
1281
+ locationType = 'region';
1282
+ }
1283
+
1284
+ if (!primaryLocation || primaryLocation.trim() === '') {
1285
+ primaryLocation = match.countryCode;
1286
+ locationType = 'country';
1287
+ }
1288
+
1289
+ // Build secondary info (show what's available)
1290
+ let secondaryInfo = [];
1291
+ if (match.placeName && locationType !== 'city') {
1292
+ secondaryInfo.push(`City: ${escapeHtml(match.placeName)}`);
1293
+ }
1294
+ if (match.stateCode && locationType !== 'region') {
1295
+ secondaryInfo.push(`Region: ${escapeHtml(match.stateCode)}`);
1296
+ }
1297
+ if (match.countryCode && locationType !== 'country') {
1298
+ secondaryInfo.push(`Country: ${escapeHtml(match.countryCode)}`);
1299
+ }
1300
+
1301
+ matchItem.innerHTML = `
1302
+ <div id="${mapId}" class="match-map"></div>
1303
+ <div class="match-info-container">
1304
+ <div class="match-header">${escapeHtml(primaryLocation)}</div>
1305
+ ${secondaryInfo.length > 0 ? `<div class="location-details">${secondaryInfo.join(' \u2022 ')}</div>` : ''}
1306
+ </div>
1307
+ `;
1308
+
1309
+ matchItem.addEventListener('click', function() {
1310
+ selectLocationMatch(match);
1311
+ });
1312
+
1313
+ matchesList.appendChild(matchItem);
1314
+ matchItems.push(matchItem);
1315
+
1316
+ setTimeout(() => {
1317
+ initializeMapForMatch(mapId, match);
1318
+ }, TIMING.MAP_INIT_DELAY);
1319
+ });
1320
+
1321
+ modal.style.display = 'block';
1322
+ isModalOpen = true;
1323
+ document.body.style.overflow = 'hidden';
1324
+
1325
+ setTimeout(() => {
1326
+ if (modalContent) {
1327
+ modalContent.focus();
1328
+ }
1329
+ }, TIMING.MODAL_FOCUS_DELAY);
1330
+ }
1331
+
1332
+ /**
1333
+ * Selects a location match and updates the corresponding table row
1334
+ * @param {Object} match - Match object with countryCode, regionCode, name, and boundingBox
1335
+ * @returns {void}
1336
+ */
1337
+ function selectLocationMatch(match) {
1338
+ if (!currentTuningButton) {
1339
+ console.error('No tuning button reference found');
1340
+ return;
1341
+ }
1342
+
1343
+ const detailsRow = currentTuningButton.closest('tr');
1344
+
1345
+ // Find the data row - it's before the expand-details-rows
1346
+ let dataRow = detailsRow.previousElementSibling;
1347
+ while (dataRow && dataRow.classList.contains('expand-details-row')) {
1348
+ dataRow = dataRow.previousElementSibling;
1349
+ }
1350
+
1351
+ if (!dataRow || !dataRow.classList.contains('expandable-row')) {
1352
+ console.error('Could not find data row');
1353
+ return;
1354
+ }
1355
+
1356
+ updateRowWithMatchData(dataRow, match);
1357
+ closeModal();
1358
+ }
1359
+
1360
+ /**
1361
+ * Updates a table row with selected match data and stores original values
1362
+ * @param {HTMLTableRowElement} dataRow - The table row to update
1363
+ * @param {Object} match - Match object with countryCode, regionCode, and name
1364
+ * @returns {void}
1365
+ */
1366
+ function updateRowWithMatchData(dataRow, match) {
1367
+ const cells = dataRow.querySelectorAll('td');
1368
+ const currentCountry = cells[CELL_INDEX.COUNTRY].textContent;
1369
+ const currentRegion = cells[CELL_INDEX.REGION].textContent;
1370
+ const currentCity = cells[CELL_INDEX.CITY].textContent;
1371
+
1372
+ if (!dataRow.hasAttribute('data-original-country')) {
1373
+ dataRow.setAttribute('data-original-country', currentCountry);
1374
+ dataRow.setAttribute('data-original-region', currentRegion);
1375
+ dataRow.setAttribute('data-original-city', currentCity);
1376
+ }
1377
+
1378
+ cells[CELL_INDEX.COUNTRY].textContent = match.countryCode;
1379
+ cells[CELL_INDEX.REGION].textContent = match.stateCode;
1380
+ cells[CELL_INDEX.CITY].textContent = match.placeName;
1381
+
1382
+ // Find the previous values row (it's the first expand-details-row after the data row)
1383
+ const previousValuesRow = dataRow.nextElementSibling;
1384
+ if (previousValuesRow && previousValuesRow.classList.contains('previous-values-row')) {
1385
+ previousValuesRow.classList.add('show');
1386
+
1387
+ const defaultCountry = previousValuesRow.querySelector('.default-country');
1388
+ const defaultRegion = previousValuesRow.querySelector('.default-region');
1389
+ const defaultCity = previousValuesRow.querySelector('.default-city');
1390
+
1391
+ if (defaultCountry) defaultCountry.textContent = dataRow.getAttribute('data-original-country');
1392
+ if (defaultRegion) defaultRegion.textContent = dataRow.getAttribute('data-original-region');
1393
+ if (defaultCity) defaultCity.textContent = dataRow.getAttribute('data-original-city');
1394
+ }
1395
+ }
1396
+
1397
+ /**
1398
+ * Initializes a Leaflet map with location boundary and marker for a match
1399
+ * @param {string} mapId - The DOM element ID where map will render
1400
+ * @param {Object} match - Match object with name, boundingBox, regionCode, countryCode
1401
+ * @returns {void}
1402
+ */
1403
+ function initializeMapForMatch(mapId, match) {
1404
+ try {
1405
+ const mapInstance = L.map(mapId, {
1406
+ scrollWheelZoom: false,
1407
+ dragging: true,
1408
+ zoomControl: true
1409
+ });
1410
+
1411
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
1412
+ attribution: '© OpenStreetMap',
1413
+ maxZoom: 19
1414
+ }).addTo(mapInstance);
1415
+
1416
+ const bbox = match.boundingBox;
1417
+
1418
+ if (bbox && bbox.length === 4) {
1419
+ const [west, north, east, south] = bbox;
1420
+ const centerLat = (south + north) / 2;
1421
+ const centerLng = (west + east) / 2;
1422
+
1423
+ const isPoint = (west === east && north === south);
1424
+
1425
+ if (isPoint) {
1426
+ const offset = 0.05;
1427
+ const bounds = [
1428
+ [south - offset, west - offset],
1429
+ [north + offset, east + offset]
1430
+ ];
1431
+
1432
+ L.rectangle(bounds, {
1433
+ color: '#dc3545',
1434
+ weight: 3,
1435
+ opacity: 1,
1436
+ fillColor: '#dc3545',
1437
+ fillOpacity: 0.2
1438
+ }).addTo(mapInstance);
1439
+
1440
+ mapInstance.fitBounds(bounds, { padding: [30, 30] });
1441
+ } else {
1442
+ const bounds = [
1443
+ [south, west],
1444
+ [north, east]
1445
+ ];
1446
+
1447
+ L.rectangle(bounds, {
1448
+ color: '#dc3545',
1449
+ weight: 3,
1450
+ opacity: 1,
1451
+ fillColor: '#dc3545',
1452
+ fillOpacity: 0.2
1453
+ }).addTo(mapInstance);
1454
+
1455
+ mapInstance.fitBounds(bounds, { padding: [20, 20] });
1456
+ }
1457
+
1458
+ L.marker([centerLat, centerLng]).addTo(mapInstance)
1459
+ .bindPopup(`<b>${escapeHtml(match.placeName)}</b><br>${escapeHtml(match.stateCode)}`);
1460
+
1461
+ maps[mapId] = mapInstance;
1462
+
1463
+ setTimeout(() => {
1464
+ mapInstance.invalidateSize();
1465
+ }, TIMING.MAP_RESIZE_DELAY);
1466
+ }
1467
+ } catch (error) {
1468
+ console.error('Error initializing map:', error);
1469
+ }
1470
+ }
1471
+
1472
+ /**
1473
+ * Sets the report mode between 'viewing' and 'tuning'
1474
+ * Tuning mode shows checkboxes and expands rows with issues
1475
+ * @param {string} mode - 'viewing' or 'tuning'
1476
+ * @returns {void}
1477
+ */
1478
+ function setMode(mode) {
1479
+ const toggle = document.getElementById('modeToggle');
1480
+ const viewingText = document.getElementById('viewingText');
1481
+ const tuningText = document.getElementById('tuningText');
1482
+
1483
+ if (mode === 'tuning') {
1484
+ document.body.classList.add('tuning-mode');
1485
+ toggle.classList.add('tuning');
1486
+ viewingText.classList.remove('active');
1487
+ tuningText.classList.add('active');
1488
+
1489
+ // Only expand rows with issues
1490
+ const expandableRows = document.querySelectorAll('.expandable-row');
1491
+ expandableRows.forEach(row => {
1492
+ const hasError = row.getAttribute('data-has-error') === 'true';
1493
+ const hasWarning = row.getAttribute('data-has-warning') === 'true';
1494
+ const hasSuggestion = row.getAttribute('data-has-suggestion') === 'true';
1495
+
1496
+ if (hasError || hasWarning || hasSuggestion) {
1497
+ let detailRow = row.nextElementSibling;
1498
+ while (detailRow && detailRow.classList.contains('expand-details-row')) {
1499
+ // Only show issues-row, not previous-values-row
1500
+ if (detailRow.classList.contains('issues-row')) {
1501
+ detailRow.classList.add('show');
1502
+ }
1503
+ detailRow = detailRow.nextElementSibling;
1504
+ }
1505
+ }
1506
+ });
1507
+ } else {
1508
+ document.body.classList.remove('tuning-mode');
1509
+ toggle.classList.remove('tuning');
1510
+ viewingText.classList.add('active');
1511
+ tuningText.classList.remove('active');
1512
+ document.querySelectorAll('.expand-details-row').forEach(row => {
1513
+ row.classList.remove('show');
1514
+ });
1515
+ }
1516
+
1517
+ // Refresh pagination after mode change
1518
+ updatePagination();
1519
+ }
1520
+
1521
+ /**
1522
+ * Toggles between viewing and tuning modes
1523
+ * @returns {void}
1524
+ */
1525
+ function toggleMode() {
1526
+ const isTuning = document.body.classList.contains('tuning-mode');
1527
+ setMode(isTuning ? 'viewing' : 'tuning');
1528
+ }
1529
+
1530
+ /**
1531
+ * Escapes HTML special characters to prevent XSS attacks
1532
+ * @param {string} text - Text to escape
1533
+ * @returns {string} Escaped HTML text
1534
+ */
1535
+ function escapeHtml(text) {
1536
+ const map = {
1537
+ '&': '&amp;',
1538
+ '<': '&lt;',
1539
+ '>': '&gt;',
1540
+ '"': '&quot;',
1541
+ "'": '&#039;'
1542
+ };
1543
+ return text.replace(/[&<>"']/g, m => map[m]);
1544
+ }
1545
+
1546
+ /**
1547
+ * Filters the entries table based on current filter input values
1548
+ * Resets to page 1 and updates pagination
1549
+ * @returns {void}
1550
+ */
1551
+ function filterTable() {
1552
+ const countryFilter = document.getElementById('filterCountry').value.toLowerCase();
1553
+ const regionFilter = document.getElementById('filterRegion').value.toLowerCase();
1554
+ const cityFilter = document.getElementById('filterCity').value.toLowerCase();
1555
+ const statusFilter = document.getElementById('filterStatus').value;
1556
+ const ipPrefixFilter = document.getElementById('filterIpPrefix').value.toLowerCase();
1557
+
1558
+ const allExpandableRows = document.querySelectorAll('.expandable-row');
1559
+
1560
+ // Filter rows and update allRows array
1561
+ allRows = Array.from(allExpandableRows).filter(row => {
1562
+ const cells = row.querySelectorAll('td');
1563
+ if (cells.length <= CELL_INDEX.STATUS) return false;
1564
+
1565
+ const rowData = {
1566
+ country: cells[CELL_INDEX.COUNTRY].textContent.toLowerCase(),
1567
+ region: cells[CELL_INDEX.REGION].textContent.toLowerCase(),
1568
+ city: cells[CELL_INDEX.CITY].textContent.toLowerCase(),
1569
+ status: cells[CELL_INDEX.STATUS].textContent,
1570
+ ipPrefix: cells[CELL_INDEX.IP_PREFIX].textContent.toLowerCase()
1571
+ };
1572
+
1573
+ return (
1574
+ (!countryFilter || rowData.country.includes(countryFilter)) &&
1575
+ (!regionFilter || rowData.region.includes(regionFilter)) &&
1576
+ (!cityFilter || rowData.city.includes(cityFilter)) &&
1577
+ (!statusFilter || rowData.status === statusFilter) &&
1578
+ (!ipPrefixFilter || rowData.ipPrefix.includes(ipPrefixFilter))
1579
+ );
1580
+ });
1581
+
1582
+ // Reset to page 1 and update pagination
1583
+ currentPage = 1;
1584
+ updatePagination();
1585
+ }
1586
+
1587
+ /**
1588
+ * Pagination state and configuration
1589
+ * @type {Object}
1590
+ */
1591
+ // Pagination state
1592
+ /** @type {number} Current page number (1-indexed) */
1593
+ let currentPage = 1;
1594
+
1595
+ /** @type {number} Number of rows to display per page */
1596
+ let rowsPerPage = 100;
1597
+
1598
+ /** @type {Array<HTMLTableRowElement>} Array of expandable rows after filtering */
1599
+ let allRows = [];
1600
+
1601
+ // Initialize on page load
1602
+ window.addEventListener('DOMContentLoaded', function() {
1603
+ // Initialize pagination
1604
+ allRows = Array.from(document.querySelectorAll('.expandable-row'));
1605
+ initializePagination();
1606
+
1607
+ // Setup select all checkbox
1608
+ const selectAllCheckbox = document.getElementById('selectAll');
1609
+ const rowCheckboxes = document.querySelectorAll('.row-checkbox');
1610
+
1611
+ selectAllCheckbox.addEventListener('change', function() {
1612
+ rowCheckboxes.forEach(checkbox => {
1613
+ checkbox.checked = selectAllCheckbox.checked;
1614
+ });
1615
+ });
1616
+
1617
+ // Update select all checkbox when individual checkboxes change
1618
+ rowCheckboxes.forEach(checkbox => {
1619
+ checkbox.addEventListener('click', function(e) {
1620
+ e.stopPropagation(); // Prevent row expansion when clicking checkbox
1621
+ });
1622
+ checkbox.addEventListener('keydown', function(e) {
1623
+ if (e.key === ' ' || e.key === 'Enter') {
1624
+ e.stopPropagation(); // Prevent row expansion when using keyboard on checkbox
1625
+ }
1626
+ });
1627
+ checkbox.addEventListener('change', function(e) {
1628
+ e.stopPropagation(); // Prevent row expansion when clicking checkbox
1629
+ const allChecked = Array.from(rowCheckboxes).every(cb => cb.checked);
1630
+ const noneChecked = Array.from(rowCheckboxes).every(cb => !cb.checked);
1631
+ selectAllCheckbox.checked = allChecked;
1632
+ selectAllCheckbox.indeterminate = !allChecked && !noneChecked;
1633
+ });
1634
+ });
1635
+
1636
+ // Setup expandable rows
1637
+ const expandableRows = document.querySelectorAll('.expandable-row');
1638
+ expandableRows.forEach(row => {
1639
+ const hasError = row.getAttribute('data-has-error') === 'true';
1640
+ const hasWarning = row.getAttribute('data-has-warning') === 'true';
1641
+ const hasSuggestion = row.getAttribute('data-has-suggestion') === 'true';
1642
+
1643
+ // Only make rows with issues focusable
1644
+ if (hasError || hasWarning || hasSuggestion) {
1645
+ row.setAttribute('tabindex', '0');
1646
+
1647
+ // Click handler
1648
+ row.addEventListener('click', function(e) {
1649
+ // Don't expand if clicking on checkbox
1650
+ if (e.target.classList.contains('row-checkbox')) {
1651
+ return;
1652
+ }
1653
+ let detailRow = this.nextElementSibling;
1654
+ let expanding = false;
1655
+ // First pass: check if we are expanding (issues-row will be shown)
1656
+ while (detailRow && detailRow.classList.contains('expand-details-row')) {
1657
+ if (detailRow.classList.contains('issues-row')) {
1658
+ expanding = !detailRow.classList.contains('show');
1659
+ break;
1660
+ }
1661
+ detailRow = detailRow.nextElementSibling;
1662
+ }
1663
+ detailRow = this.nextElementSibling;
1664
+ while (detailRow && detailRow.classList.contains('expand-details-row')) {
1665
+ if (detailRow.classList.contains('issues-row')) {
1666
+ // Always toggle issues-row
1667
+ detailRow.classList.toggle('show');
1668
+ } else if (detailRow.classList.contains('previous-values-row')) {
1669
+ if (expanding) {
1670
+ // Show previous-values-row if this row has original data (was tuned)
1671
+ if (row.hasAttribute('data-original-country') ||
1672
+ row.hasAttribute('data-original-region') ||
1673
+ row.hasAttribute('data-original-city')) {
1674
+ detailRow.classList.add('show');
1675
+ }
1676
+ } else {
1677
+ // If collapsing, hide previous-values-row
1678
+ detailRow.classList.remove('show');
1679
+ }
1680
+ }
1681
+ detailRow = detailRow.nextElementSibling;
1682
+ }
1683
+ // Refresh pagination to show/hide the toggled detail rows
1684
+ updatePagination();
1685
+ });
1686
+
1687
+ // Keyboard handler
1688
+ row.addEventListener('keydown', function(e) {
1689
+ // Don't handle if focus is on checkbox
1690
+ if (document.activeElement.classList.contains('row-checkbox')) {
1691
+ return;
1692
+ }
1693
+ if (e.key === 'Enter' || e.key === ' ') {
1694
+ e.preventDefault();
1695
+ let detailRow = this.nextElementSibling;
1696
+ let expanding = false;
1697
+ // First pass: check if we are expanding (issues-row will be shown)
1698
+ while (detailRow && detailRow.classList.contains('expand-details-row')) {
1699
+ if (detailRow.classList.contains('issues-row')) {
1700
+ expanding = !detailRow.classList.contains('show');
1701
+ break;
1702
+ }
1703
+ detailRow = detailRow.nextElementSibling;
1704
+ }
1705
+ detailRow = this.nextElementSibling;
1706
+ while (detailRow && detailRow.classList.contains('expand-details-row')) {
1707
+ if (detailRow.classList.contains('issues-row')) {
1708
+ // Always toggle issues-row
1709
+ detailRow.classList.toggle('show');
1710
+ } else if (detailRow.classList.contains('previous-values-row')) {
1711
+ if (expanding) {
1712
+ // Show previous-values-row if this row has original data (was tuned)
1713
+ if (row.hasAttribute('data-original-country') ||
1714
+ row.hasAttribute('data-original-region') ||
1715
+ row.hasAttribute('data-original-city')) {
1716
+ detailRow.classList.add('show');
1717
+ }
1718
+ } else {
1719
+ // If collapsing, hide previous-values-row
1720
+ detailRow.classList.remove('show');
1721
+ }
1722
+ }
1723
+ detailRow = detailRow.nextElementSibling;
1724
+ }
1725
+ // Refresh pagination to show/hide the toggled detail rows
1726
+ updatePagination();
1727
+ }
1728
+ });
1729
+ } else {
1730
+ row.style.cursor = 'default';
1731
+ }
1732
+ });
1733
+
1734
+ // Toggle Expand All button
1735
+ let isExpanded = false;
1736
+ document.getElementById('toggleExpandAll').addEventListener('click', function() {
1737
+ const expandableRows = document.querySelectorAll('.expandable-row');
1738
+ const button = document.getElementById('toggleExpandAll');
1739
+
1740
+ if (!isExpanded) {
1741
+ // Show all
1742
+ expandableRows.forEach(row => {
1743
+ const checkbox = row.querySelector('.row-checkbox');
1744
+ if (!checkbox || !checkbox.checked) return; // Only work on checked rows
1745
+
1746
+ const hasError = row.getAttribute('data-has-error') === 'true';
1747
+ const hasWarning = row.getAttribute('data-has-warning') === 'true';
1748
+ const hasSuggestion = row.getAttribute('data-has-suggestion') === 'true';
1749
+
1750
+ // Only expand rows with issues
1751
+ if (hasError || hasWarning || hasSuggestion) {
1752
+ let detailRow = row.nextElementSibling;
1753
+ while (detailRow && detailRow.classList.contains('expand-details-row')) {
1754
+ // Show issues-row always
1755
+ if (detailRow.classList.contains('issues-row')) {
1756
+ detailRow.classList.add('show');
1757
+ } else if (detailRow.classList.contains('previous-values-row')) {
1758
+ // Show previous-values-row if this row has original data (was tuned)
1759
+ if (row.hasAttribute('data-original-country') ||
1760
+ row.hasAttribute('data-original-region') ||
1761
+ row.hasAttribute('data-original-city')) {
1762
+ detailRow.classList.add('show');
1763
+ }
1764
+ }
1765
+ detailRow = detailRow.nextElementSibling;
1766
+ }
1767
+ }
1768
+ });
1769
+ button.innerHTML = '<i class="bi bi-arrows-collapse" style="margin-right: 5px;"></i>Collapse Rows';
1770
+ isExpanded = true;
1771
+ } else {
1772
+ // Collapse all
1773
+ expandableRows.forEach(row => {
1774
+ const checkbox = row.querySelector('.row-checkbox');
1775
+ if (!checkbox || !checkbox.checked) return; // Only work on checked rows
1776
+
1777
+ let detailRow = row.nextElementSibling;
1778
+ while (detailRow && detailRow.classList.contains('expand-details-row')) {
1779
+ detailRow.classList.remove('show');
1780
+ detailRow = detailRow.nextElementSibling;
1781
+ }
1782
+ });
1783
+ button.innerHTML = '<i class="bi bi-arrows-expand" style="margin-right: 5px;"></i>Expand Rows';
1784
+ isExpanded = false;
1785
+ }
1786
+
1787
+ // Refresh pagination to show expanded rows correctly
1788
+ updatePagination();
1789
+ });
1790
+
1791
+ // Toggle Filters button
1792
+ document.getElementById('toggleFilters').addEventListener('click', function() {
1793
+ const filterRow = document.getElementById('filterRow');
1794
+ const button = document.getElementById('toggleFilters');
1795
+
1796
+ if (filterRow.style.display === 'none') {
1797
+ filterRow.style.display = '';
1798
+ button.innerHTML = '<i class="bi bi-funnel-fill" style="margin-right: 5px;"></i>Hide Filters';
1799
+ } else {
1800
+ filterRow.style.display = 'none';
1801
+ button.innerHTML = '<i class="bi bi-funnel-fill" style="margin-right: 5px;"></i>Show Filters';
1802
+ }
1803
+ });
1804
+
1805
+ // Tune All button
1806
+ document.getElementById('tuneAll').addEventListener('click', async function() {
1807
+ const expandableRows = document.querySelectorAll('.expandable-row');
1808
+
1809
+ let updatedCount = 0;
1810
+ let skippedCount = 0;
1811
+
1812
+ expandableRows.forEach(dataRow => {
1813
+ const checkbox = dataRow.querySelector('.row-checkbox');
1814
+ if (!checkbox || !checkbox.checked) {
1815
+ skippedCount++;
1816
+ return; // Only work on checked rows
1817
+ }
1818
+
1819
+ const isTunable = dataRow.getAttribute('data-tunable') === 'true';
1820
+ if (!isTunable) {
1821
+ skippedCount++;
1822
+ return;
1823
+ }
1824
+
1825
+ const tunedCountry = dataRow.getAttribute('data-tuned-country');
1826
+ const tunedRegion = dataRow.getAttribute('data-tuned-region');
1827
+ const tunedCity = dataRow.getAttribute('data-tuned-city');
1828
+
1829
+ if (!tunedCountry && !tunedRegion && !tunedCity) {
1830
+ skippedCount++;
1831
+ return;
1832
+ }
1833
+
1834
+ const cells = dataRow.querySelectorAll('td');
1835
+ if (cells.length <= CELL_INDEX.STATUS) {
1836
+ skippedCount++;
1837
+ return;
1838
+ }
1839
+
1840
+ if (!dataRow.hasAttribute('data-original-country')) {
1841
+ dataRow.setAttribute('data-original-country', cells[CELL_INDEX.COUNTRY].textContent);
1842
+ dataRow.setAttribute('data-original-region', cells[CELL_INDEX.REGION].textContent);
1843
+ dataRow.setAttribute('data-original-city', cells[CELL_INDEX.CITY].textContent);
1844
+ }
1845
+
1846
+ if (tunedCountry) cells[CELL_INDEX.COUNTRY].textContent = tunedCountry;
1847
+ if (tunedRegion) cells[CELL_INDEX.REGION].textContent = tunedRegion;
1848
+ if (tunedCity) cells[CELL_INDEX.CITY].textContent = tunedCity;
1849
+
1850
+ // Find the previous values row
1851
+ const previousValuesRow = dataRow.nextElementSibling;
1852
+ if (previousValuesRow && previousValuesRow.classList.contains('previous-values-row')) {
1853
+ previousValuesRow.classList.add('show');
1854
+
1855
+ const defaultCountry = previousValuesRow.querySelector('.default-country');
1856
+ const defaultRegion = previousValuesRow.querySelector('.default-region');
1857
+ const defaultCity = previousValuesRow.querySelector('.default-city');
1858
+
1859
+ if (defaultCountry) defaultCountry.textContent = dataRow.getAttribute('data-original-country');
1860
+ if (defaultRegion) defaultRegion.textContent = dataRow.getAttribute('data-original-region');
1861
+ if (defaultCity) defaultCity.textContent = dataRow.getAttribute('data-original-city');
1862
+ }
1863
+
1864
+ updatedCount++;
1865
+ });
1866
+
1867
+ // Refresh pagination to update displayed values
1868
+ updatePagination();
1869
+
1870
+ alert(`Successfully updated ${updatedCount} rows (${skippedCount} rows skipped - not tunable or no tuned values available)`);
1871
+ });
1872
+
1873
+ // Add filter event listeners
1874
+ document.getElementById('filterCountry').addEventListener('input', filterTable);
1875
+ document.getElementById('filterRegion').addEventListener('input', filterTable);
1876
+ document.getElementById('filterCity').addEventListener('input', filterTable);
1877
+ document.getElementById('filterStatus').addEventListener('change', filterTable);
1878
+ document.getElementById('filterIpPrefix').addEventListener('input', filterTable);
1879
+
1880
+ // Reset filters button
1881
+ document.getElementById('resetFilters').addEventListener('click', function() {
1882
+ document.getElementById('filterCountry').value = '';
1883
+ document.getElementById('filterRegion').value = '';
1884
+ document.getElementById('filterCity').value = '';
1885
+ document.getElementById('filterStatus').value = '';
1886
+ document.getElementById('filterIpPrefix').value = '';
1887
+
1888
+ // Reset to all rows and update pagination
1889
+ allRows = Array.from(document.querySelectorAll('.expandable-row'));
1890
+ currentPage = 1;
1891
+ updatePagination();
1892
+ });
1893
+
1894
+ // Download CSV button
1895
+ document.getElementById('downloadCSV').addEventListener('click', function() {
1896
+ const rows = document.querySelectorAll('.expandable-row');
1897
+ const rowDataMap = {};
1898
+
1899
+ // Collect all data rows with their line numbers
1900
+ rows.forEach(row => {
1901
+ const cells = row.querySelectorAll('td');
1902
+ if (cells.length > CELL_INDEX.CITY) {
1903
+ const lineNum = parseInt(cells[CELL_INDEX.LINE].textContent.trim());
1904
+ const ipPrefix = cells[CELL_INDEX.IP_PREFIX].textContent.trim();
1905
+ const country = cells[CELL_INDEX.COUNTRY].textContent.trim();
1906
+ const region = cells[CELL_INDEX.REGION].textContent.trim();
1907
+ const city = cells[CELL_INDEX.CITY].textContent.trim();
1908
+
1909
+ rowDataMap[lineNum] = [ipPrefix, country, region, city];
1910
+ }
1911
+ });
1912
+
1913
+ // Build CSV content with comments in the correct positions
1914
+ const csvLines = [];
1915
+
1916
+ // Find max line number
1917
+ const allLineNumbers = Object.keys(rowDataMap).map(n => parseInt(n));
1918
+ const maxLine = Math.max(...allLineNumbers);
1919
+
1920
+ // Iterate through all line numbers from 1 to maxLine
1921
+ for (let lineNum = 1; lineNum <= maxLine; lineNum++) {
1922
+ if (lineNum in commentMap) {
1923
+ // This line is a comment
1924
+ csvLines.push(commentMap[lineNum]);
1925
+ } else if (rowDataMap[lineNum]) {
1926
+ // This line is a data row
1927
+ const row = rowDataMap[lineNum];
1928
+ const csvRow = row.map(cell => {
1929
+ // Escape quotes and wrap in quotes if contains comma, quote, or newline
1930
+ const cellStr = String(cell);
1931
+ if (cellStr.includes(',') || cellStr.includes('"') || cellStr.includes('\n')) {
1932
+ return '"' + cellStr.replace(/"/g, '""') + '"';
1933
+ }
1934
+ return cellStr;
1935
+ }).join(',');
1936
+ csvLines.push(csvRow);
1937
+ }
1938
+ // If neither comment nor data, skip the line (maintains original CSV structure)
1939
+ }
1940
+
1941
+ const csvContent = csvLines.join('\n');
1942
+
1943
+ // Create download link
1944
+ const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
1945
+ const link = document.createElement('a');
1946
+ const url = URL.createObjectURL(blob);
1947
+
1948
+ // Get filename from inputFileMetrics, ensure it has .csv extension
1949
+ let filename =
1950
+ document.getElementById('inputFileMetrics')
1951
+ .textContent
1952
+ .trim()
1953
+ .split(/[/\\]/)
1954
+ .pop() || 'geofeed_report.csv';
1955
+ if (!filename.toLowerCase().endsWith('.csv')) {
1956
+ filename += '.csv';
1957
+ }
1958
+
1959
+ link.setAttribute('href', url);
1960
+ link.setAttribute('download', filename);
1961
+ link.style.visibility = 'hidden';
1962
+ document.body.appendChild(link);
1963
+ link.click();
1964
+ document.body.removeChild(link);
1965
+ });
1966
+
1967
+ // Pagination event listeners
1968
+ document.getElementById('pageSize').addEventListener('change', function() {
1969
+ const value = this.value;
1970
+ if (value === 'all') {
1971
+ rowsPerPage = allRows.length;
1972
+ } else {
1973
+ rowsPerPage = parseInt(value);
1974
+ }
1975
+ currentPage = 1;
1976
+ updatePagination();
1977
+ });
1978
+
1979
+ document.getElementById('firstPage').addEventListener('click', function() {
1980
+ currentPage = 1;
1981
+ updatePagination();
1982
+ });
1983
+
1984
+ document.getElementById('prevPage').addEventListener('click', function() {
1985
+ if (currentPage > 1) {
1986
+ currentPage--;
1987
+ updatePagination();
1988
+ }
1989
+ });
1990
+
1991
+ document.getElementById('nextPage').addEventListener('click', function() {
1992
+ const totalPages = Math.ceil(allRows.length / rowsPerPage);
1993
+ if (currentPage < totalPages) {
1994
+ currentPage++;
1995
+ updatePagination();
1996
+ }
1997
+ });
1998
+
1999
+ document.getElementById('lastPage').addEventListener('click', function() {
2000
+ currentPage = Math.ceil(allRows.length / rowsPerPage);
2001
+ updatePagination();
2002
+ });
2003
+
2004
+ initSummaryMap();
2005
+ });
2006
+
2007
+ /**
2008
+ * Initializes pagination on page load
2009
+ * @returns {void}
2010
+ */
2011
+ function initializePagination() {
2012
+ updatePagination();
2013
+ }
2014
+
2015
+
2016
+ function initSummaryMap() {
2017
+ try {
2018
+ const summaryMapEl = document.getElementById('summaryMap');
2019
+ if (!summaryMapEl) return;
2020
+ summaryMapInstance = L.map('summaryMap', {
2021
+ scrollWheelZoom: true,
2022
+ dragging: true,
2023
+ zoomControl: true,
2024
+ center: [20, 0],
2025
+ zoom: 2
2026
+ });
2027
+ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
2028
+ attribution: '\u00a9 <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
2029
+ maxZoom: 19
2030
+ }).addTo(summaryMapInstance);
2031
+ summaryLayerGroup = L.layerGroup().addTo(summaryMapInstance);
2032
+ // Parse and cache all row data once
2033
+ summaryRowData = [];
2034
+ const expandableRows = document.querySelectorAll('.expandable-row');
2035
+ expandableRows.forEach(row => {
2036
+ const cells = row.querySelectorAll('td');
2037
+ const hasError = row.getAttribute('data-has-error') === 'true';
2038
+ const hasWarning = row.getAttribute('data-has-warning') === 'true';
2039
+ const hasSugg = row.getAttribute('data-has-suggestion') === 'true';
2040
+ let color = '#28a745';
2041
+ if (hasError) color = '#dc3545';
2042
+ else if (hasWarning) color = '#fd7e14';
2043
+ else if (hasSugg) color = '#17a2b8';
2044
+ const country = cells[CELL_INDEX.COUNTRY] ? cells[CELL_INDEX.COUNTRY].textContent.trim() : '';
2045
+ const region = cells[CELL_INDEX.REGION] ? cells[CELL_INDEX.REGION].textContent.trim() : '';
2046
+ const city = cells[CELL_INDEX.CITY] ? cells[CELL_INDEX.CITY].textContent.trim() : '';
2047
+ const parts = [];
2048
+ if (city && region && country) {
2049
+ parts.push('<b>' + escapeHtml(city) + '</b>' + ' &bull; ' + escapeHtml(region) + ' &bull; ' + escapeHtml(country));
2050
+ } else if (city && country) {
2051
+ parts.push('<b>' + escapeHtml(city) + '</b>' + ' &bull; ' + escapeHtml(country));
2052
+ } else if (region && country) {
2053
+ parts.push('<b>' + escapeHtml(region) + '</b>' + ' &bull; ' + escapeHtml(country));
2054
+ } else if (country) {
2055
+ parts.push('<b>' + escapeHtml(country) + '</b>');
2056
+ }
2057
+ summaryRowData.push({
2058
+ rowId: row.id,
2059
+ bbox: row.getAttribute('data-bounding-box') || '',
2060
+ h3cells: row.getAttribute('data-h3-cells') || '',
2061
+ color: color,
2062
+ popup: parts.join('<br>')
2063
+ });
2064
+ });
2065
+ setTimeout(() => {
2066
+ summaryMapInstance.invalidateSize();
2067
+ switchMapMode('bbox');
2068
+ }, 350);
2069
+ } catch (err) {
2070
+ console.error('initSummaryMap error:', err);
2071
+ }
2072
+ }
2073
+
2074
+ function switchMapMode(mode) {
2075
+ const toggle = document.getElementById('mapModeToggle');
2076
+ const bboxText = document.getElementById('mapModeBboxText');
2077
+ const h3Text = document.getElementById('mapModeH3Text');
2078
+ // If called with no argument, act as a toggle
2079
+ if (mode === undefined) {
2080
+ mode = currentMapMode === 'bbox' ? 'h3' : 'bbox';
2081
+ }
2082
+ if (mode === 'h3') {
2083
+ toggle.classList.add('h3mode');
2084
+ bboxText.classList.remove('active');
2085
+ h3Text.classList.add('active');
2086
+ } else {
2087
+ toggle.classList.remove('h3mode');
2088
+ bboxText.classList.add('active');
2089
+ h3Text.classList.remove('active');
2090
+ }
2091
+ renderSummaryMapLayers(mode);
2092
+ }
2093
+
2094
+ function renderSummaryMapLayers(mode) {
2095
+ if (!summaryMapInstance || !summaryLayerGroup) return;
2096
+ currentMapMode = mode;
2097
+ summaryLayerGroup.clearLayers();
2098
+
2099
+ // Determine which row IDs are visible on the current page
2100
+ const startIndex = (currentPage - 1) * rowsPerPage;
2101
+ const endIndex = Math.min(startIndex + rowsPerPage, allRows.length);
2102
+ const visibleIds = new Set();
2103
+ for (let i = startIndex; i < endIndex; i++) {
2104
+ visibleIds.add(allRows[i].id);
2105
+ }
2106
+
2107
+ const tempBoundsLayers = [];
2108
+ const seenBboxKeys = new Set(); // deduplicate identical bounding boxes / h3 cell sets
2109
+
2110
+ summaryRowData.forEach(data => {
2111
+ // Only render entries whose row is on the current page
2112
+ if (!visibleIds.has(data.rowId)) return;
2113
+
2114
+ if (mode === 'bbox') {
2115
+ const raw = data.bbox.replace(/[\[\]]/g, '').trim();
2116
+ const pts = raw.split(/[\s,]+/).map(Number);
2117
+ if (pts.length !== 4 || pts.some(v => isNaN(v))) return;
2118
+
2119
+ // Skip duplicate bounding boxes
2120
+ const bboxKey = pts.join(',');
2121
+ if (seenBboxKeys.has(bboxKey)) return;
2122
+ seenBboxKeys.add(bboxKey);
2123
+
2124
+ const [west, north, east, south] = pts;
2125
+ const lb = [[south, west], [north, east]];
2126
+ const rect = L.rectangle(lb, {
2127
+ color: data.color, weight: 3, opacity: 1,
2128
+ fillColor: data.color, fillOpacity: 0.35
2129
+ });
2130
+ rect.bindPopup(data.popup);
2131
+ summaryLayerGroup.addLayer(rect);
2132
+ const cm = L.circleMarker([(south + north) / 2, (west + east) / 2], {
2133
+ radius: 5, color: data.color, fillColor: data.color, fillOpacity: 0.9, weight: 1
2134
+ });
2135
+ cm.bindPopup(data.popup);
2136
+ summaryLayerGroup.addLayer(cm);
2137
+ tempBoundsLayers.push(L.rectangle(lb));
2138
+ } else {
2139
+ // H3 cells mode
2140
+ const raw = data.h3cells.replace(/[\[\]]/g, '').trim();
2141
+ if (!raw) return;
2142
+
2143
+ // Skip duplicate h3 cell sets
2144
+ if (seenBboxKeys.has(raw)) return;
2145
+ seenBboxKeys.add(raw);
2146
+
2147
+ const cellIds = raw.split(/[\s,]+/).filter(Boolean);
2148
+ cellIds.forEach(cellId => {
2149
+ try {
2150
+ const boundary = h3.cellToBoundary(cellId); // returns [[lat,lng],...]
2151
+ const poly = L.polygon(boundary, {
2152
+ color: data.color, weight: 2, opacity: 0.9,
2153
+ fillColor: data.color, fillOpacity: 0.35
2154
+ });
2155
+ poly.bindPopup(data.popup);
2156
+ summaryLayerGroup.addLayer(poly);
2157
+ const b = poly.getBounds();
2158
+ tempBoundsLayers.push(L.rectangle([[b.getSouth(), b.getWest()], [b.getNorth(), b.getEast()]]));
2159
+ } catch (e) {
2160
+ console.warn('H3 render error for cell', cellId, e);
2161
+ }
2162
+ });
2163
+ }
2164
+ });
2165
+ if (tempBoundsLayers.length > 0) {
2166
+ const group = L.featureGroup(tempBoundsLayers);
2167
+ summaryMapInstance.fitBounds(group.getBounds(), { padding: [40, 40], maxZoom: 14 });
2168
+ }
2169
+ }
2170
+
2171
+
2172
+ /**
2173
+ * Updates pagination display for current page
2174
+ * Shows/hides rows based on current page and rowsPerPage
2175
+ * @returns {void}
2176
+ */
2177
+ function updatePagination() {
2178
+ const totalPages = Math.max(1, Math.ceil(allRows.length / rowsPerPage));
2179
+
2180
+ // Ensure currentPage is within valid range
2181
+ if (currentPage > totalPages) {
2182
+ currentPage = totalPages;
2183
+ }
2184
+ if (currentPage < 1) {
2185
+ currentPage = 1;
2186
+ }
2187
+
2188
+ const startIndex = (currentPage - 1) * rowsPerPage;
2189
+ const endIndex = Math.min(startIndex + rowsPerPage, allRows.length);
2190
+
2191
+ // Hide ALL expandable rows first (not just filtered ones)
2192
+ const allExpandableRows = document.querySelectorAll('.expandable-row');
2193
+ allExpandableRows.forEach(row => {
2194
+ row.style.display = 'none';
2195
+ // Hide associated detail rows
2196
+ let nextRow = row.nextElementSibling;
2197
+ while (nextRow && nextRow.classList.contains('expand-details-row')) {
2198
+ nextRow.style.display = 'none';
2199
+ nextRow = nextRow.nextElementSibling;
2200
+ }
2201
+ });
2202
+
2203
+ // Show rows for current page
2204
+ for (let i = startIndex; i < endIndex; i++) {
2205
+ const row = allRows[i];
2206
+ row.style.display = '';
2207
+ // Show associated detail rows if they have 'show' class
2208
+ let nextRow = row.nextElementSibling;
2209
+ while (nextRow && nextRow.classList.contains('expand-details-row')) {
2210
+ if (nextRow.classList.contains('show')) {
2211
+ nextRow.style.display = '';
2212
+ }
2213
+ nextRow = nextRow.nextElementSibling;
2214
+ }
2215
+ }
2216
+
2217
+ // Update pagination info
2218
+ if (allRows.length === 0) {
2219
+ document.getElementById('paginationInfo').textContent = 'Showing 0 of 0 rows';
2220
+ } else {
2221
+ document.getElementById('paginationInfo').textContent =
2222
+ `Showing ${startIndex + 1}-${endIndex} of ${allRows.length} rows`;
2223
+ }
2224
+
2225
+ // Update button states
2226
+ document.getElementById('firstPage').disabled = currentPage === 1 || allRows.length === 0;
2227
+ document.getElementById('prevPage').disabled = currentPage === 1 || allRows.length === 0;
2228
+ document.getElementById('nextPage').disabled = currentPage === totalPages || allRows.length === 0;
2229
+ document.getElementById('lastPage').disabled = currentPage === totalPages || allRows.length === 0;
2230
+
2231
+ // Update page numbers
2232
+ updatePageNumbers(totalPages);
2233
+
2234
+ // Refresh the Geographic Coverage Map to show only current-page entries
2235
+ renderSummaryMapLayers(currentMapMode);
2236
+ }
2237
+
2238
+ /**
2239
+ * Updates page number buttons display with ellipsis for large page counts
2240
+ * @param {number} totalPages - Total number of pages available
2241
+ * @returns {void}
2242
+ */
2243
+ function updatePageNumbers(totalPages) {
2244
+ const pageNumbersContainer = document.getElementById('pageNumbers');
2245
+ pageNumbersContainer.innerHTML = '';
2246
+
2247
+ // Show max 5 page numbers with ellipsis
2248
+ const maxVisible = 5;
2249
+ let startPage = Math.max(1, currentPage - Math.floor(maxVisible / 2));
2250
+ let endPage = Math.min(totalPages, startPage + maxVisible - 1);
2251
+
2252
+ // Adjust if we're near the end
2253
+ if (endPage - startPage < maxVisible - 1) {
2254
+ startPage = Math.max(1, endPage - maxVisible + 1);
2255
+ }
2256
+
2257
+ // Add first page and ellipsis if needed
2258
+ if (startPage > 1) {
2259
+ addPageButton(1);
2260
+ if (startPage > 2) {
2261
+ const ellipsis = document.createElement('span');
2262
+ ellipsis.textContent = '...';
2263
+ ellipsis.style.padding = '6px 8px';
2264
+ ellipsis.style.color = '#333';
2265
+ pageNumbersContainer.appendChild(ellipsis);
2266
+ }
2267
+ }
2268
+
2269
+ // Add page numbers
2270
+ for (let i = startPage; i <= endPage; i++) {
2271
+ addPageButton(i);
2272
+ }
2273
+
2274
+ // Add ellipsis and last page if needed
2275
+ if (endPage < totalPages) {
2276
+ if (endPage < totalPages - 1) {
2277
+ const ellipsis = document.createElement('span');
2278
+ ellipsis.textContent = '...';
2279
+ ellipsis.style.padding = '6px 8px';
2280
+ ellipsis.style.color = '#333';
2281
+ pageNumbersContainer.appendChild(ellipsis);
2282
+ }
2283
+ addPageButton(totalPages);
2284
+ }
2285
+ }
2286
+
2287
+ /**
2288
+ * Creates and adds a page number button to pagination controls
2289
+ * @param {number} pageNum - Page number for the button
2290
+ * @returns {void}
2291
+ */
2292
+ function addPageButton(pageNum) {
2293
+ const pageNumbersContainer = document.getElementById('pageNumbers');
2294
+ const btn = document.createElement('button');
2295
+ btn.className = 'pagination-btn' + (pageNum === currentPage ? ' active' : '');
2296
+ btn.textContent = pageNum;
2297
+ btn.addEventListener('click', function() {
2298
+ currentPage = pageNum;
2299
+ updatePagination();
2300
+ });
2301
+ pageNumbersContainer.appendChild(btn);
2302
+ }
2303
+ </script>
2304
+ </body>
2305
+ </html>