diff options
| author | Nate Sesti <sestinj@gmail.com> | 2023-07-24 01:00:42 -0700 | 
|---|---|---|
| committer | Nate Sesti <sestinj@gmail.com> | 2023-07-24 01:00:42 -0700 | 
| commit | 85ce06beb9b2d587b0b572117a98318d226bed61 (patch) | |
| tree | 76fc6232b5219d0bd61b547b26624641a99e7b9b /extension/react-app | |
| parent | 699a74250fd4cf91af930ff63077aeb81f74856f (diff) | |
| parent | 885f88af1d7b35e03b1de4df3e74a60da1a777ed (diff) | |
| download | sncontinue-85ce06beb9b2d587b0b572117a98318d226bed61.tar.gz sncontinue-85ce06beb9b2d587b0b572117a98318d226bed61.tar.bz2 sncontinue-85ce06beb9b2d587b0b572117a98318d226bed61.zip | |
Merge branch 'main' into show-react-immediately
Diffstat (limited to 'extension/react-app')
| -rw-r--r-- | extension/react-app/package-lock.json | 1473 | ||||
| -rw-r--r-- | extension/react-app/package.json | 2 | ||||
| -rw-r--r-- | extension/react-app/src/App.tsx | 8 | ||||
| -rw-r--r-- | extension/react-app/src/components/ComboBox.tsx | 102 | ||||
| -rw-r--r-- | extension/react-app/src/components/InputAndButton.tsx | 10 | ||||
| -rw-r--r-- | extension/react-app/src/components/Onboarding.tsx | 19 | ||||
| -rw-r--r-- | extension/react-app/src/components/PillButton.tsx | 172 | ||||
| -rw-r--r-- | extension/react-app/src/components/StepContainer.tsx | 116 | ||||
| -rw-r--r-- | extension/react-app/src/components/TextDialog.tsx | 71 | ||||
| -rw-r--r-- | extension/react-app/src/components/index.ts | 23 | ||||
| -rw-r--r-- | extension/react-app/src/hooks/AbstractContinueGUIClientProtocol.ts | 35 | ||||
| -rw-r--r-- | extension/react-app/src/hooks/ContinueGUIClientProtocol.ts | 93 | ||||
| -rw-r--r-- | extension/react-app/src/hooks/useContinueGUIProtocol.ts | 91 | ||||
| -rw-r--r-- | extension/react-app/src/hooks/useWebsocket.ts | 2 | ||||
| -rw-r--r-- | extension/react-app/src/index.css | 4 | ||||
| -rw-r--r-- | extension/react-app/src/pages/gui.tsx | 84 | ||||
| -rw-r--r-- | extension/react-app/src/util/index.ts | 43 | 
17 files changed, 1955 insertions, 393 deletions
| diff --git a/extension/react-app/package-lock.json b/extension/react-app/package-lock.json index 7316581d..13e02e86 100644 --- a/extension/react-app/package-lock.json +++ b/extension/react-app/package-lock.json @@ -11,12 +11,12 @@          "@styled-icons/heroicons-outline": "^10.47.0",          "@styled-icons/heroicons-solid": "^10.47.0",          "@types/vscode-webview": "^1.57.1", +        "@uiw/react-markdown-preview": "^4.1.13",          "downshift": "^7.6.0",          "posthog-js": "^1.58.0",          "prismjs": "^1.29.0",          "react": "^18.2.0",          "react-dom": "^18.2.0", -        "react-markdown": "^8.0.5",          "react-redux": "^8.0.5",          "react-switch": "^7.0.0",          "react-syntax-highlighter": "^15.5.0", @@ -963,6 +963,16 @@        "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",        "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="      }, +    "node_modules/@types/parse5": { +      "version": "6.0.3", +      "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", +      "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==" +    }, +    "node_modules/@types/prismjs": { +      "version": "1.26.0", +      "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz", +      "integrity": "sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==" +    },      "node_modules/@types/prop-types": {        "version": "15.7.5",        "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", @@ -1027,6 +1037,34 @@        "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.1.tgz",        "integrity": "sha512-ghW5SfuDmsGDS2A4xkvGsLwDRNc3Vj5rS6rPOyPm/IryZuf3wceZKxgYaUoW+k9f0f/CB7y2c1rRsdOWZWn0PQ=="      }, +    "node_modules/@uiw/copy-to-clipboard": { +      "version": "1.0.15", +      "resolved": "https://registry.npmjs.org/@uiw/copy-to-clipboard/-/copy-to-clipboard-1.0.15.tgz", +      "integrity": "sha512-1bbGZ3T+SGmA07BoVPK4UCUDcowDN/moctviJGQexfOc9qL8TMLDQPr7mTPvDKhgJkgnlKkAQNFU8PiarIi9sQ==" +    }, +    "node_modules/@uiw/react-markdown-preview": { +      "version": "4.1.13", +      "resolved": "https://registry.npmjs.org/@uiw/react-markdown-preview/-/react-markdown-preview-4.1.13.tgz", +      "integrity": "sha512-fmIGvBpK6HJyDFf7EokjZSIS0713Bq5KwhOsZ8IkbCMYDcDThFlmMkTTqyzGjL3phrkP9ED5O63WSILzefqe6A==", +      "dependencies": { +        "@babel/runtime": "^7.17.2", +        "@uiw/copy-to-clipboard": "~1.0.12", +        "react-markdown": "~8.0.0", +        "rehype-attr": "~2.1.0", +        "rehype-autolink-headings": "~6.1.1", +        "rehype-ignore": "^1.0.1", +        "rehype-prism-plus": "~1.5.0", +        "rehype-raw": "^6.1.1", +        "rehype-rewrite": "~3.0.6", +        "rehype-slug": "~5.1.0", +        "remark-gfm": "~3.0.1", +        "unist-util-visit": "^4.1.0" +      }, +      "peerDependencies": { +        "react": ">=16.8.0", +        "react-dom": ">=16.8.0" +      } +    },      "node_modules/@vitejs/plugin-react-swc": {        "version": "3.2.0",        "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.2.0.tgz", @@ -1163,6 +1201,15 @@          "url": "https://github.com/sponsors/wooorm"        }      }, +    "node_modules/bcp-47-match": { +      "version": "2.0.3", +      "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", +      "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    },      "node_modules/binary-extensions": {        "version": "2.2.0",        "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1172,6 +1219,11 @@          "node": ">=8"        }      }, +    "node_modules/boolbase": { +      "version": "1.0.0", +      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", +      "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" +    },      "node_modules/braces": {        "version": "3.0.2",        "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -1245,6 +1297,15 @@          }        ]      }, +    "node_modules/ccount": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", +      "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    },      "node_modules/chalk": {        "version": "2.4.2",        "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -1370,6 +1431,11 @@          "node": ">=4"        }      }, +    "node_modules/css-selector-parser": { +      "version": "1.4.1", +      "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.4.1.tgz", +      "integrity": "sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g==" +    },      "node_modules/css-to-react-native": {        "version": "3.2.0",        "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", @@ -1473,6 +1539,18 @@          "node": ">=0.3.1"        }      }, +    "node_modules/direction": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", +      "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==", +      "bin": { +        "direction": "cli.js" +      }, +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    },      "node_modules/dlv": {        "version": "1.1.3",        "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -1684,6 +1762,11 @@        "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",        "dev": true      }, +    "node_modules/github-slugger": { +      "version": "2.0.0", +      "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", +      "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" +    },      "node_modules/glob-parent": {        "version": "6.0.2",        "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -1729,6 +1812,86 @@          "node": ">=4"        }      }, +    "node_modules/hast-util-from-parse5": { +      "version": "7.1.2", +      "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", +      "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "@types/unist": "^2.0.0", +        "hastscript": "^7.0.0", +        "property-information": "^6.0.0", +        "vfile": "^5.0.0", +        "vfile-location": "^4.0.0", +        "web-namespaces": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/hast-util-from-parse5/node_modules/hast-util-parse-selector": { +      "version": "3.1.1", +      "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", +      "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", +      "dependencies": { +        "@types/hast": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/hast-util-from-parse5/node_modules/hastscript": { +      "version": "7.2.0", +      "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", +      "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "comma-separated-tokens": "^2.0.0", +        "hast-util-parse-selector": "^3.0.0", +        "property-information": "^6.0.0", +        "space-separated-tokens": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/hast-util-has-property": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-2.0.1.tgz", +      "integrity": "sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==", +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/hast-util-heading-rank": { +      "version": "2.1.1", +      "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-2.1.1.tgz", +      "integrity": "sha512-iAuRp+ESgJoRFJbSyaqsfvJDY6zzmFoEnL1gtz1+U8gKtGGj1p0CVlysuUAUjq95qlZESHINLThwJzNGmgGZxA==", +      "dependencies": { +        "@types/hast": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/hast-util-is-element": { +      "version": "2.1.3", +      "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz", +      "integrity": "sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "@types/unist": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    },      "node_modules/hast-util-parse-selector": {        "version": "2.2.5",        "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz", @@ -1738,6 +1901,83 @@          "url": "https://opencollective.com/unified"        }      }, +    "node_modules/hast-util-raw": { +      "version": "7.2.3", +      "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz", +      "integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "@types/parse5": "^6.0.0", +        "hast-util-from-parse5": "^7.0.0", +        "hast-util-to-parse5": "^7.0.0", +        "html-void-elements": "^2.0.0", +        "parse5": "^6.0.0", +        "unist-util-position": "^4.0.0", +        "unist-util-visit": "^4.0.0", +        "vfile": "^5.0.0", +        "web-namespaces": "^2.0.0", +        "zwitch": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/hast-util-select": { +      "version": "5.0.5", +      "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-5.0.5.tgz", +      "integrity": "sha512-QQhWMhgTFRhCaQdgTKzZ5g31GLQ9qRb1hZtDPMqQaOhpLBziWcshUS0uCR5IJ0U1jrK/mxg35fmcq+Dp/Cy2Aw==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "@types/unist": "^2.0.0", +        "bcp-47-match": "^2.0.0", +        "comma-separated-tokens": "^2.0.0", +        "css-selector-parser": "^1.0.0", +        "direction": "^2.0.0", +        "hast-util-has-property": "^2.0.0", +        "hast-util-to-string": "^2.0.0", +        "hast-util-whitespace": "^2.0.0", +        "not": "^0.1.0", +        "nth-check": "^2.0.0", +        "property-information": "^6.0.0", +        "space-separated-tokens": "^2.0.0", +        "unist-util-visit": "^4.0.0", +        "zwitch": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/hast-util-to-parse5": { +      "version": "7.1.0", +      "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz", +      "integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "comma-separated-tokens": "^2.0.0", +        "property-information": "^6.0.0", +        "space-separated-tokens": "^2.0.0", +        "web-namespaces": "^2.0.0", +        "zwitch": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/hast-util-to-string": { +      "version": "2.0.0", +      "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-2.0.0.tgz", +      "integrity": "sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==", +      "dependencies": { +        "@types/hast": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    },      "node_modules/hast-util-whitespace": {        "version": "2.0.1",        "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", @@ -1814,6 +2054,15 @@        "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",        "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="      }, +    "node_modules/html-void-elements": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", +      "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    },      "node_modules/inline-style-parser": {        "version": "0.1.1",        "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", @@ -1995,6 +2244,15 @@        "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",        "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="      }, +    "node_modules/longest-streak": { +      "version": "3.1.0", +      "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", +      "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    },      "node_modules/loose-envify": {        "version": "1.4.0",        "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -2019,6 +2277,15 @@          "url": "https://github.com/sponsors/wooorm"        }      }, +    "node_modules/markdown-table": { +      "version": "3.0.3", +      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", +      "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    },      "node_modules/mdast-util-definitions": {        "version": "5.1.2",        "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", @@ -2033,6 +2300,32 @@          "url": "https://opencollective.com/unified"        }      }, +    "node_modules/mdast-util-find-and-replace": { +      "version": "2.2.2", +      "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.2.tgz", +      "integrity": "sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==", +      "dependencies": { +        "@types/mdast": "^3.0.0", +        "escape-string-regexp": "^5.0.0", +        "unist-util-is": "^5.0.0", +        "unist-util-visit-parents": "^5.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { +      "version": "5.0.0", +      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", +      "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", +      "engines": { +        "node": ">=12" +      }, +      "funding": { +        "url": "https://github.com/sponsors/sindresorhus" +      } +    },      "node_modules/mdast-util-from-markdown": {        "version": "1.3.0",        "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.0.tgz", @@ -2056,6 +2349,107 @@          "url": "https://opencollective.com/unified"        }      }, +    "node_modules/mdast-util-gfm": { +      "version": "2.0.2", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz", +      "integrity": "sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==", +      "dependencies": { +        "mdast-util-from-markdown": "^1.0.0", +        "mdast-util-gfm-autolink-literal": "^1.0.0", +        "mdast-util-gfm-footnote": "^1.0.0", +        "mdast-util-gfm-strikethrough": "^1.0.0", +        "mdast-util-gfm-table": "^1.0.0", +        "mdast-util-gfm-task-list-item": "^1.0.0", +        "mdast-util-to-markdown": "^1.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/mdast-util-gfm-autolink-literal": { +      "version": "1.0.3", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.3.tgz", +      "integrity": "sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==", +      "dependencies": { +        "@types/mdast": "^3.0.0", +        "ccount": "^2.0.0", +        "mdast-util-find-and-replace": "^2.0.0", +        "micromark-util-character": "^1.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/mdast-util-gfm-footnote": { +      "version": "1.0.2", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.2.tgz", +      "integrity": "sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==", +      "dependencies": { +        "@types/mdast": "^3.0.0", +        "mdast-util-to-markdown": "^1.3.0", +        "micromark-util-normalize-identifier": "^1.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/mdast-util-gfm-strikethrough": { +      "version": "1.0.3", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.3.tgz", +      "integrity": "sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==", +      "dependencies": { +        "@types/mdast": "^3.0.0", +        "mdast-util-to-markdown": "^1.3.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/mdast-util-gfm-table": { +      "version": "1.0.7", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.7.tgz", +      "integrity": "sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==", +      "dependencies": { +        "@types/mdast": "^3.0.0", +        "markdown-table": "^3.0.0", +        "mdast-util-from-markdown": "^1.0.0", +        "mdast-util-to-markdown": "^1.3.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/mdast-util-gfm-task-list-item": { +      "version": "1.0.2", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.2.tgz", +      "integrity": "sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==", +      "dependencies": { +        "@types/mdast": "^3.0.0", +        "mdast-util-to-markdown": "^1.3.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/mdast-util-phrasing": { +      "version": "3.0.1", +      "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz", +      "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==", +      "dependencies": { +        "@types/mdast": "^3.0.0", +        "unist-util-is": "^5.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    },      "node_modules/mdast-util-to-hast": {        "version": "12.3.0",        "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", @@ -2075,6 +2469,25 @@          "url": "https://opencollective.com/unified"        }      }, +    "node_modules/mdast-util-to-markdown": { +      "version": "1.5.0", +      "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz", +      "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==", +      "dependencies": { +        "@types/mdast": "^3.0.0", +        "@types/unist": "^2.0.0", +        "longest-streak": "^3.0.0", +        "mdast-util-phrasing": "^3.0.0", +        "mdast-util-to-string": "^3.0.0", +        "micromark-util-decode-string": "^1.0.0", +        "unist-util-visit": "^4.0.0", +        "zwitch": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    },      "node_modules/mdast-util-to-string": {        "version": "3.1.1",        "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.1.tgz", @@ -2163,6 +2576,120 @@          "uvu": "^0.5.0"        }      }, +    "node_modules/micromark-extension-gfm": { +      "version": "2.0.3", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz", +      "integrity": "sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==", +      "dependencies": { +        "micromark-extension-gfm-autolink-literal": "^1.0.0", +        "micromark-extension-gfm-footnote": "^1.0.0", +        "micromark-extension-gfm-strikethrough": "^1.0.0", +        "micromark-extension-gfm-table": "^1.0.0", +        "micromark-extension-gfm-tagfilter": "^1.0.0", +        "micromark-extension-gfm-task-list-item": "^1.0.0", +        "micromark-util-combine-extensions": "^1.0.0", +        "micromark-util-types": "^1.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/micromark-extension-gfm-autolink-literal": { +      "version": "1.0.5", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.5.tgz", +      "integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==", +      "dependencies": { +        "micromark-util-character": "^1.0.0", +        "micromark-util-sanitize-uri": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/micromark-extension-gfm-footnote": { +      "version": "1.1.2", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.2.tgz", +      "integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==", +      "dependencies": { +        "micromark-core-commonmark": "^1.0.0", +        "micromark-factory-space": "^1.0.0", +        "micromark-util-character": "^1.0.0", +        "micromark-util-normalize-identifier": "^1.0.0", +        "micromark-util-sanitize-uri": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0", +        "uvu": "^0.5.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/micromark-extension-gfm-strikethrough": { +      "version": "1.0.7", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.7.tgz", +      "integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==", +      "dependencies": { +        "micromark-util-chunked": "^1.0.0", +        "micromark-util-classify-character": "^1.0.0", +        "micromark-util-resolve-all": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0", +        "uvu": "^0.5.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/micromark-extension-gfm-table": { +      "version": "1.0.7", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.7.tgz", +      "integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==", +      "dependencies": { +        "micromark-factory-space": "^1.0.0", +        "micromark-util-character": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0", +        "uvu": "^0.5.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/micromark-extension-gfm-tagfilter": { +      "version": "1.0.2", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.2.tgz", +      "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", +      "dependencies": { +        "micromark-util-types": "^1.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/micromark-extension-gfm-task-list-item": { +      "version": "1.0.5", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.5.tgz", +      "integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==", +      "dependencies": { +        "micromark-factory-space": "^1.0.0", +        "micromark-util-character": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0", +        "uvu": "^0.5.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    },      "node_modules/micromark-factory-destination": {        "version": "1.0.0",        "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz", @@ -2589,6 +3116,22 @@          "node": ">=0.10.0"        }      }, +    "node_modules/not": { +      "version": "0.1.0", +      "resolved": "https://registry.npmjs.org/not/-/not-0.1.0.tgz", +      "integrity": "sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==" +    }, +    "node_modules/nth-check": { +      "version": "2.1.1", +      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", +      "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", +      "dependencies": { +        "boolbase": "^1.0.0" +      }, +      "funding": { +        "url": "https://github.com/fb55/nth-check?sponsor=1" +      } +    },      "node_modules/object-assign": {        "version": "4.1.1",        "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2632,6 +3175,16 @@          "url": "https://github.com/sponsors/wooorm"        }      }, +    "node_modules/parse-numeric-range": { +      "version": "1.3.0", +      "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", +      "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" +    }, +    "node_modules/parse5": { +      "version": "6.0.1", +      "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", +      "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" +    },      "node_modules/path-parse": {        "version": "1.0.7",        "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -3047,6 +3600,257 @@        "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",        "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="      }, +    "node_modules/rehype-attr": { +      "version": "2.1.4", +      "resolved": "https://registry.npmjs.org/rehype-attr/-/rehype-attr-2.1.4.tgz", +      "integrity": "sha512-iAeaL5JyF4XxkcvWzpi/0SAF7iV7qOTaHS56tJuEsXziQc3+PEmMn65kV8OFgbO9mRVY7J1fRC/aLvot1PsNkg==", +      "dependencies": { +        "unified": "~10.1.1", +        "unist-util-visit": "~4.1.0" +      }, +      "engines": { +        "node": "^12.20.0 || ^14.13.1 || >=16.0.0" +      } +    }, +    "node_modules/rehype-autolink-headings": { +      "version": "6.1.1", +      "resolved": "https://registry.npmjs.org/rehype-autolink-headings/-/rehype-autolink-headings-6.1.1.tgz", +      "integrity": "sha512-NMYzZIsHM3sA14nC5rAFuUPIOfg+DFmf9EY1YMhaNlB7+3kK/ZlE6kqPfuxr1tsJ1XWkTrMtMoyHosU70d35mA==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "extend": "^3.0.0", +        "hast-util-has-property": "^2.0.0", +        "hast-util-heading-rank": "^2.0.0", +        "hast-util-is-element": "^2.0.0", +        "unified": "^10.0.0", +        "unist-util-visit": "^4.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/rehype-ignore": { +      "version": "1.0.5", +      "resolved": "https://registry.npmjs.org/rehype-ignore/-/rehype-ignore-1.0.5.tgz", +      "integrity": "sha512-JQXS5eDwXaYKwB8JEYFJJA/YvGi0sSNUOYuiURMtuPTg8tuWHFB91JMYLbImH1FyvyGQM4fIBqNMAPB50WR2Bw==", +      "dependencies": { +        "hast-util-select": "^5.0.5", +        "unified": "^10.1.2", +        "unist-util-visit": "^4.1.2" +      }, +      "engines": { +        "node": "^14.13.1 || >=16.0.0" +      } +    }, +    "node_modules/rehype-parse": { +      "version": "8.0.4", +      "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz", +      "integrity": "sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "hast-util-from-parse5": "^7.0.0", +        "parse5": "^6.0.0", +        "unified": "^10.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/rehype-prism-plus": { +      "version": "1.5.1", +      "resolved": "https://registry.npmjs.org/rehype-prism-plus/-/rehype-prism-plus-1.5.1.tgz", +      "integrity": "sha512-mowYefSfrIkMMxkb0fwuEXlvc5nA9b1vQ6mzujM81Qx28RI0mo7jCHsBZ2tJ4eIJKXdFn+EdPkZZBGB10K02vg==", +      "dependencies": { +        "hast-util-to-string": "^2.0.0", +        "parse-numeric-range": "^1.3.0", +        "refractor": "^4.7.0", +        "rehype-parse": "^8.0.2", +        "unist-util-filter": "^4.0.0", +        "unist-util-visit": "^4.0.0" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/character-entities-legacy": { +      "version": "3.0.0", +      "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", +      "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/character-reference-invalid": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", +      "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/hast-util-parse-selector": { +      "version": "3.1.1", +      "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", +      "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", +      "dependencies": { +        "@types/hast": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/hastscript": { +      "version": "7.2.0", +      "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", +      "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "comma-separated-tokens": "^2.0.0", +        "hast-util-parse-selector": "^3.0.0", +        "property-information": "^6.0.0", +        "space-separated-tokens": "^2.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/is-alphabetical": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", +      "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/is-alphanumerical": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", +      "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", +      "dependencies": { +        "is-alphabetical": "^2.0.0", +        "is-decimal": "^2.0.0" +      }, +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/is-decimal": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", +      "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/is-hexadecimal": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", +      "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/parse-entities": { +      "version": "4.0.1", +      "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", +      "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", +      "dependencies": { +        "@types/unist": "^2.0.0", +        "character-entities": "^2.0.0", +        "character-entities-legacy": "^3.0.0", +        "character-reference-invalid": "^2.0.0", +        "decode-named-character-reference": "^1.0.0", +        "is-alphanumerical": "^2.0.0", +        "is-decimal": "^2.0.0", +        "is-hexadecimal": "^2.0.0" +      }, +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    }, +    "node_modules/rehype-prism-plus/node_modules/refractor": { +      "version": "4.8.1", +      "resolved": "https://registry.npmjs.org/refractor/-/refractor-4.8.1.tgz", +      "integrity": "sha512-/fk5sI0iTgFYlmVGYVew90AoYnNMP6pooClx/XKqyeeCQXrL0Kvgn8V0VEht5ccdljbzzF1i3Q213gcntkRExg==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "@types/prismjs": "^1.0.0", +        "hastscript": "^7.0.0", +        "parse-entities": "^4.0.0" +      }, +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    }, +    "node_modules/rehype-raw": { +      "version": "6.1.1", +      "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz", +      "integrity": "sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "hast-util-raw": "^7.2.0", +        "unified": "^10.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/rehype-rewrite": { +      "version": "3.0.6", +      "resolved": "https://registry.npmjs.org/rehype-rewrite/-/rehype-rewrite-3.0.6.tgz", +      "integrity": "sha512-REDTNCvsKcAazy8IQWzKp66AhSUDSOIKssSCqNqCcT9sN7JCwAAm3mWGTUdUzq80ABuy8d0D6RBwbnewu1aY1g==", +      "dependencies": { +        "hast-util-select": "~5.0.1", +        "unified": "~10.1.1", +        "unist-util-visit": "~4.1.0" +      }, +      "engines": { +        "node": "^12.20.0 || ^14.13.1 || >=16.0.0" +      } +    }, +    "node_modules/rehype-slug": { +      "version": "5.1.0", +      "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-5.1.0.tgz", +      "integrity": "sha512-Gf91dJoXneiorNEnn+Phx97CO7oRMrpi+6r155tTxzGuLtm+QrI4cTwCa9e1rtePdL4i9tSO58PeSS6HWfgsiw==", +      "dependencies": { +        "@types/hast": "^2.0.0", +        "github-slugger": "^2.0.0", +        "hast-util-has-property": "^2.0.0", +        "hast-util-heading-rank": "^2.0.0", +        "hast-util-to-string": "^2.0.0", +        "unified": "^10.0.0", +        "unist-util-visit": "^4.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    }, +    "node_modules/remark-gfm": { +      "version": "3.0.1", +      "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", +      "integrity": "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==", +      "dependencies": { +        "@types/mdast": "^3.0.0", +        "mdast-util-gfm": "^2.0.0", +        "micromark-extension-gfm": "^2.0.0", +        "unified": "^10.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    },      "node_modules/remark-parse": {        "version": "10.0.1",        "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz", @@ -3365,6 +4169,16 @@          "url": "https://opencollective.com/unified"        }      }, +    "node_modules/unist-util-filter": { +      "version": "4.0.1", +      "resolved": "https://registry.npmjs.org/unist-util-filter/-/unist-util-filter-4.0.1.tgz", +      "integrity": "sha512-RynicUM/vbOSTSiUK+BnaK9XMfmQUh6gyi7L6taNgc7FIf84GukXVV3ucGzEN/PhUUkdP5hb1MmXc+3cvPUm5Q==", +      "dependencies": { +        "@types/unist": "^2.0.0", +        "unist-util-is": "^5.0.0", +        "unist-util-visit-parents": "^5.0.0" +      } +    },      "node_modules/unist-util-generated": {        "version": "2.0.1",        "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", @@ -3517,6 +4331,19 @@          "url": "https://opencollective.com/unified"        }      }, +    "node_modules/vfile-location": { +      "version": "4.1.0", +      "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", +      "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", +      "dependencies": { +        "@types/unist": "^2.0.0", +        "vfile": "^5.0.0" +      }, +      "funding": { +        "type": "opencollective", +        "url": "https://opencollective.com/unified" +      } +    },      "node_modules/vfile-message": {        "version": "3.1.4",        "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", @@ -3587,6 +4414,15 @@          "fs-extra": "^10.0.0"        }      }, +    "node_modules/web-namespaces": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", +      "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      } +    },      "node_modules/xtend": {        "version": "4.0.2",        "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -3603,6 +4439,15 @@        "engines": {          "node": ">= 6"        } +    }, +    "node_modules/zwitch": { +      "version": "2.0.4", +      "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", +      "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", +      "funding": { +        "type": "github", +        "url": "https://github.com/sponsors/wooorm" +      }      }    },    "dependencies": { @@ -4143,6 +4988,16 @@        "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz",        "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA=="      }, +    "@types/parse5": { +      "version": "6.0.3", +      "resolved": "https://registry.npmjs.org/@types/parse5/-/parse5-6.0.3.tgz", +      "integrity": "sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==" +    }, +    "@types/prismjs": { +      "version": "1.26.0", +      "resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.0.tgz", +      "integrity": "sha512-ZTaqn/qSqUuAq1YwvOFQfVW1AR/oQJlLSZVustdjwI+GZ8kr0MSHBj0tsXPW1EqHubx50gtBEjbPGsdZwQwCjQ==" +    },      "@types/prop-types": {        "version": "15.7.5",        "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", @@ -4207,6 +5062,30 @@        "resolved": "https://registry.npmjs.org/@types/vscode-webview/-/vscode-webview-1.57.1.tgz",        "integrity": "sha512-ghW5SfuDmsGDS2A4xkvGsLwDRNc3Vj5rS6rPOyPm/IryZuf3wceZKxgYaUoW+k9f0f/CB7y2c1rRsdOWZWn0PQ=="      }, +    "@uiw/copy-to-clipboard": { +      "version": "1.0.15", +      "resolved": "https://registry.npmjs.org/@uiw/copy-to-clipboard/-/copy-to-clipboard-1.0.15.tgz", +      "integrity": "sha512-1bbGZ3T+SGmA07BoVPK4UCUDcowDN/moctviJGQexfOc9qL8TMLDQPr7mTPvDKhgJkgnlKkAQNFU8PiarIi9sQ==" +    }, +    "@uiw/react-markdown-preview": { +      "version": "4.1.13", +      "resolved": "https://registry.npmjs.org/@uiw/react-markdown-preview/-/react-markdown-preview-4.1.13.tgz", +      "integrity": "sha512-fmIGvBpK6HJyDFf7EokjZSIS0713Bq5KwhOsZ8IkbCMYDcDThFlmMkTTqyzGjL3phrkP9ED5O63WSILzefqe6A==", +      "requires": { +        "@babel/runtime": "^7.17.2", +        "@uiw/copy-to-clipboard": "~1.0.12", +        "react-markdown": "~8.0.0", +        "rehype-attr": "~2.1.0", +        "rehype-autolink-headings": "~6.1.1", +        "rehype-ignore": "^1.0.1", +        "rehype-prism-plus": "~1.5.0", +        "rehype-raw": "^6.1.1", +        "rehype-rewrite": "~3.0.6", +        "rehype-slug": "~5.1.0", +        "remark-gfm": "~3.0.1", +        "unist-util-visit": "^4.1.0" +      } +    },      "@vitejs/plugin-react-swc": {        "version": "3.2.0",        "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.2.0.tgz", @@ -4299,12 +5178,22 @@        "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",        "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="      }, +    "bcp-47-match": { +      "version": "2.0.3", +      "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", +      "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==" +    },      "binary-extensions": {        "version": "2.2.0",        "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",        "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",        "dev": true      }, +    "boolbase": { +      "version": "1.0.0", +      "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", +      "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" +    },      "braces": {        "version": "3.0.2",        "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -4343,6 +5232,11 @@        "integrity": "sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA==",        "dev": true      }, +    "ccount": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", +      "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==" +    },      "chalk": {        "version": "2.4.2",        "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4436,6 +5330,11 @@        "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",        "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg=="      }, +    "css-selector-parser": { +      "version": "1.4.1", +      "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-1.4.1.tgz", +      "integrity": "sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g==" +    },      "css-to-react-native": {        "version": "3.2.0",        "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", @@ -4506,6 +5405,11 @@        "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz",        "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw=="      }, +    "direction": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", +      "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==" +    },      "dlv": {        "version": "1.1.3",        "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", @@ -4672,6 +5576,11 @@        "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",        "dev": true      }, +    "github-slugger": { +      "version": "2.0.0", +      "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", +      "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==" +    },      "glob-parent": {        "version": "6.0.2",        "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -4705,11 +5614,130 @@        "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",        "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="      }, +    "hast-util-from-parse5": { +      "version": "7.1.2", +      "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-7.1.2.tgz", +      "integrity": "sha512-Nz7FfPBuljzsN3tCQ4kCBKqdNhQE2l0Tn+X1ubgKBPRoiDIu1mL08Cfw4k7q71+Duyaw7DXDN+VTAp4Vh3oCOw==", +      "requires": { +        "@types/hast": "^2.0.0", +        "@types/unist": "^2.0.0", +        "hastscript": "^7.0.0", +        "property-information": "^6.0.0", +        "vfile": "^5.0.0", +        "vfile-location": "^4.0.0", +        "web-namespaces": "^2.0.0" +      }, +      "dependencies": { +        "hast-util-parse-selector": { +          "version": "3.1.1", +          "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", +          "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", +          "requires": { +            "@types/hast": "^2.0.0" +          } +        }, +        "hastscript": { +          "version": "7.2.0", +          "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", +          "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", +          "requires": { +            "@types/hast": "^2.0.0", +            "comma-separated-tokens": "^2.0.0", +            "hast-util-parse-selector": "^3.0.0", +            "property-information": "^6.0.0", +            "space-separated-tokens": "^2.0.0" +          } +        } +      } +    }, +    "hast-util-has-property": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-2.0.1.tgz", +      "integrity": "sha512-X2+RwZIMTMKpXUzlotatPzWj8bspCymtXH3cfG3iQKV+wPF53Vgaqxi/eLqGck0wKq1kS9nvoB1wchbCPEL8sg==" +    }, +    "hast-util-heading-rank": { +      "version": "2.1.1", +      "resolved": "https://registry.npmjs.org/hast-util-heading-rank/-/hast-util-heading-rank-2.1.1.tgz", +      "integrity": "sha512-iAuRp+ESgJoRFJbSyaqsfvJDY6zzmFoEnL1gtz1+U8gKtGGj1p0CVlysuUAUjq95qlZESHINLThwJzNGmgGZxA==", +      "requires": { +        "@types/hast": "^2.0.0" +      } +    }, +    "hast-util-is-element": { +      "version": "2.1.3", +      "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-2.1.3.tgz", +      "integrity": "sha512-O1bKah6mhgEq2WtVMk+Ta5K7pPMqsBBlmzysLdcwKVrqzZQ0CHqUPiIVspNhAG1rvxpvJjtGee17XfauZYKqVA==", +      "requires": { +        "@types/hast": "^2.0.0", +        "@types/unist": "^2.0.0" +      } +    },      "hast-util-parse-selector": {        "version": "2.2.5",        "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz",        "integrity": "sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ=="      }, +    "hast-util-raw": { +      "version": "7.2.3", +      "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-7.2.3.tgz", +      "integrity": "sha512-RujVQfVsOrxzPOPSzZFiwofMArbQke6DJjnFfceiEbFh7S05CbPt0cYN+A5YeD3pso0JQk6O1aHBnx9+Pm2uqg==", +      "requires": { +        "@types/hast": "^2.0.0", +        "@types/parse5": "^6.0.0", +        "hast-util-from-parse5": "^7.0.0", +        "hast-util-to-parse5": "^7.0.0", +        "html-void-elements": "^2.0.0", +        "parse5": "^6.0.0", +        "unist-util-position": "^4.0.0", +        "unist-util-visit": "^4.0.0", +        "vfile": "^5.0.0", +        "web-namespaces": "^2.0.0", +        "zwitch": "^2.0.0" +      } +    }, +    "hast-util-select": { +      "version": "5.0.5", +      "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-5.0.5.tgz", +      "integrity": "sha512-QQhWMhgTFRhCaQdgTKzZ5g31GLQ9qRb1hZtDPMqQaOhpLBziWcshUS0uCR5IJ0U1jrK/mxg35fmcq+Dp/Cy2Aw==", +      "requires": { +        "@types/hast": "^2.0.0", +        "@types/unist": "^2.0.0", +        "bcp-47-match": "^2.0.0", +        "comma-separated-tokens": "^2.0.0", +        "css-selector-parser": "^1.0.0", +        "direction": "^2.0.0", +        "hast-util-has-property": "^2.0.0", +        "hast-util-to-string": "^2.0.0", +        "hast-util-whitespace": "^2.0.0", +        "not": "^0.1.0", +        "nth-check": "^2.0.0", +        "property-information": "^6.0.0", +        "space-separated-tokens": "^2.0.0", +        "unist-util-visit": "^4.0.0", +        "zwitch": "^2.0.0" +      } +    }, +    "hast-util-to-parse5": { +      "version": "7.1.0", +      "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-7.1.0.tgz", +      "integrity": "sha512-YNRgAJkH2Jky5ySkIqFXTQiaqcAtJyVE+D5lkN6CdtOqrnkLfGYYrEcKuHOJZlp+MwjSwuD3fZuawI+sic/RBw==", +      "requires": { +        "@types/hast": "^2.0.0", +        "comma-separated-tokens": "^2.0.0", +        "property-information": "^6.0.0", +        "space-separated-tokens": "^2.0.0", +        "web-namespaces": "^2.0.0", +        "zwitch": "^2.0.0" +      } +    }, +    "hast-util-to-string": { +      "version": "2.0.0", +      "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-2.0.0.tgz", +      "integrity": "sha512-02AQ3vLhuH3FisaMM+i/9sm4OXGSq1UhOOCpTLLQtHdL3tZt7qil69r8M8iDkZYyC0HCFylcYoP+8IO7ddta1A==", +      "requires": { +        "@types/hast": "^2.0.0" +      } +    },      "hast-util-whitespace": {        "version": "2.0.1",        "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", @@ -4767,6 +5795,11 @@          }        }      }, +    "html-void-elements": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-2.0.1.tgz", +      "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==" +    },      "inline-style-parser": {        "version": "0.1.1",        "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.1.1.tgz", @@ -4880,6 +5913,11 @@        "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",        "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="      }, +    "longest-streak": { +      "version": "3.1.0", +      "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", +      "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==" +    },      "loose-envify": {        "version": "1.4.0",        "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4897,6 +5935,11 @@          "highlight.js": "~10.7.0"        }      }, +    "markdown-table": { +      "version": "3.0.3", +      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", +      "integrity": "sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==" +    },      "mdast-util-definitions": {        "version": "5.1.2",        "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", @@ -4907,6 +5950,24 @@          "unist-util-visit": "^4.0.0"        }      }, +    "mdast-util-find-and-replace": { +      "version": "2.2.2", +      "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.2.tgz", +      "integrity": "sha512-MTtdFRz/eMDHXzeK6W3dO7mXUlF82Gom4y0oOgvHhh/HXZAGvIQDUvQ0SuUx+j2tv44b8xTHOm8K/9OoRFnXKw==", +      "requires": { +        "@types/mdast": "^3.0.0", +        "escape-string-regexp": "^5.0.0", +        "unist-util-is": "^5.0.0", +        "unist-util-visit-parents": "^5.0.0" +      }, +      "dependencies": { +        "escape-string-regexp": { +          "version": "5.0.0", +          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", +          "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==" +        } +      } +    },      "mdast-util-from-markdown": {        "version": "1.3.0",        "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.0.tgz", @@ -4926,6 +5987,79 @@          "uvu": "^0.5.0"        }      }, +    "mdast-util-gfm": { +      "version": "2.0.2", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-2.0.2.tgz", +      "integrity": "sha512-qvZ608nBppZ4icQlhQQIAdc6S3Ffj9RGmzwUKUWuEICFnd1LVkN3EktF7ZHAgfcEdvZB5owU9tQgt99e2TlLjg==", +      "requires": { +        "mdast-util-from-markdown": "^1.0.0", +        "mdast-util-gfm-autolink-literal": "^1.0.0", +        "mdast-util-gfm-footnote": "^1.0.0", +        "mdast-util-gfm-strikethrough": "^1.0.0", +        "mdast-util-gfm-table": "^1.0.0", +        "mdast-util-gfm-task-list-item": "^1.0.0", +        "mdast-util-to-markdown": "^1.0.0" +      } +    }, +    "mdast-util-gfm-autolink-literal": { +      "version": "1.0.3", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.3.tgz", +      "integrity": "sha512-My8KJ57FYEy2W2LyNom4n3E7hKTuQk/0SES0u16tjA9Z3oFkF4RrC/hPAPgjlSpezsOvI8ObcXcElo92wn5IGA==", +      "requires": { +        "@types/mdast": "^3.0.0", +        "ccount": "^2.0.0", +        "mdast-util-find-and-replace": "^2.0.0", +        "micromark-util-character": "^1.0.0" +      } +    }, +    "mdast-util-gfm-footnote": { +      "version": "1.0.2", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.2.tgz", +      "integrity": "sha512-56D19KOGbE00uKVj3sgIykpwKL179QsVFwx/DCW0u/0+URsryacI4MAdNJl0dh+u2PSsD9FtxPFbHCzJ78qJFQ==", +      "requires": { +        "@types/mdast": "^3.0.0", +        "mdast-util-to-markdown": "^1.3.0", +        "micromark-util-normalize-identifier": "^1.0.0" +      } +    }, +    "mdast-util-gfm-strikethrough": { +      "version": "1.0.3", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.3.tgz", +      "integrity": "sha512-DAPhYzTYrRcXdMjUtUjKvW9z/FNAMTdU0ORyMcbmkwYNbKocDpdk+PX1L1dQgOID/+vVs1uBQ7ElrBQfZ0cuiQ==", +      "requires": { +        "@types/mdast": "^3.0.0", +        "mdast-util-to-markdown": "^1.3.0" +      } +    }, +    "mdast-util-gfm-table": { +      "version": "1.0.7", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.7.tgz", +      "integrity": "sha512-jjcpmNnQvrmN5Vx7y7lEc2iIOEytYv7rTvu+MeyAsSHTASGCCRA79Igg2uKssgOs1i1po8s3plW0sTu1wkkLGg==", +      "requires": { +        "@types/mdast": "^3.0.0", +        "markdown-table": "^3.0.0", +        "mdast-util-from-markdown": "^1.0.0", +        "mdast-util-to-markdown": "^1.3.0" +      } +    }, +    "mdast-util-gfm-task-list-item": { +      "version": "1.0.2", +      "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.2.tgz", +      "integrity": "sha512-PFTA1gzfp1B1UaiJVyhJZA1rm0+Tzn690frc/L8vNX1Jop4STZgOE6bxUhnzdVSB+vm2GU1tIsuQcA9bxTQpMQ==", +      "requires": { +        "@types/mdast": "^3.0.0", +        "mdast-util-to-markdown": "^1.3.0" +      } +    }, +    "mdast-util-phrasing": { +      "version": "3.0.1", +      "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-3.0.1.tgz", +      "integrity": "sha512-WmI1gTXUBJo4/ZmSk79Wcb2HcjPJBzM1nlI/OUWA8yk2X9ik3ffNbBGsU+09BFmXaL1IBb9fiuvq6/KMiNycSg==", +      "requires": { +        "@types/mdast": "^3.0.0", +        "unist-util-is": "^5.0.0" +      } +    },      "mdast-util-to-hast": {        "version": "12.3.0",        "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", @@ -4941,6 +6075,21 @@          "unist-util-visit": "^4.0.0"        }      }, +    "mdast-util-to-markdown": { +      "version": "1.5.0", +      "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-1.5.0.tgz", +      "integrity": "sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==", +      "requires": { +        "@types/mdast": "^3.0.0", +        "@types/unist": "^2.0.0", +        "longest-streak": "^3.0.0", +        "mdast-util-phrasing": "^3.0.0", +        "mdast-util-to-string": "^3.0.0", +        "micromark-util-decode-string": "^1.0.0", +        "unist-util-visit": "^4.0.0", +        "zwitch": "^2.0.0" +      } +    },      "mdast-util-to-string": {        "version": "3.1.1",        "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.1.tgz", @@ -5002,6 +6151,92 @@          "uvu": "^0.5.0"        }      }, +    "micromark-extension-gfm": { +      "version": "2.0.3", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-2.0.3.tgz", +      "integrity": "sha512-vb9OoHqrhCmbRidQv/2+Bc6pkP0FrtlhurxZofvOEy5o8RtuuvTq+RQ1Vw5ZDNrVraQZu3HixESqbG+0iKk/MQ==", +      "requires": { +        "micromark-extension-gfm-autolink-literal": "^1.0.0", +        "micromark-extension-gfm-footnote": "^1.0.0", +        "micromark-extension-gfm-strikethrough": "^1.0.0", +        "micromark-extension-gfm-table": "^1.0.0", +        "micromark-extension-gfm-tagfilter": "^1.0.0", +        "micromark-extension-gfm-task-list-item": "^1.0.0", +        "micromark-util-combine-extensions": "^1.0.0", +        "micromark-util-types": "^1.0.0" +      } +    }, +    "micromark-extension-gfm-autolink-literal": { +      "version": "1.0.5", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.5.tgz", +      "integrity": "sha512-z3wJSLrDf8kRDOh2qBtoTRD53vJ+CWIyo7uyZuxf/JAbNJjiHsOpG1y5wxk8drtv3ETAHutCu6N3thkOOgueWg==", +      "requires": { +        "micromark-util-character": "^1.0.0", +        "micromark-util-sanitize-uri": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0" +      } +    }, +    "micromark-extension-gfm-footnote": { +      "version": "1.1.2", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.1.2.tgz", +      "integrity": "sha512-Yxn7z7SxgyGWRNa4wzf8AhYYWNrwl5q1Z8ii+CSTTIqVkmGZF1CElX2JI8g5yGoM3GAman9/PVCUFUSJ0kB/8Q==", +      "requires": { +        "micromark-core-commonmark": "^1.0.0", +        "micromark-factory-space": "^1.0.0", +        "micromark-util-character": "^1.0.0", +        "micromark-util-normalize-identifier": "^1.0.0", +        "micromark-util-sanitize-uri": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0", +        "uvu": "^0.5.0" +      } +    }, +    "micromark-extension-gfm-strikethrough": { +      "version": "1.0.7", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.7.tgz", +      "integrity": "sha512-sX0FawVE1o3abGk3vRjOH50L5TTLr3b5XMqnP9YDRb34M0v5OoZhG+OHFz1OffZ9dlwgpTBKaT4XW/AsUVnSDw==", +      "requires": { +        "micromark-util-chunked": "^1.0.0", +        "micromark-util-classify-character": "^1.0.0", +        "micromark-util-resolve-all": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0", +        "uvu": "^0.5.0" +      } +    }, +    "micromark-extension-gfm-table": { +      "version": "1.0.7", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.7.tgz", +      "integrity": "sha512-3ZORTHtcSnMQEKtAOsBQ9/oHp9096pI/UvdPtN7ehKvrmZZ2+bbWhi0ln+I9drmwXMt5boocn6OlwQzNXeVeqw==", +      "requires": { +        "micromark-factory-space": "^1.0.0", +        "micromark-util-character": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0", +        "uvu": "^0.5.0" +      } +    }, +    "micromark-extension-gfm-tagfilter": { +      "version": "1.0.2", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.2.tgz", +      "integrity": "sha512-5XWB9GbAUSHTn8VPU8/1DBXMuKYT5uOgEjJb8gN3mW0PNW5OPHpSdojoqf+iq1xo7vWzw/P8bAHY0n6ijpXF7g==", +      "requires": { +        "micromark-util-types": "^1.0.0" +      } +    }, +    "micromark-extension-gfm-task-list-item": { +      "version": "1.0.5", +      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.5.tgz", +      "integrity": "sha512-RMFXl2uQ0pNQy6Lun2YBYT9g9INXtWJULgbt01D/x8/6yJ2qpKyzdZD3pi6UIkzF++Da49xAelVKUeUMqd5eIQ==", +      "requires": { +        "micromark-factory-space": "^1.0.0", +        "micromark-util-character": "^1.0.0", +        "micromark-util-symbol": "^1.0.0", +        "micromark-util-types": "^1.0.0", +        "uvu": "^0.5.0" +      } +    },      "micromark-factory-destination": {        "version": "1.0.0",        "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz", @@ -5217,6 +6452,19 @@        "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",        "dev": true      }, +    "not": { +      "version": "0.1.0", +      "resolved": "https://registry.npmjs.org/not/-/not-0.1.0.tgz", +      "integrity": "sha512-5PDmaAsVfnWUgTUbJ3ERwn7u79Z0dYxN9ErxCpVJJqe2RK0PJ3z+iFUxuqjwtlDDegXvtWoxD/3Fzxox7tFGWA==" +    }, +    "nth-check": { +      "version": "2.1.1", +      "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", +      "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", +      "requires": { +        "boolbase": "^1.0.0" +      } +    },      "object-assign": {        "version": "4.1.1",        "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -5248,6 +6496,16 @@          }        }      }, +    "parse-numeric-range": { +      "version": "1.3.0", +      "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz", +      "integrity": "sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ==" +    }, +    "parse5": { +      "version": "6.0.1", +      "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", +      "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" +    },      "path-parse": {        "version": "1.0.7",        "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", @@ -5510,6 +6768,190 @@        "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",        "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="      }, +    "rehype-attr": { +      "version": "2.1.4", +      "resolved": "https://registry.npmjs.org/rehype-attr/-/rehype-attr-2.1.4.tgz", +      "integrity": "sha512-iAeaL5JyF4XxkcvWzpi/0SAF7iV7qOTaHS56tJuEsXziQc3+PEmMn65kV8OFgbO9mRVY7J1fRC/aLvot1PsNkg==", +      "requires": { +        "unified": "~10.1.1", +        "unist-util-visit": "~4.1.0" +      } +    }, +    "rehype-autolink-headings": { +      "version": "6.1.1", +      "resolved": "https://registry.npmjs.org/rehype-autolink-headings/-/rehype-autolink-headings-6.1.1.tgz", +      "integrity": "sha512-NMYzZIsHM3sA14nC5rAFuUPIOfg+DFmf9EY1YMhaNlB7+3kK/ZlE6kqPfuxr1tsJ1XWkTrMtMoyHosU70d35mA==", +      "requires": { +        "@types/hast": "^2.0.0", +        "extend": "^3.0.0", +        "hast-util-has-property": "^2.0.0", +        "hast-util-heading-rank": "^2.0.0", +        "hast-util-is-element": "^2.0.0", +        "unified": "^10.0.0", +        "unist-util-visit": "^4.0.0" +      } +    }, +    "rehype-ignore": { +      "version": "1.0.5", +      "resolved": "https://registry.npmjs.org/rehype-ignore/-/rehype-ignore-1.0.5.tgz", +      "integrity": "sha512-JQXS5eDwXaYKwB8JEYFJJA/YvGi0sSNUOYuiURMtuPTg8tuWHFB91JMYLbImH1FyvyGQM4fIBqNMAPB50WR2Bw==", +      "requires": { +        "hast-util-select": "^5.0.5", +        "unified": "^10.1.2", +        "unist-util-visit": "^4.1.2" +      } +    }, +    "rehype-parse": { +      "version": "8.0.4", +      "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-8.0.4.tgz", +      "integrity": "sha512-MJJKONunHjoTh4kc3dsM1v3C9kGrrxvA3U8PxZlP2SjH8RNUSrb+lF7Y0KVaUDnGH2QZ5vAn7ulkiajM9ifuqg==", +      "requires": { +        "@types/hast": "^2.0.0", +        "hast-util-from-parse5": "^7.0.0", +        "parse5": "^6.0.0", +        "unified": "^10.0.0" +      } +    }, +    "rehype-prism-plus": { +      "version": "1.5.1", +      "resolved": "https://registry.npmjs.org/rehype-prism-plus/-/rehype-prism-plus-1.5.1.tgz", +      "integrity": "sha512-mowYefSfrIkMMxkb0fwuEXlvc5nA9b1vQ6mzujM81Qx28RI0mo7jCHsBZ2tJ4eIJKXdFn+EdPkZZBGB10K02vg==", +      "requires": { +        "hast-util-to-string": "^2.0.0", +        "parse-numeric-range": "^1.3.0", +        "refractor": "^4.7.0", +        "rehype-parse": "^8.0.2", +        "unist-util-filter": "^4.0.0", +        "unist-util-visit": "^4.0.0" +      }, +      "dependencies": { +        "character-entities-legacy": { +          "version": "3.0.0", +          "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", +          "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==" +        }, +        "character-reference-invalid": { +          "version": "2.0.1", +          "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", +          "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==" +        }, +        "hast-util-parse-selector": { +          "version": "3.1.1", +          "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", +          "integrity": "sha512-jdlwBjEexy1oGz0aJ2f4GKMaVKkA9jwjr4MjAAI22E5fM/TXVZHuS5OpONtdeIkRKqAaryQ2E9xNQxijoThSZA==", +          "requires": { +            "@types/hast": "^2.0.0" +          } +        }, +        "hastscript": { +          "version": "7.2.0", +          "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-7.2.0.tgz", +          "integrity": "sha512-TtYPq24IldU8iKoJQqvZOuhi5CyCQRAbvDOX0x1eW6rsHSxa/1i2CCiptNTotGHJ3VoHRGmqiv6/D3q113ikkw==", +          "requires": { +            "@types/hast": "^2.0.0", +            "comma-separated-tokens": "^2.0.0", +            "hast-util-parse-selector": "^3.0.0", +            "property-information": "^6.0.0", +            "space-separated-tokens": "^2.0.0" +          } +        }, +        "is-alphabetical": { +          "version": "2.0.1", +          "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", +          "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==" +        }, +        "is-alphanumerical": { +          "version": "2.0.1", +          "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", +          "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", +          "requires": { +            "is-alphabetical": "^2.0.0", +            "is-decimal": "^2.0.0" +          } +        }, +        "is-decimal": { +          "version": "2.0.1", +          "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", +          "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==" +        }, +        "is-hexadecimal": { +          "version": "2.0.1", +          "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", +          "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==" +        }, +        "parse-entities": { +          "version": "4.0.1", +          "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.1.tgz", +          "integrity": "sha512-SWzvYcSJh4d/SGLIOQfZ/CoNv6BTlI6YEQ7Nj82oDVnRpwe/Z/F1EMx42x3JAOwGBlCjeCH0BRJQbQ/opHL17w==", +          "requires": { +            "@types/unist": "^2.0.0", +            "character-entities": "^2.0.0", +            "character-entities-legacy": "^3.0.0", +            "character-reference-invalid": "^2.0.0", +            "decode-named-character-reference": "^1.0.0", +            "is-alphanumerical": "^2.0.0", +            "is-decimal": "^2.0.0", +            "is-hexadecimal": "^2.0.0" +          } +        }, +        "refractor": { +          "version": "4.8.1", +          "resolved": "https://registry.npmjs.org/refractor/-/refractor-4.8.1.tgz", +          "integrity": "sha512-/fk5sI0iTgFYlmVGYVew90AoYnNMP6pooClx/XKqyeeCQXrL0Kvgn8V0VEht5ccdljbzzF1i3Q213gcntkRExg==", +          "requires": { +            "@types/hast": "^2.0.0", +            "@types/prismjs": "^1.0.0", +            "hastscript": "^7.0.0", +            "parse-entities": "^4.0.0" +          } +        } +      } +    }, +    "rehype-raw": { +      "version": "6.1.1", +      "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-6.1.1.tgz", +      "integrity": "sha512-d6AKtisSRtDRX4aSPsJGTfnzrX2ZkHQLE5kiUuGOeEoLpbEulFF4hj0mLPbsa+7vmguDKOVVEQdHKDSwoaIDsQ==", +      "requires": { +        "@types/hast": "^2.0.0", +        "hast-util-raw": "^7.2.0", +        "unified": "^10.0.0" +      } +    }, +    "rehype-rewrite": { +      "version": "3.0.6", +      "resolved": "https://registry.npmjs.org/rehype-rewrite/-/rehype-rewrite-3.0.6.tgz", +      "integrity": "sha512-REDTNCvsKcAazy8IQWzKp66AhSUDSOIKssSCqNqCcT9sN7JCwAAm3mWGTUdUzq80ABuy8d0D6RBwbnewu1aY1g==", +      "requires": { +        "hast-util-select": "~5.0.1", +        "unified": "~10.1.1", +        "unist-util-visit": "~4.1.0" +      } +    }, +    "rehype-slug": { +      "version": "5.1.0", +      "resolved": "https://registry.npmjs.org/rehype-slug/-/rehype-slug-5.1.0.tgz", +      "integrity": "sha512-Gf91dJoXneiorNEnn+Phx97CO7oRMrpi+6r155tTxzGuLtm+QrI4cTwCa9e1rtePdL4i9tSO58PeSS6HWfgsiw==", +      "requires": { +        "@types/hast": "^2.0.0", +        "github-slugger": "^2.0.0", +        "hast-util-has-property": "^2.0.0", +        "hast-util-heading-rank": "^2.0.0", +        "hast-util-to-string": "^2.0.0", +        "unified": "^10.0.0", +        "unist-util-visit": "^4.0.0" +      } +    }, +    "remark-gfm": { +      "version": "3.0.1", +      "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-3.0.1.tgz", +      "integrity": "sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==", +      "requires": { +        "@types/mdast": "^3.0.0", +        "mdast-util-gfm": "^2.0.0", +        "micromark-extension-gfm": "^2.0.0", +        "unified": "^10.0.0" +      } +    },      "remark-parse": {        "version": "10.0.1",        "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz", @@ -5722,6 +7164,16 @@          "vfile": "^5.0.0"        }      }, +    "unist-util-filter": { +      "version": "4.0.1", +      "resolved": "https://registry.npmjs.org/unist-util-filter/-/unist-util-filter-4.0.1.tgz", +      "integrity": "sha512-RynicUM/vbOSTSiUK+BnaK9XMfmQUh6gyi7L6taNgc7FIf84GukXVV3ucGzEN/PhUUkdP5hb1MmXc+3cvPUm5Q==", +      "requires": { +        "@types/unist": "^2.0.0", +        "unist-util-is": "^5.0.0", +        "unist-util-visit-parents": "^5.0.0" +      } +    },      "unist-util-generated": {        "version": "2.0.1",        "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", @@ -5819,6 +7271,15 @@          "vfile-message": "^3.0.0"        }      }, +    "vfile-location": { +      "version": "4.1.0", +      "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-4.1.0.tgz", +      "integrity": "sha512-YF23YMyASIIJXpktBa4vIGLJ5Gs88UB/XePgqPmTa7cDA+JeO3yclbpheQYCHjVHBn/yePzrXuygIL+xbvRYHw==", +      "requires": { +        "@types/unist": "^2.0.0", +        "vfile": "^5.0.0" +      } +    },      "vfile-message": {        "version": "3.1.4",        "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", @@ -5849,6 +7310,11 @@          "fs-extra": "^10.0.0"        }      }, +    "web-namespaces": { +      "version": "2.0.1", +      "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", +      "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==" +    },      "xtend": {        "version": "4.0.2",        "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -5859,6 +7325,11 @@        "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",        "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",        "dev": true +    }, +    "zwitch": { +      "version": "2.0.4", +      "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", +      "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="      }    }  } diff --git a/extension/react-app/package.json b/extension/react-app/package.json index 4bedb813..704f520a 100644 --- a/extension/react-app/package.json +++ b/extension/react-app/package.json @@ -12,12 +12,12 @@      "@styled-icons/heroicons-outline": "^10.47.0",      "@styled-icons/heroicons-solid": "^10.47.0",      "@types/vscode-webview": "^1.57.1", +    "@uiw/react-markdown-preview": "^4.1.13",      "downshift": "^7.6.0",      "posthog-js": "^1.58.0",      "prismjs": "^1.29.0",      "react": "^18.2.0",      "react-dom": "^18.2.0", -    "react-markdown": "^8.0.5",      "react-redux": "^8.0.5",      "react-switch": "^7.0.0",      "react-syntax-highlighter": "^15.5.0", diff --git a/extension/react-app/src/App.tsx b/extension/react-app/src/App.tsx index c9bd42e0..aa462171 100644 --- a/extension/react-app/src/App.tsx +++ b/extension/react-app/src/App.tsx @@ -2,7 +2,7 @@ import DebugPanel from "./components/DebugPanel";  import GUI from "./pages/gui";  import { createContext } from "react";  import useContinueGUIProtocol from "./hooks/useWebsocket"; -import ContinueGUIClientProtocol from "./hooks/useContinueGUIProtocol"; +import ContinueGUIClientProtocol from "./hooks/ContinueGUIClientProtocol";  export const GUIClientContext = createContext<    ContinueGUIClientProtocol | undefined @@ -13,11 +13,7 @@ function App() {    return (      <GUIClientContext.Provider value={client}> -      <DebugPanel -        tabs={[ -          { element: <GUI />, title: "GUI" } -        ]} -      /> +      <DebugPanel tabs={[{ element: <GUI />, title: "GUI" }]} />      </GUIClientContext.Provider>    );  } diff --git a/extension/react-app/src/components/ComboBox.tsx b/extension/react-app/src/components/ComboBox.tsx index 7d6541c7..1e2ca135 100644 --- a/extension/react-app/src/components/ComboBox.tsx +++ b/extension/react-app/src/components/ComboBox.tsx @@ -1,30 +1,20 @@ -import React, { -  useCallback, -  useEffect, -  useImperativeHandle, -  useState, -} from "react"; +import React, { useEffect, useImperativeHandle, useState } from "react";  import { useCombobox } from "downshift";  import styled from "styled-components";  import { -  buttonColor,    defaultBorderRadius,    lightGray,    secondaryDark,    vscBackground, +  vscForeground,  } from ".";  import CodeBlock from "./CodeBlock"; -import { RangeInFile } from "../../../src/client";  import PillButton from "./PillButton";  import HeaderButtonWithText from "./HeaderButtonWithText"; -import { -  Trash, -  LockClosed, -  LockOpen, -  Plus, -  DocumentPlus, -} from "@styled-icons/heroicons-outline"; +import { DocumentPlus } from "@styled-icons/heroicons-outline";  import { HighlightedRangeContext } from "../../../schema/FullState"; +import { postVscMessage } from "../vscode"; +import { getMetaKeyLabel } from "../util";  // #region styled components  const mainInputFontSize = 13; @@ -48,21 +38,6 @@ const EmptyPillDiv = styled.div`    }  `; -const ContextDropdown = styled.div` -  position: absolute; -  padding: 4px; -  width: calc(100% - 16px - 8px); -  background-color: ${secondaryDark}; -  color: white; -  border-bottom-right-radius: ${defaultBorderRadius}; -  border-bottom-left-radius: ${defaultBorderRadius}; -  /* border: 1px solid white; */ -  border-top: none; -  margin: 8px; -  outline: 1px solid orange; -  z-index: 5; -`; -  const MainTextInput = styled.textarea`    resize: none; @@ -74,7 +49,7 @@ const MainTextInput = styled.textarea`    height: auto;    width: 100%;    background-color: ${secondaryDark}; -  color: white; +  color: ${vscForeground};    z-index: 1;    border: 1px solid transparent; @@ -96,15 +71,15 @@ const Ul = styled.ul<{        : `transform: translateY(${2 * mainInputFontSize}px);`}    position: absolute;    background: ${vscBackground}; -  background-color: ${secondaryDark}; -  color: white; +  color: ${vscForeground};    max-height: ${UlMaxHeight}px; +  width: calc(100% - 16px);    overflow-y: scroll;    overflow-x: hidden;    padding: 0;    ${({ hidden }) => hidden && "display: none;"}    border-radius: ${defaultBorderRadius}; -  border: 0.5px solid gray; +  outline: 0.5px solid gray;    z-index: 2;    // Get rid of scrollbar and its padding    scrollbar-width: none; @@ -120,6 +95,7 @@ const Li = styled.li<{    selected: boolean;    isLastItem: boolean;  }>` +  background-color: ${vscBackground};    ${({ highlighted }) => highlighted && "background: #ff000066;"}    ${({ selected }) => selected && "font-weight: bold;"}      padding: 0.5rem 0.75rem; @@ -149,10 +125,6 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {    // The position of the current command you are typing now, so the one that will be appended to history once you press enter    const [positionInHistory, setPositionInHistory] = React.useState<number>(0);    const [items, setItems] = React.useState(props.items); -  const [hoveringButton, setHoveringButton] = React.useState(false); -  const [hoveringContextDropdown, setHoveringContextDropdown] = -    React.useState(false); -  const [pinned, setPinned] = useState(false);    const [highlightedCodeSections, setHighlightedCodeSections] = React.useState(      props.highlightedCodeSections || []    ); @@ -181,6 +153,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {    useImperativeHandle(ref, () => downshiftProps, [downshiftProps]);    const [metaKeyPressed, setMetaKeyPressed] = useState(false); +  const [focused, setFocused] = useState(false);    useEffect(() => {      const handleKeyDown = (e: KeyboardEvent) => {        if (e.key === "Meta") { @@ -241,6 +214,14 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {          )} */}          {highlightedCodeSections.map((section, idx) => (            <PillButton +            warning={ +              section.range.contents.length > 4000 && section.editing +                ? "Editing such a large range may be slow" +                : undefined +            } +            onlyShowDelete={ +              highlightedCodeSections.length <= 1 || section.editing +            }              editing={section.editing}              pinned={section.pinned}              index={idx} @@ -258,15 +239,6 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {                  return newSections;                });              }} -            onHover={(val: boolean) => { -              if (val) { -                setHoveringButton(val); -              } else { -                setTimeout(() => { -                  setHoveringButton(val); -                }, 100); -              } -            }}            />          ))}          {props.highlightedCodeSections.length > 0 && @@ -276,11 +248,11 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {                  props.onToggleAddContext();                }}              > -              Highlight to Add Context +              Highlight code section              </EmptyPillDiv>            ) : (              <HeaderButtonWithText -              text="Add to Context" +              text="Add more code to context"                onClick={() => {                  props.onToggleAddContext();                }} @@ -292,7 +264,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {        <div className="flex px-2" ref={divRef} hidden={!downshiftProps.isOpen}>          <MainTextInput            disabled={props.disabled} -          placeholder="Ask a question, give instructions, or type '/' to see slash commands. ⌘⏎ to edit." +          placeholder={`Ask a question, give instructions, or type '/' to see slash commands`}            {...getInputProps({              onChange: (e) => {                const target = e.target as HTMLTextAreaElement; @@ -305,6 +277,13 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {                // setShowContextDropdown(target.value.endsWith("@"));              }, +            onFocus: (e) => { +              setFocused(true); +            }, +            onBlur: (e) => { +              setFocused(false); +              postVscMessage("blurContinueInput", {}); +            },              onKeyDown: (event) => {                if (event.key === "Enter" && event.shiftKey) {                  // Prevent Downshift's default 'Enter' behavior. @@ -359,6 +338,7 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {            })}            showAbove={showAbove()}            ulHeightPixels={ulRef.current?.getBoundingClientRect().height || 0} +          hidden={!downshiftProps.isOpen || items.length === 0}          >            {downshiftProps.isOpen &&              items.map((item, index) => ( @@ -378,29 +358,13 @@ const ComboBox = React.forwardRef((props: ComboBoxProps, ref) => {        </div>        {highlightedCodeSections.length === 0 &&          (downshiftProps.inputValue?.startsWith("/edit") || -          (metaKeyPressed && downshiftProps.inputValue?.length > 0)) && ( +          (focused && +            metaKeyPressed && +            downshiftProps.inputValue?.length > 0)) && (            <div className="text-trueGray-400 pr-4 text-xs text-right">              Inserting at cursor            </div>          )} -      <ContextDropdown -        onMouseEnter={() => { -          setHoveringContextDropdown(true); -        }} -        onMouseLeave={() => { -          setHoveringContextDropdown(false); -        }} -        hidden={true || (!hoveringContextDropdown && !hoveringButton)} -      > -        {highlightedCodeSections.map((section, idx) => ( -          <> -            <p>{section.display_name}</p> -            <CodeBlock showCopy={false} key={idx}> -              {section.range.contents} -            </CodeBlock> -          </> -        ))} -      </ContextDropdown>      </>    );  }); diff --git a/extension/react-app/src/components/InputAndButton.tsx b/extension/react-app/src/components/InputAndButton.tsx index 0a8592f2..8019d014 100644 --- a/extension/react-app/src/components/InputAndButton.tsx +++ b/extension/react-app/src/components/InputAndButton.tsx @@ -1,6 +1,6 @@  import React, { useRef } from "react";  import styled from "styled-components"; -import { vscBackground } from "."; +import { vscBackground, vscForeground } from ".";  interface InputAndButtonProps {    onUserInput: (input: string) => void; @@ -16,7 +16,7 @@ const Input = styled.input`    padding: 0.5rem;    border: 1px solid white;    background-color: ${vscBackground}; -  color: white; +  color: ${vscForeground};    border-radius: 4px;    border-top-right-radius: 0;    border-bottom-right-radius: 0; @@ -27,7 +27,7 @@ const Button = styled.button`    padding: 0.5rem;    border: 1px solid white;    background-color: ${vscBackground}; -  color: white; +  color: ${vscForeground};    border-radius: 4px;    border-top-left-radius: 0;    border-bottom-left-radius: 0; @@ -35,8 +35,8 @@ const Button = styled.button`    cursor: pointer;    &:hover { -    background-color: white; -    color: black; +    background-color: ${vscForeground}; +    color: ${vscBackground};    }  `; diff --git a/extension/react-app/src/components/Onboarding.tsx b/extension/react-app/src/components/Onboarding.tsx index 7772a25e..231c1e93 100644 --- a/extension/react-app/src/components/Onboarding.tsx +++ b/extension/react-app/src/components/Onboarding.tsx @@ -22,22 +22,17 @@ const StyledSpan = styled.span`    &:hover {      background-color: #ffffff33;    } +  white-space: nowrap;  `;  const Onboarding = () => {    const [counter, setCounter] = useState(4); -  const gifs = ["intro", "explain", "edit", "generate", "intro"]; +  const gifs = ["intro", "highlight", "question", "help"];    const topMessages = [ -    "Welcome to Continue!", -    "Answer coding questions", -    "Edit in natural language", -    "Generate files from scratch", -  ]; -  const bottomMessages = [ -    "", -    "Ask Continue about a part of your code to get another perspective", -    "Highlight a section of code and instruct Continue to refactor it", -    "Let Continue build the scaffolding of Python scripts, React components, and more", +    "Welcome!", +    "Highlight code", +    "Ask a question", +    "Use /help to learn more",    ];    useEffect(() => { @@ -107,7 +102,6 @@ const Onboarding = () => {              />            )}          </div> -        <p>{bottomMessages[counter]}</p>          <p            style={{              paddingLeft: "50px", @@ -115,6 +109,7 @@ const Onboarding = () => {              paddingBottom: "50px",              textAlign: "center",              cursor: "pointer", +            whiteSpace: "nowrap",            }}          >            <StyledSpan diff --git a/extension/react-app/src/components/PillButton.tsx b/extension/react-app/src/components/PillButton.tsx index 31d98c0f..5929d06a 100644 --- a/extension/react-app/src/components/PillButton.tsx +++ b/extension/react-app/src/components/PillButton.tsx @@ -3,15 +3,20 @@ import styled from "styled-components";  import {    StyledTooltip,    defaultBorderRadius, -  lightGray,    secondaryDark, +  vscBackground, +  vscForeground,  } from "."; -import { Trash, PaintBrush, MapPin } from "@styled-icons/heroicons-outline"; +import { +  Trash, +  PaintBrush, +  ExclamationTriangle, +} from "@styled-icons/heroicons-outline";  import { GUIClientContext } from "../App";  const Button = styled.button`    border: none; -  color: white; +  color: ${vscForeground};    background-color: ${secondaryDark};    border-radius: ${defaultBorderRadius};    padding: 8px; @@ -28,10 +33,8 @@ const GridDiv = styled.div`    height: 100%;    display: grid;    grid-gap: 0; -  grid-template-columns: 1fr 1fr;    align-items: center;    border-radius: ${defaultBorderRadius}; -  overflow: hidden;    background-color: ${secondaryDark};  `; @@ -48,6 +51,21 @@ const ButtonDiv = styled.div<{ backgroundColor: string }>`    }  `; +const CircleDiv = styled.div` +  position: absolute; +  top: -10px; +  right: -10px; +  width: 20px; +  height: 20px; +  border-radius: 50%; +  background-color: red; +  color: white; +  display: flex; +  align-items: center; +  justify-content: center; +  padding: 2px; +`; +  interface PillButtonProps {    onHover?: (arg0: boolean) => void;    onDelete?: () => void; @@ -55,6 +73,8 @@ interface PillButtonProps {    index: number;    editing: boolean;    pinned: boolean; +  warning?: string; +  onlyShowDelete?: boolean;  }  const PillButton = (props: PillButtonProps) => { @@ -63,75 +83,103 @@ const PillButton = (props: PillButtonProps) => {    return (      <> -      <Button -        style={{ -          position: "relative", -          borderColor: props.editing -            ? "#8800aa" -            : props.pinned -            ? "#ffff0099" -            : "transparent", -          borderWidth: "1px", -          borderStyle: "solid", -        }} -        onMouseEnter={() => { -          setIsHovered(true); -          if (props.onHover) { -            props.onHover(true); -          } -        }} -        onMouseLeave={() => { -          setIsHovered(false); -          if (props.onHover) { -            props.onHover(false); -          } -        }} -      > -        {isHovered && ( -          <GridDiv> -            <ButtonDiv -              data-tooltip-id={`edit-${props.index}`} -              backgroundColor={"#8800aa55"} -              onClick={() => { -                client?.setEditingAtIndices([props.index]); +      <div style={{ position: "relative" }}> +        <Button +          style={{ +            position: "relative", +            borderColor: props.warning +              ? "red" +              : props.editing +              ? "#8800aa" +              : props.pinned +              ? "#ffff0099" +              : "transparent", +            borderWidth: "1px", +            borderStyle: "solid", +          }} +          onMouseEnter={() => { +            setIsHovered(true); +            if (props.onHover) { +              props.onHover(true); +            } +          }} +          onMouseLeave={() => { +            setIsHovered(false); +            if (props.onHover) { +              props.onHover(false); +            } +          }} +        > +          {isHovered && ( +            <GridDiv +              style={{ +                gridTemplateColumns: props.onlyShowDelete ? "1fr" : "1fr 1fr", +                backgroundColor: vscBackground,                }}              > -              <PaintBrush style={{ margin: "auto" }} width="1.6em"></PaintBrush> -            </ButtonDiv> +              {props.onlyShowDelete || ( +                <ButtonDiv +                  data-tooltip-id={`edit-${props.index}`} +                  backgroundColor={"#8800aa55"} +                  onClick={() => { +                    client?.setEditingAtIndices([props.index]); +                  }} +                > +                  <PaintBrush +                    style={{ margin: "auto" }} +                    width="1.6em" +                  ></PaintBrush> +                </ButtonDiv> +              )} -            {/* <ButtonDiv +              {/* <ButtonDiv              data-tooltip-id={`pin-${props.index}`}              backgroundColor={"#ffff0055"}              onClick={() => {                client?.setPinnedAtIndices([props.index]);              }} -          > +            >              <MapPin style={{ margin: "auto" }} width="1.6em"></MapPin>            </ButtonDiv> */} -            <StyledTooltip id={`pin-${props.index}`}> -              Edit this range +              <StyledTooltip id={`pin-${props.index}`}> +                Edit this range +              </StyledTooltip> +              <ButtonDiv +                data-tooltip-id={`delete-${props.index}`} +                backgroundColor={"#cc000055"} +                onClick={() => { +                  if (props.onDelete) { +                    props.onDelete(); +                  } +                }} +              > +                <Trash style={{ margin: "auto" }} width="1.6em"></Trash> +              </ButtonDiv> +            </GridDiv> +          )} +          {props.title} +        </Button> +        <StyledTooltip id={`edit-${props.index}`}> +          {props.editing +            ? "Editing this section (with entire file as context)" +            : "Edit this section"} +        </StyledTooltip> +        <StyledTooltip id={`delete-${props.index}`}>Delete</StyledTooltip> +        {props.warning && ( +          <> +            <CircleDiv data-tooltip-id={`circle-div-${props.title}`}> +              <ExclamationTriangle +                style={{ margin: "auto" }} +                width="1.0em" +                strokeWidth={2} +              /> +            </CircleDiv> +            <StyledTooltip id={`circle-div-${props.title}`}> +              {props.warning}              </StyledTooltip> -            <ButtonDiv -              data-tooltip-id={`delete-${props.index}`} -              backgroundColor={"#cc000055"} -              onClick={() => { -                if (props.onDelete) { -                  props.onDelete(); -                } -              }} -            > -              <Trash style={{ margin: "auto" }} width="1.6em"></Trash> -            </ButtonDiv> -          </GridDiv> +          </>          )} -        {props.title} -      </Button> -      <StyledTooltip id={`edit-${props.index}`}> -        {props.editing -          ? "Editing this range (with rest of file as context)" -          : "Edit this range"} -      </StyledTooltip> -      <StyledTooltip id={`delete-${props.index}`}>Delete</StyledTooltip> +      </div>      </>    );  }; diff --git a/extension/react-app/src/components/StepContainer.tsx b/extension/react-app/src/components/StepContainer.tsx index d1a8a46a..bc8665fd 100644 --- a/extension/react-app/src/components/StepContainer.tsx +++ b/extension/react-app/src/components/StepContainer.tsx @@ -1,4 +1,4 @@ -import { useCallback, useEffect, useRef, useState } from "react"; +import { useContext, useEffect, useRef, useState } from "react";  import styled, { keyframes } from "styled-components";  import {    appear, @@ -6,18 +6,21 @@ import {    secondaryDark,    vscBackground,    vscBackgroundTransparent, +  vscForeground,  } from ".";  import {    ChevronDown,    ChevronRight,    ArrowPath,    XMark, +  MagnifyingGlass,  } from "@styled-icons/heroicons-outline";  import { StopCircle } from "@styled-icons/heroicons-solid";  import { HistoryNode } from "../../../schema/HistoryNode"; -import ReactMarkdown from "react-markdown";  import HeaderButtonWithText from "./HeaderButtonWithText"; -import CodeBlock from "./CodeBlock"; +import MarkdownPreview from "@uiw/react-markdown-preview"; +import { getMetaKeyLabel, isMetaEquivalentKeyPressed } from "../util"; +import { GUIClientContext } from "../App";  interface StepContainerProps {    historyNode: HistoryNode; @@ -31,6 +34,7 @@ interface StepContainerProps {    onToggle: () => void;    isFirst: boolean;    isLast: boolean; +  index: number;  }  // #region styled components @@ -38,7 +42,6 @@ interface StepContainerProps {  const MainDiv = styled.div<{ stepDepth: number; inFuture: boolean }>`    opacity: ${(props) => (props.inFuture ? 0.3 : 1)};    animation: ${appear} 0.3s ease-in-out; -  /* padding-left: ${(props) => props.stepDepth * 20}px; */    overflow: hidden;    margin-left: 0px;    margin-right: 0px; @@ -52,12 +55,7 @@ const StepContainerDiv = styled.div<{ open: boolean }>`  `;  const HeaderDiv = styled.div<{ error: boolean; loading: boolean }>` -  background-color: ${(props) => -    props.error -      ? "#522" -      : props.loading -      ? vscBackgroundTransparent -      : vscBackground}; +  background-color: ${(props) => (props.error ? "#522" : vscBackground)};    display: grid;    grid-template-columns: 1fr auto auto;    grid-gap: 8px; @@ -72,19 +70,6 @@ const ContentDiv = styled.div<{ isUserInput: boolean }>`    font-size: 13px;  `; -const MarkdownPre = styled.pre` -  background-color: ${secondaryDark}; -  padding: 10px; -  border-radius: ${defaultBorderRadius}; -  border: 0.5px solid white; -`; - -const StyledCode = styled.code` -  word-wrap: break-word; -  color: #f69292; -  background: transparent; -`; -  const gradient = keyframes`    0% {      background-position: 0px 0; @@ -124,6 +109,33 @@ const GradientBorder = styled.div<{    background-size: 200% 200%;  `; +const StyledMarkdownPreview = styled(MarkdownPreview)` +  pre { +    background-color: ${secondaryDark}; +    padding: 1px; +    border-radius: ${defaultBorderRadius}; +    border: 0.5px solid white; +  } + +  code { +    color: #f78383; +    word-wrap: break-word; +    border-radius: ${defaultBorderRadius}; +    background-color: ${secondaryDark}; +  } + +  pre > code { +    background-color: ${secondaryDark}; +    color: ${vscForeground}; +  } + +  background-color: ${vscBackground}; +  font-family: "Lexend", sans-serif; +  font-size: 13px; +  padding: 8px; +  color: ${vscForeground}; +`; +  // #endregion  function StepContainer(props: StepContainerProps) { @@ -131,6 +143,7 @@ function StepContainer(props: StepContainerProps) {    const naturalLanguageInputRef = useRef<HTMLTextAreaElement>(null);    const userInputRef = useRef<HTMLInputElement>(null);    const isUserInput = props.historyNode.step.name === "UserInputStep"; +  const client = useContext(GUIClientContext);    useEffect(() => {      if (userInputRef?.current) { @@ -158,7 +171,7 @@ function StepContainer(props: StepContainerProps) {      >        <StepContainerDiv open={props.open}>          <GradientBorder -          loading={props.historyNode.active as boolean || false} +          loading={(props.historyNode.active as boolean) || false}            isFirst={props.isFirst}            isLast={props.isLast}            borderColor={ @@ -170,7 +183,7 @@ function StepContainer(props: StepContainerProps) {            }            className="overflow-hidden cursor-pointer"            onClick={(e) => { -            if (e.metaKey) { +            if (isMetaEquivalentKeyPressed(e)) {                props.onToggleAll();              } else {                props.onToggle(); @@ -178,7 +191,7 @@ function StepContainer(props: StepContainerProps) {            }}          >            <HeaderDiv -            loading={props.historyNode.active as boolean || false} +            loading={(props.historyNode.active as boolean) || false}              error={props.historyNode.observation?.error ? true : false}            >              <div className="m-2"> @@ -201,12 +214,27 @@ function StepContainer(props: StepContainerProps) {              </HeaderButton> */}              <> +              {(props.historyNode.logs as any)?.length > 0 && ( +                <HeaderButtonWithText +                  text="Logs" +                  onClick={(e) => { +                    e.stopPropagation(); +                    client?.showLogsAtIndex(props.index); +                  }} +                > +                  <MagnifyingGlass size="1.4em" /> +                </HeaderButtonWithText> +              )}                <HeaderButtonWithText                  onClick={(e) => {                    e.stopPropagation();                    props.onDelete();                  }} -                text={props.historyNode.active ? "Stop (⌘⌫)" : "Delete"} +                text={ +                  props.historyNode.active +                    ? `Stop (${getMetaKeyLabel()}⌫)` +                    : "Delete" +                }                >                  {props.historyNode.active ? (                    <StopCircle size="1.6em" onClick={props.onDelete} /> @@ -242,31 +270,19 @@ function StepContainer(props: StepContainerProps) {            )}            {props.historyNode.observation?.error ? ( -            <pre className="overflow-x-scroll"> -              {props.historyNode.observation.error as string} -            </pre> +            <details> +              <summary>View Traceback</summary> +              <pre className="overflow-x-scroll"> +                {props.historyNode.observation.error as string} +              </pre> +            </details>            ) : ( -            <ReactMarkdown -              key={1} -              className="overflow-x-scroll" -              components={{ -                pre: ({ node, ...props }) => { -                  return ( -                    <CodeBlock -                      children={(props.children[0] as any).props.children[0]} -                    /> -                  ); -                }, -                code: ({ node, ...props }) => { -                  return <StyledCode children={props.children[0] as any} />; -                }, -                ul: ({ node, ...props }) => { -                  return <ul className="ml-0" {...props} />; -                }, +            <StyledMarkdownPreview +              source={props.historyNode.step.description || ""} +              wrapperElement={{ +                "data-color-mode": "dark",                }} -            > -              {props.historyNode.step.description as any} -            </ReactMarkdown> +            />            )}          </ContentDiv>        </StepContainerDiv> diff --git a/extension/react-app/src/components/TextDialog.tsx b/extension/react-app/src/components/TextDialog.tsx index ea5727f0..9597b578 100644 --- a/extension/react-app/src/components/TextDialog.tsx +++ b/extension/react-app/src/components/TextDialog.tsx @@ -1,7 +1,9 @@  // Write a component that displays a dialog box with a text field and a button.  import React, { useEffect, useState } from "react";  import styled from "styled-components"; -import { Button, buttonColor, secondaryDark, vscBackground } from "."; +import { Button, secondaryDark, vscBackground, vscForeground } from "."; +import { isMetaEquivalentKeyPressed } from "../util"; +import { ReactMarkdown } from "react-markdown/lib/react-markdown";  const ScreenCover = styled.div`    position: absolute; @@ -20,13 +22,13 @@ const DialogContainer = styled.div`  `;  const Dialog = styled.div` -  background-color: white; +  color: ${vscForeground}; +  background-color: ${vscBackground};    border-radius: 8px;    padding: 8px;    display: flex;    flex-direction: column; -  /* box-shadow: 0 0 10px 0 rgba(255, 255, 255, 0.5); */ -  border: 2px solid ${buttonColor}; +  box-shadow: 0 0 10px 0 ${vscForeground};    width: fit-content;    margin: auto;  `; @@ -37,14 +39,16 @@ const TextArea = styled.textarea`    padding: 8px;    outline: 1px solid black;    resize: none; +  background-color: ${secondaryDark}; +  color: ${vscForeground};    &:focus { -    outline: 1px solid ${buttonColor}; +    outline: 1px solid ${vscForeground};    }  `;  const P = styled.p` -  color: black; +  color: ${vscForeground};    margin: 8px auto;  `; @@ -53,6 +57,7 @@ const TextDialog = (props: {    onEnter: (text: string) => void;    onClose: () => void;    message?: string; +  entryOn?: boolean;  }) => {    const [text, setText] = useState("");    const textAreaRef = React.createRef<HTMLTextAreaElement>(); @@ -76,29 +81,37 @@ const TextDialog = (props: {          }}        >          <Dialog> -          <P>{props.message || ""}</P> -          <TextArea -            rows={10} -            ref={textAreaRef} -            onKeyDown={(e) => { -              if (e.key === "Enter" && e.metaKey && textAreaRef.current) { -                props.onEnter(textAreaRef.current.value); -                setText(""); -              } else if (e.key === "Escape") { -                props.onClose(); -              } -            }} -          /> -          <Button -            onClick={() => { -              if (textAreaRef.current) { -                props.onEnter(textAreaRef.current.value); -                setText(""); -              } -            }} -          > -            Enter -          </Button> +          <ReactMarkdown>{props.message || ""}</ReactMarkdown> +          {props.entryOn && ( +            <> +              <TextArea +                rows={10} +                ref={textAreaRef} +                onKeyDown={(e) => { +                  if ( +                    e.key === "Enter" && +                    isMetaEquivalentKeyPressed(e) && +                    textAreaRef.current +                  ) { +                    props.onEnter(textAreaRef.current.value); +                    setText(""); +                  } else if (e.key === "Escape") { +                    props.onClose(); +                  } +                }} +              /> +              <Button +                onClick={() => { +                  if (textAreaRef.current) { +                    props.onEnter(textAreaRef.current.value); +                    setText(""); +                  } +                }} +              > +                Enter +              </Button> +            </> +          )}          </Dialog>        </DialogContainer>      </ScreenCover> diff --git a/extension/react-app/src/components/index.ts b/extension/react-app/src/components/index.ts index 9ae0f097..cb5e7915 100644 --- a/extension/react-app/src/components/index.ts +++ b/extension/react-app/src/components/index.ts @@ -3,12 +3,16 @@ import styled, { keyframes } from "styled-components";  export const defaultBorderRadius = "5px";  export const lightGray = "rgb(100 100 100)"; -export const secondaryDark = "rgb(45 45 45)"; -export const vscBackground = "rgb(30 30 30)"; +// export const secondaryDark = "rgb(45 45 45)"; +// export const vscBackground = "rgb(30 30 30)";  export const vscBackgroundTransparent = "#1e1e1ede";  export const buttonColor = "rgb(113 28 59)";  export const buttonColorHover = "rgb(113 28 59 0.67)"; +export const secondaryDark = "var(--vscode-textBlockQuote-background)"; +export const vscBackground = "var(--vscode-editor-background)"; +export const vscForeground = "var(--vscode-editor-foreground)"; +  export const Button = styled.button`    padding: 10px 12px;    margin: 8px 0; @@ -46,8 +50,8 @@ export const TextArea = styled.textarea`    resize: vertical;    padding: 4px; -  caret-color: white; -  color: white; +  caret-color: ${vscForeground}; +  color: #{vscForeground};    &:focus {      outline: 1px solid ${buttonColor}; @@ -120,7 +124,7 @@ export const MainTextInput = styled.textarea`    border: 1px solid #ccc;    margin: 8px 8px;    background-color: ${vscBackground}; -  color: white; +  color: ${vscForeground};    outline: 1px solid orange;    resize: none;  `; @@ -137,8 +141,9 @@ export const appear = keyframes`  `;  export const HeaderButton = styled.button<{ inverted: boolean | undefined }>` -  background-color: ${({ inverted }) => (inverted ? "white" : "transparent")}; -  color: ${({ inverted }) => (inverted ? "black" : "white")}; +  background-color: ${({ inverted }) => +    inverted ? vscForeground : "transparent"}; +  color: ${({ inverted }) => (inverted ? vscBackground : vscForeground)};    border: none;    border-radius: ${defaultBorderRadius}; @@ -146,7 +151,9 @@ export const HeaderButton = styled.button<{ inverted: boolean | undefined }>`    &:hover {      background-color: ${({ inverted }) => -      typeof inverted === "undefined" || inverted ? lightGray : "transparent"}; +      typeof inverted === "undefined" || inverted +        ? secondaryDark +        : "transparent"};    }    display: flex;    align-items: center; diff --git a/extension/react-app/src/hooks/AbstractContinueGUIClientProtocol.ts b/extension/react-app/src/hooks/AbstractContinueGUIClientProtocol.ts new file mode 100644 index 00000000..6c0df8fc --- /dev/null +++ b/extension/react-app/src/hooks/AbstractContinueGUIClientProtocol.ts @@ -0,0 +1,35 @@ +abstract class AbstractContinueGUIClientProtocol { +  abstract sendMainInput(input: string): void; + +  abstract reverseToIndex(index: number): void; + +  abstract sendRefinementInput(input: string, index: number): void; + +  abstract sendStepUserInput(input: string, index: number): void; + +  abstract onStateUpdate(state: any): void; + +  abstract onAvailableSlashCommands( +    callback: (commands: { name: string; description: string }[]) => void +  ): void; + +  abstract changeDefaultModel(model: string): void; + +  abstract sendClear(): void; + +  abstract retryAtIndex(index: number): void; + +  abstract deleteAtIndex(index: number): void; + +  abstract deleteContextAtIndices(indices: number[]): void; + +  abstract setEditingAtIndices(indices: number[]): void; + +  abstract setPinnedAtIndices(indices: number[]): void; + +  abstract toggleAddingHighlightedCode(): void; + +  abstract showLogsAtIndex(index: number): void; +} + +export default AbstractContinueGUIClientProtocol; diff --git a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts index a179c2bf..7d6c2a71 100644 --- a/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts +++ b/extension/react-app/src/hooks/ContinueGUIClientProtocol.ts @@ -1,33 +1,92 @@ -abstract class AbstractContinueGUIClientProtocol { -  abstract sendMainInput(input: string): void; +import AbstractContinueGUIClientProtocol from "./AbstractContinueGUIClientProtocol"; +import { Messenger, WebsocketMessenger } from "./messenger"; +import { VscodeMessenger } from "./vscodeMessenger"; -  abstract reverseToIndex(index: number): void; +class ContinueGUIClientProtocol extends AbstractContinueGUIClientProtocol { +  messenger: Messenger; +  // Server URL must contain the session ID param +  serverUrlWithSessionId: string; -  abstract sendRefinementInput(input: string, index: number): void; +  constructor( +    serverUrlWithSessionId: string, +    useVscodeMessagePassing: boolean +  ) { +    super(); +    this.serverUrlWithSessionId = serverUrlWithSessionId; +    this.messenger = useVscodeMessagePassing +      ? new VscodeMessenger(serverUrlWithSessionId) +      : new WebsocketMessenger(serverUrlWithSessionId); +  } -  abstract sendStepUserInput(input: string, index: number): void; +  sendMainInput(input: string) { +    this.messenger.send("main_input", { input }); +  } -  abstract onStateUpdate(state: any): void; +  reverseToIndex(index: number) { +    this.messenger.send("reverse_to_index", { index }); +  } -  abstract onAvailableSlashCommands( +  sendRefinementInput(input: string, index: number) { +    this.messenger.send("refinement_input", { input, index }); +  } + +  sendStepUserInput(input: string, index: number) { +    this.messenger.send("step_user_input", { input, index }); +  } + +  onStateUpdate(callback: (state: any) => void) { +    this.messenger.onMessageType("state_update", (data: any) => { +      if (data.state) { +        callback(data.state); +      } +    }); +  } + +  onAvailableSlashCommands(      callback: (commands: { name: string; description: string }[]) => void -  ): void; +  ) { +    this.messenger.onMessageType("available_slash_commands", (data: any) => { +      if (data.commands) { +        callback(data.commands); +      } +    }); +  } + +  changeDefaultModel(model: string) { +    this.messenger.send("change_default_model", { model }); +  } -  abstract changeDefaultModel(model: string): void; +  sendClear() { +    this.messenger.send("clear_history", {}); +  } -  abstract sendClear(): void; +  retryAtIndex(index: number) { +    this.messenger.send("retry_at_index", { index }); +  } -  abstract retryAtIndex(index: number): void; +  deleteAtIndex(index: number) { +    this.messenger.send("delete_at_index", { index }); +  } -  abstract deleteAtIndex(index: number): void; +  deleteContextAtIndices(indices: number[]) { +    this.messenger.send("delete_context_at_indices", { indices }); +  } -  abstract deleteContextAtIndices(indices: number[]): void; +  setEditingAtIndices(indices: number[]) { +    this.messenger.send("set_editing_at_indices", { indices }); +  } -  abstract setEditingAtIndices(indices: number[]): void; +  setPinnedAtIndices(indices: number[]) { +    this.messenger.send("set_pinned_at_indices", { indices }); +  } -  abstract setPinnedAtIndices(indices: number[]): void; +  toggleAddingHighlightedCode(): void { +    this.messenger.send("toggle_adding_highlighted_code", {}); +  } -  abstract toggleAddingHighlightedCode(): void; +  showLogsAtIndex(index: number): void { +    this.messenger.send("show_logs_at_index", { index }); +  }  } -export default AbstractContinueGUIClientProtocol; +export default ContinueGUIClientProtocol; diff --git a/extension/react-app/src/hooks/useContinueGUIProtocol.ts b/extension/react-app/src/hooks/useContinueGUIProtocol.ts deleted file mode 100644 index 2060dd7f..00000000 --- a/extension/react-app/src/hooks/useContinueGUIProtocol.ts +++ /dev/null @@ -1,91 +0,0 @@ -import AbstractContinueGUIClientProtocol from "./ContinueGUIClientProtocol"; -// import { Messenger, WebsocketMessenger } from "../../../src/util/messenger"; -import { Messenger, WebsocketMessenger } from "./messenger"; -import { VscodeMessenger } from "./vscodeMessenger"; - -class ContinueGUIClientProtocol extends AbstractContinueGUIClientProtocol { -  messenger: Messenger; -  // Server URL must contain the session ID param -  serverUrlWithSessionId: string; - -  constructor( -    serverUrlWithSessionId: string, -    useVscodeMessagePassing: boolean -  ) { -    super(); -    this.serverUrlWithSessionId = serverUrlWithSessionId; -    if (useVscodeMessagePassing) { -      this.messenger = new VscodeMessenger(serverUrlWithSessionId); -    } else { -      this.messenger = new WebsocketMessenger(serverUrlWithSessionId); -    } -  } - -  sendMainInput(input: string) { -    this.messenger.send("main_input", { input }); -  } - -  reverseToIndex(index: number) { -    this.messenger.send("reverse_to_index", { index }); -  } - -  sendRefinementInput(input: string, index: number) { -    this.messenger.send("refinement_input", { input, index }); -  } - -  sendStepUserInput(input: string, index: number) { -    this.messenger.send("step_user_input", { input, index }); -  } - -  onStateUpdate(callback: (state: any) => void) { -    this.messenger.onMessageType("state_update", (data: any) => { -      if (data.state) { -        callback(data.state); -      } -    }); -  } - -  onAvailableSlashCommands( -    callback: (commands: { name: string; description: string }[]) => void -  ) { -    this.messenger.onMessageType("available_slash_commands", (data: any) => { -      if (data.commands) { -        callback(data.commands); -      } -    }); -  } - -  changeDefaultModel(model: string) { -    this.messenger.send("change_default_model", { model }); -  } - -  sendClear() { -    this.messenger.send("clear_history", {}); -  } - -  retryAtIndex(index: number) { -    this.messenger.send("retry_at_index", { index }); -  } - -  deleteAtIndex(index: number) { -    this.messenger.send("delete_at_index", { index }); -  } - -  deleteContextAtIndices(indices: number[]) { -    this.messenger.send("delete_context_at_indices", { indices }); -  } - -  setEditingAtIndices(indices: number[]) { -    this.messenger.send("set_editing_at_indices", { indices }); -  } - -  setPinnedAtIndices(indices: number[]) { -    this.messenger.send("set_pinned_at_indices", { indices }); -  } - -  toggleAddingHighlightedCode(): void { -    this.messenger.send("toggle_adding_highlighted_code", {}); -  } -} - -export default ContinueGUIClientProtocol; diff --git a/extension/react-app/src/hooks/useWebsocket.ts b/extension/react-app/src/hooks/useWebsocket.ts index e762666f..6b36be97 100644 --- a/extension/react-app/src/hooks/useWebsocket.ts +++ b/extension/react-app/src/hooks/useWebsocket.ts @@ -1,7 +1,7 @@  import React, { useEffect, useState } from "react";  import { RootStore } from "../redux/store";  import { useSelector } from "react-redux"; -import ContinueGUIClientProtocol from "./useContinueGUIProtocol"; +import ContinueGUIClientProtocol from "./ContinueGUIClientProtocol";  import { postVscMessage } from "../vscode";  function useContinueGUIProtocol(useVscodeMessagePassing: boolean = true) { diff --git a/extension/react-app/src/index.css b/extension/react-app/src/index.css index 6e33c89c..bac7fe97 100644 --- a/extension/react-app/src/index.css +++ b/extension/react-app/src/index.css @@ -14,13 +14,13 @@ html,  body,  #root {    height: 100%; -  background-color: var(--vsc-background); +  background-color: var(--vscode-editor-background);    font-family: "Lexend", sans-serif;  }  body {    padding: 0; -  color: white; +  color: var(--vscode-editor-foreground);    padding: 0px;    margin: 0px;    height: 100%; diff --git a/extension/react-app/src/pages/gui.tsx b/extension/react-app/src/pages/gui.tsx index 4ff260fa..49f41dcf 100644 --- a/extension/react-app/src/pages/gui.tsx +++ b/extension/react-app/src/pages/gui.tsx @@ -1,5 +1,9 @@  import styled from "styled-components"; -import { defaultBorderRadius } from "../components"; +import { +  defaultBorderRadius, +  vscBackground, +  vscForeground, +} from "../components";  import Loader from "../components/Loader";  import ContinueButton from "../components/ContinueButton";  import { FullState, HighlightedRangeContext } from "../../../schema/FullState"; @@ -23,6 +27,7 @@ import { RootStore } from "../redux/store";  import { postVscMessage } from "../vscode";  import UserInputContainer from "../components/UserInputContainer";  import Onboarding from "../components/Onboarding"; +import { isMetaEquivalentKeyPressed } from "../util";  const TopGUIDiv = styled.div`    overflow: hidden; @@ -70,7 +75,6 @@ function GUI(props: GUIProps) {      }    }, [dataSwitchOn]); -  const [usingFastModel, setUsingFastModel] = useState(false);    const [waitingForSteps, setWaitingForSteps] = useState(false);    const [userInputQueue, setUserInputQueue] = useState<string[]>([]);    const [highlightedRanges, setHighlightedRanges] = useState< @@ -95,11 +99,8 @@ function GUI(props: GUIProps) {            name: "Welcome to Continue",            hide: false,            description: `- Highlight code and ask a question or give instructions -- Use \`cmd+k\` (Mac) / \`ctrl+k\` (Windows) to open Continue -- Use \`cmd+shift+e\` / \`ctrl+shift+e\` to open file Explorer -- Add your own OpenAI API key to VS Code Settings with \`cmd+,\` -- Use slash commands when you want fine-grained control -- Past steps are included as part of the context by default`, +          - Use \`cmd+m\` (Mac) / \`ctrl+m\` (Windows) to open Continue +          - Use \`/help\` to ask questions about how to use Continue`,            system_message: null,            chat_context: [],            manage_own_chat_context: false, @@ -115,6 +116,7 @@ function GUI(props: GUIProps) {    const [showFeedbackDialog, setShowFeedbackDialog] = useState(false);    const [feedbackDialogMessage, setFeedbackDialogMessage] = useState(""); +  const [feedbackEntryOn, setFeedbackEntryOn] = useState(true);    const topGuiDivRef = useRef<HTMLDivElement>(null); @@ -138,14 +140,11 @@ function GUI(props: GUIProps) {    }, [topGuiDivRef.current, scrollTimeout]);    useEffect(() => { +    // Cmd + Backspace to delete current step      const listener = (e: any) => { -      // Cmd + i to toggle fast model -      if (e.key === "i" && e.metaKey && e.shiftKey) { -        setUsingFastModel((prev) => !prev); -        // Cmd + backspace to stop currently running step -      } else if ( +      if (          e.key === "Backspace" && -        e.metaKey && +        isMetaEquivalentKeyPressed(e) &&          typeof history?.current_index !== "undefined" &&          history.timeline[history.current_index]?.active        ) { @@ -162,7 +161,6 @@ function GUI(props: GUIProps) {    useEffect(() => {      client?.onStateUpdate((state: FullState) => {        // Scroll only if user is at very bottom of the window. -      setUsingFastModel(state.default_model === "gpt-3.5-turbo");        const shouldScrollToBottom =          topGuiDivRef.current &&          topGuiDivRef.current?.offsetHeight - window.scrollY < 100; @@ -223,7 +221,7 @@ function GUI(props: GUIProps) {      if (mainTextInputRef.current) {        let input = (mainTextInputRef.current as any).inputValue;        // cmd+enter to /edit -      if (event?.metaKey) { +      if (isMetaEquivalentKeyPressed(event)) {          input = `/edit ${input}`;        }        (mainTextInputRef.current as any).setInputValue(""); @@ -269,15 +267,18 @@ function GUI(props: GUIProps) {    return (      <>        <Onboarding /> -      <TextDialog showDialog={showFeedbackDialog} -      onEnter={(text) => { -        client?.sendMainInput(`/feedback ${text}`); -        setShowFeedbackDialog(false); -      }} -      onClose={() => { -        setShowFeedbackDialog(false); -      }} -      message={feedbackDialogMessage} /> +      <TextDialog +        showDialog={showFeedbackDialog} +        onEnter={(text) => { +          client?.sendMainInput(`/feedback ${text}`); +          setShowFeedbackDialog(false); +        }} +        onClose={() => { +          setShowFeedbackDialog(false); +        }} +        message={feedbackDialogMessage} +        entryOn={feedbackEntryOn} +      />        <TopGUIDiv          ref={topGuiDivRef} @@ -307,6 +308,7 @@ function GUI(props: GUIProps) {              )            ) : (              <StepContainer +              index={index}                isLast={index === history.timeline.length - 1}                isFirst={index === 0}                open={stepsOpen[index]} @@ -371,12 +373,13 @@ function GUI(props: GUIProps) {          style={{            position: "fixed",            bottom: "50px", -          backgroundColor: "white", -          color: "black", +          backgroundColor: vscBackground, +          color: vscForeground,            borderRadius: defaultBorderRadius,            padding: "16px",            margin: "16px",            zIndex: 100, +          boxShadow: `0px 0px 10px 0px ${vscForeground}`,          }}          hidden={!showDataSharingInfo}        > @@ -425,24 +428,26 @@ function GUI(props: GUIProps) {          </div>          <HeaderButtonWithText            onClick={() => { -            // client?.changeDefaultModel( -            //   usingFastModel ? "gpt-4" : "gpt-3.5-turbo" -            // ); -            if (!usingFastModel) { -              // Show the dialog -              setFeedbackDialogMessage( -                "We don't yet support local models, but we're working on it! If privacy is a concern of yours, please write a short note to let us know." -              ); -              setShowFeedbackDialog(true); -            } -            setUsingFastModel((prev) => !prev); +            // Show the dialog +            setFeedbackDialogMessage( +              `Continue uses GPT-4 by default, but works with any model. If you'd like to keep your code completely private, there are few options: + +Run a local model with ggml: [5 minute quickstart](https://github.com/continuedev/ggml-server-example) + +Use Azure OpenAI service, which is GDPR and HIPAA compliant: [Tutorial](https://continue.dev/docs/customization#azure-openai-service) + +If you already have an LLM deployed on your own infrastructure, or would like to do so, please contact us at hi@continue.dev. +              ` +            ); +            setFeedbackEntryOn(false); +            setShowFeedbackDialog(true);            }} -          text={usingFastModel ? "local" : "gpt-4"} +          text={"Use Private Model"}          >            <div              style={{ fontSize: "18px", marginLeft: "2px", marginRight: "2px" }}            > -            {usingFastModel ? "🔒" : "🧠"} +            🔒            </div>          </HeaderButtonWithText>          <HeaderButtonWithText @@ -467,6 +472,7 @@ function GUI(props: GUIProps) {              setFeedbackDialogMessage(                "Having trouble using Continue? Want a new feature? Let us know! This box is anonymous, but we will promptly address your feedback."              ); +            setFeedbackEntryOn(true);              setShowFeedbackDialog(true);            }}            text="Feedback" diff --git a/extension/react-app/src/util/index.ts b/extension/react-app/src/util/index.ts new file mode 100644 index 00000000..c4168e13 --- /dev/null +++ b/extension/react-app/src/util/index.ts @@ -0,0 +1,43 @@ +type Platform = "mac" | "linux" | "windows" | "unknown"; + +export function getPlatform(): Platform { +  const platform = window.navigator.platform.toUpperCase(); +  if (platform.indexOf("MAC") >= 0) { +    return "mac"; +  } else if (platform.indexOf("LINUX") >= 0) { +    return "linux"; +  } else if (platform.indexOf("WIN") >= 0) { +    return "windows"; +  } else { +    return "unknown"; +  } +} + +export function isMetaEquivalentKeyPressed(event: { +  metaKey: boolean; +  ctrlKey: boolean; +}): boolean { +  const platform = getPlatform(); +  switch (platform) { +    case "mac": +      return event.metaKey; +    case "linux": +    case "windows": +      return event.ctrlKey; +    default: +      return event.metaKey; +  } +} + +export function getMetaKeyLabel(): string { +  const platform = getPlatform(); +  switch (platform) { +    case "mac": +      return "⌘"; +    case "linux": +    case "windows": +      return "^"; +    default: +      return "⌘"; +  } +} | 
