diff --git a/README.md b/README.md index b7f01a43da..2af8230549 100644 --- a/README.md +++ b/README.md @@ -2725,7 +2725,7 @@ Whether to use Google-style or Numpy-style conventions when detecting docstring sections. By default, conventions will be inferred from the available sections. -**Default value**: `"convention"` +**Default value**: `None` **Type**: `Convention` diff --git a/playground/README.md b/playground/README.md index 7d10a1f55b..b60817f87d 100644 --- a/playground/README.md +++ b/playground/README.md @@ -8,3 +8,7 @@ In-browser playground for Ruff. Available [https://ruff.pages.dev/](https://ruff root directory. - Install TypeScript dependencies with: `npm install`. - Start the development server with: `npm run dev`. + +## Implementation + +Design based on [Tailwind Play](https://play.tailwindcss.com/). Themed with [`ayu`](https://github.com/dempfi/ayu). diff --git a/playground/index.html b/playground/index.html index cc4767e7f4..588e2f851d 100644 --- a/playground/index.html +++ b/playground/index.html @@ -13,17 +13,10 @@ rel="icon" href="data:image/svg+xml,🛠️" /> +
-
- GitHub stars -
diff --git a/playground/package-lock.json b/playground/package-lock.json index e0ecf29c70..7b3d2508a9 100644 --- a/playground/package-lock.json +++ b/playground/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "@monaco-editor/react": "^4.4.6", + "classnames": "^2.3.2", "lz-string": "^1.4.4", "monaco-editor": "^0.34.1", "react": "^18.2.0", @@ -20,13 +21,16 @@ "@typescript-eslint/eslint-plugin": "^5.47.1", "@typescript-eslint/parser": "^5.47.1", "@vitejs/plugin-react-swc": "^3.0.0", + "autoprefixer": "^10.4.13", "eslint": "^8.30.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.31.11", "eslint-plugin-react-hooks": "^4.6.0", + "postcss": "^8.4.20", "prettier": "^2.8.1", + "tailwindcss": "^3.2.4", "typescript": "^4.9.3", "vite": "^4.0.0" } @@ -958,6 +962,38 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "dependencies": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + } + }, + "node_modules/acorn-node/node_modules/acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -998,6 +1034,25 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1081,12 +1136,54 @@ "get-intrinsic": "^1.1.3" } }, + "node_modules/autoprefixer": { + "version": "10.4.13", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", + "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + ], + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-lite": "^1.0.30001426", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/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, + "engines": { + "node": ">=8" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -1109,6 +1206,34 @@ "node": ">=8" } }, + "node_modules/browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -1131,6 +1256,31 @@ "node": ">=6" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001441", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001441.tgz", + "integrity": "sha512-OyxRR4Vof59I3yGWXws6i908EtGbMzVUi3ganaZQHmydk1iwDhRnvaPG2WaR0KcqrDFKrxVZHULT396LEPhXfg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + } + ] + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1147,6 +1297,50 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -1185,6 +1379,18 @@ "node": ">= 8" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/csstype": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", @@ -1230,6 +1436,38 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/defined": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "dependencies": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + }, + "bin": { + "detective": "bin/detective.js" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1242,6 +1480,12 @@ "node": ">=8" } }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "node_modules/doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -1254,6 +1498,12 @@ "node": ">=6.0.0" } }, + "node_modules/electron-to-chromium": { + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true + }, "node_modules/es-abstract": { "version": "1.20.5", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz", @@ -1356,6 +1606,15 @@ "@esbuild/win32-x64": "0.16.9" } }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -1912,6 +2171,19 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2225,6 +2497,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -2499,6 +2783,15 @@ "node": ">= 0.8.0" } }, + "node_modules/lilconfig": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2629,6 +2922,30 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node_modules/node-releases": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", + "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -2637,6 +2954,15 @@ "node": ">=0.10.0" } }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -2862,6 +3188,15 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/postcss": { "version": "8.4.20", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz", @@ -2886,6 +3221,109 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.10" + }, + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -2961,6 +3399,18 @@ } ] }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -2989,6 +3439,27 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -3307,6 +3778,47 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwindcss": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", + "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", + "dev": true, + "dependencies": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.18", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "6.0.0", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=12.13.0" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3410,6 +3922,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + } + ], + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "browserslist-lint": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -3419,6 +3957,12 @@ "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/vite": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.1.tgz", @@ -3514,12 +4058,30 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -4029,6 +4591,31 @@ "dev": true, "requires": {} }, + "acorn-node": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz", + "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==", + "dev": true, + "requires": { + "acorn": "^7.0.0", + "acorn-walk": "^7.0.0", + "xtend": "^4.0.2" + }, + "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + } + } + }, + "acorn-walk": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz", + "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", + "dev": true + }, "ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -4056,6 +4643,22 @@ "color-convert": "^2.0.1" } }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4118,12 +4721,32 @@ "get-intrinsic": "^1.1.3" } }, + "autoprefixer": { + "version": "10.4.13", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.13.tgz", + "integrity": "sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg==", + "dev": true, + "requires": { + "browserslist": "^4.21.4", + "caniuse-lite": "^1.0.30001426", + "fraction.js": "^4.2.0", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.0", + "postcss-value-parser": "^4.2.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "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 + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -4143,6 +4766,18 @@ "fill-range": "^7.0.1" } }, + "browserslist": { + "version": "4.21.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", + "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001400", + "electron-to-chromium": "^1.4.251", + "node-releases": "^2.0.6", + "update-browserslist-db": "^1.0.9" + } + }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -4159,6 +4794,18 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, + "camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001441", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001441.tgz", + "integrity": "sha512-OyxRR4Vof59I3yGWXws6i908EtGbMzVUi3ganaZQHmydk1iwDhRnvaPG2WaR0KcqrDFKrxVZHULT396LEPhXfg==", + "dev": true + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -4169,6 +4816,38 @@ "supports-color": "^7.1.0" } }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "classnames": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4201,6 +4880,12 @@ "which": "^2.0.1" } }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, "csstype": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", @@ -4232,6 +4917,29 @@ "object-keys": "^1.1.1" } }, + "defined": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", + "dev": true + }, + "detective": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", + "integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==", + "dev": true, + "requires": { + "acorn-node": "^1.8.2", + "defined": "^1.0.0", + "minimist": "^1.2.6" + } + }, + "didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -4241,6 +4949,12 @@ "path-type": "^4.0.0" } }, + "dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "doctrine": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", @@ -4250,6 +4964,12 @@ "esutils": "^2.0.2" } }, + "electron-to-chromium": { + "version": "1.4.284", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", + "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==", + "dev": true + }, "es-abstract": { "version": "1.20.5", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.5.tgz", @@ -4333,6 +5053,12 @@ "@esbuild/win32-x64": "0.16.9" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -4763,6 +5489,12 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "dev": true + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -4985,6 +5717,15 @@ "has-bigints": "^1.0.1" } }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -5174,6 +5915,12 @@ "type-check": "~0.4.0" } }, + "lilconfig": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", + "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "dev": true + }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -5271,11 +6018,35 @@ "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", "dev": true }, + "node-releases": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.8.tgz", + "integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==", + "dev": true + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, + "object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true + }, "object-inspect": { "version": "1.12.2", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", @@ -5435,6 +6206,12 @@ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true + }, "postcss": { "version": "8.4.20", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz", @@ -5446,6 +6223,61 @@ "source-map-js": "^1.0.2" } }, + "postcss-import": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", + "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", + "dev": true, + "requires": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + } + }, + "postcss-js": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", + "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "dev": true, + "requires": { + "camelcase-css": "^2.0.1" + } + }, + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dev": true, + "requires": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + } + }, + "postcss-nested": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz", + "integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.10" + } + }, + "postcss-selector-parser": { + "version": "6.0.11", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", + "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -5489,6 +6321,12 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true + }, "react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -5511,6 +6349,24 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "requires": { + "pify": "^2.3.0" + } + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, "regexp.prototype.flags": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", @@ -5723,6 +6579,37 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true }, + "tailwindcss": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", + "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", + "dev": true, + "requires": { + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "color-name": "^1.1.4", + "detective": "^5.2.1", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.2.12", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "lilconfig": "^2.0.6", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.18", + "postcss-import": "^14.1.0", + "postcss-js": "^4.0.0", + "postcss-load-config": "^3.1.4", + "postcss-nested": "6.0.0", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "quick-lru": "^5.1.1", + "resolve": "^1.22.1" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5798,6 +6685,16 @@ "which-boxed-primitive": "^1.0.2" } }, + "update-browserslist-db": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", + "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "dev": true, + "requires": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -5807,6 +6704,12 @@ "punycode": "^2.1.0" } }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "vite": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/vite/-/vite-4.0.1.tgz", @@ -5854,12 +6757,24 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, "yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, "yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/playground/package.json b/playground/package.json index f092b17f01..8f37e13e87 100644 --- a/playground/package.json +++ b/playground/package.json @@ -14,6 +14,7 @@ }, "dependencies": { "@monaco-editor/react": "^4.4.6", + "classnames": "^2.3.2", "lz-string": "^1.4.4", "monaco-editor": "^0.34.1", "react": "^18.2.0", @@ -25,13 +26,16 @@ "@typescript-eslint/eslint-plugin": "^5.47.1", "@typescript-eslint/parser": "^5.47.1", "@vitejs/plugin-react-swc": "^3.0.0", + "autoprefixer": "^10.4.13", "eslint": "^8.30.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.26.0", "eslint-plugin-prettier": "^4.2.1", "eslint-plugin-react": "^7.31.11", "eslint-plugin-react-hooks": "^4.6.0", + "postcss": "^8.4.20", "prettier": "^2.8.1", + "tailwindcss": "^3.2.4", "typescript": "^4.9.3", "vite": "^4.0.0" } diff --git a/playground/postcss.config.cjs b/playground/postcss.config.cjs new file mode 100644 index 0000000000..12a703d900 --- /dev/null +++ b/playground/postcss.config.cjs @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/playground/src/App.tsx b/playground/src/App.tsx deleted file mode 100644 index 902c210e74..0000000000 --- a/playground/src/App.tsx +++ /dev/null @@ -1,200 +0,0 @@ -import lzstring from "lz-string"; -import Editor, { useMonaco } from "@monaco-editor/react"; -import { MarkerSeverity } from "monaco-editor/esm/vs/editor/editor.api"; -import { useEffect, useState, useCallback } from "react"; - -import init, { Check, check } from "./pkg/ruff.js"; -import { AVAILABLE_OPTIONS } from "./ruff_options"; -import { Config, getDefaultConfig, toRuffConfig } from "./config"; -import { Options } from "./Options"; - -const DEFAULT_SOURCE = - "# Define a function that takes an integer n and returns the nth number in the Fibonacci\n" + - "# sequence.\n" + - "def fibonacci(n):\n" + - " if n == 0:\n" + - " return 0\n" + - " elif n == 1:\n" + - " return 1\n" + - " else:\n" + - " return fibonacci(n-1) + fibonacci(n-2)\n" + - "\n" + - "# Use a for loop to generate and print the first 10 numbers in the Fibonacci sequence.\n" + - "for i in range(10):\n" + - " print(fibonacci(i))\n" + - "\n" + - "# Output:\n" + - "# 0\n" + - "# 1\n" + - "# 1\n" + - "# 2\n" + - "# 3\n" + - "# 5\n" + - "# 8\n" + - "# 13\n" + - "# 21\n" + - "# 34\n"; - -function restoreConfigAndSource(): [Config, string] { - const value = lzstring.decompressFromEncodedURIComponent( - window.location.hash.slice(1) - ); - let config = {}; - let source = DEFAULT_SOURCE; - - if (value) { - const parts = value.split("$$$"); - config = JSON.parse(parts[0]); - source = parts[1]; - } - - return [config, source]; -} - -function persistConfigAndSource(config: Config, source: string) { - window.location.hash = lzstring.compressToEncodedURIComponent( - JSON.stringify(config) + "$$$" + source - ); -} - -const defaultConfig = getDefaultConfig(AVAILABLE_OPTIONS); - -export default function App() { - const monaco = useMonaco(); - const [initialized, setInitialized] = useState(false); - const [config, setConfig] = useState(null); - const [source, setSource] = useState(null); - const [error, setError] = useState(null); - - useEffect(() => { - init().then(() => setInitialized(true)); - }, []); - - useEffect(() => { - if (source == null && config == null && monaco) { - const [config, source] = restoreConfigAndSource(); - setConfig(config); - setSource(source); - } - }, [monaco, source, config]); - - useEffect(() => { - if (config != null && source != null) { - persistConfigAndSource(config, source); - } - }, [config, source]); - - useEffect(() => { - const editor = monaco?.editor; - const model = editor?.getModels()[0]; - if (!editor || !model || !initialized || source == null || config == null) { - return; - } - - let checks: Check[]; - try { - checks = check(source, toRuffConfig(config)); - setError(null); - } catch (e) { - setError(String(e)); - return; - } - - editor.setModelMarkers( - model, - "owner", - checks.map((check) => ({ - startLineNumber: check.location.row, - startColumn: check.location.column + 1, - endLineNumber: check.end_location.row, - endColumn: check.end_location.column + 1, - message: `${check.code}: ${check.message}`, - severity: MarkerSeverity.Error, - })) - ); - - const codeActionProvider = monaco?.languages.registerCodeActionProvider( - "python", - { - // @ts-expect-error: The type definition is wrong. - provideCodeActions: function (model, position) { - const actions = checks - .filter((check) => position.startLineNumber === check.location.row) - .filter((check) => check.fix) - .map((check) => ({ - title: `Fix ${check.code}`, - id: `fix-${check.code}`, - kind: "quickfix", - edit: check.fix - ? { - edits: [ - { - resource: model.uri, - versionId: model.getVersionId(), - edit: { - range: { - startLineNumber: check.fix.location.row, - startColumn: check.fix.location.column + 1, - endLineNumber: check.fix.end_location.row, - endColumn: check.fix.end_location.column + 1, - }, - text: check.fix.content, - }, - }, - ], - } - : undefined, - })); - return { actions, dispose: () => {} }; - }, - } - ); - - return () => { - codeActionProvider?.dispose(); - }; - }, [config, source, monaco, initialized]); - - const handleEditorChange = useCallback( - (value: string | undefined) => { - setSource(value || ""); - }, - [setSource] - ); - - const handleOptionChange = useCallback( - (groupName: string, fieldName: string, value: string) => { - const group = Object.assign({}, (config || {})[groupName]); - if (value === defaultConfig[groupName][fieldName] || value === "") { - delete group[fieldName]; - } else { - group[fieldName] = value; - } - - setConfig({ - ...config, - [groupName]: group, - }); - }, - [config] - ); - - return ( -
- - - {error &&
{error}
} -
- ); -} diff --git a/playground/src/Editor/Editor.tsx b/playground/src/Editor/Editor.tsx new file mode 100644 index 0000000000..4aad7e43fc --- /dev/null +++ b/playground/src/Editor/Editor.tsx @@ -0,0 +1,137 @@ +import { useCallback, useEffect, useState } from "react"; +import { persist, restore } from "./config"; +import { DEFAULT_CONFIG_SOURCE, DEFAULT_PYTHON_SOURCE } from "../constants"; +import { ErrorMessage } from "./ErrorMessage"; +import Header from "./Header"; +import init, { check, current_version, Check } from "../pkg"; +import SettingsEditor from "./SettingsEditor"; +import SourceEditor from "./SourceEditor"; +import Themes from "./Themes"; + +type Tab = "Source" | "Settings"; + +export default function Editor() { + const [initialized, setInitialized] = useState(false); + const [version, setVersion] = useState(null); + const [tab, setTab] = useState("Source"); + const [edit, setEdit] = useState(0); + const [configSource, setConfigSource] = useState(null); + const [pythonSource, setPythonSource] = useState(null); + const [checks, setChecks] = useState([]); + const [error, setError] = useState(null); + + useEffect(() => { + init().then(() => setInitialized(true)); + }, []); + + useEffect(() => { + if (!initialized || configSource == null || pythonSource == null) { + return; + } + + let config: any; + let checks: Check[]; + + try { + config = JSON.parse(configSource); + } catch (e) { + setChecks([]); + setError((e as Error).message); + return; + } + + try { + checks = check(pythonSource, config); + } catch (e) { + setError(e as string); + return; + } + + setError(null); + setChecks(checks); + }, [initialized, configSource, pythonSource]); + + useEffect(() => { + if (configSource == null || pythonSource == null) { + const payload = restore(); + if (payload) { + const [configSource, pythonSource] = payload; + setConfigSource(configSource); + setPythonSource(pythonSource); + } else { + setConfigSource(DEFAULT_CONFIG_SOURCE); + setPythonSource(DEFAULT_PYTHON_SOURCE); + } + } + }, [configSource, pythonSource]); + + useEffect(() => { + if (!initialized) { + return; + } + + setVersion(current_version()); + }, [initialized]); + + const handleShare = useCallback(() => { + if (!initialized || configSource == null || pythonSource == null) { + return; + } + + persist(configSource, pythonSource); + }, [initialized, configSource, pythonSource]); + + const handlePythonSourceChange = useCallback((pythonSource: string) => { + setEdit((edit) => edit + 1); + setPythonSource(pythonSource); + }, []); + + const handleConfigSourceChange = useCallback((configSource: string) => { + setEdit((edit) => edit + 1); + setConfigSource(configSource); + }, []); + + return ( +
+
+ + + +
+ {initialized && configSource != null && pythonSource != null ? ( + <> + + + + ) : null} +
+ {error && tab === "Source" ? ( +
+ {error} +
+ ) : null} +
+ ); +} diff --git a/playground/src/Editor/ErrorMessage.tsx b/playground/src/Editor/ErrorMessage.tsx new file mode 100644 index 0000000000..4488bbca89 --- /dev/null +++ b/playground/src/Editor/ErrorMessage.tsx @@ -0,0 +1,26 @@ +function truncate(str: string, length: number) { + if (str.length > length) { + return str.slice(0, length) + "..."; + } else { + return str; + } +} + +export function ErrorMessage({ children }: { children: string }) { + return ( +
+

Error

+

+ {truncate( + children.startsWith("Error: ") + ? children.slice("Error: ".length) + : children, + 120 + )} +

+
+ ); +} diff --git a/playground/src/Editor/Header.tsx b/playground/src/Editor/Header.tsx new file mode 100644 index 0000000000..3e23be00a6 --- /dev/null +++ b/playground/src/Editor/Header.tsx @@ -0,0 +1,73 @@ +import classNames from "classnames"; +import ShareButton from "./ShareButton"; +import VersionTag from "./VersionTag"; + +export type Tab = "Source" | "Settings"; + +export default function Header({ + edit, + version, + tab, + onChange, + onShare, +}: { + edit: number; + version: string | null; + tab: Tab; + onChange: (tab: Tab) => void; + onShare?: () => void; +}) { + return ( +
+
+ + + {version ? ( +
+ v{version} +
+ ) : null} +
+
+ +
+
+ ); +} diff --git a/playground/src/Editor/SettingsEditor.tsx b/playground/src/Editor/SettingsEditor.tsx new file mode 100644 index 0000000000..fa16446728 --- /dev/null +++ b/playground/src/Editor/SettingsEditor.tsx @@ -0,0 +1,54 @@ +/** + * Editor for the settings JSON. + */ + +import Editor, { useMonaco } from "@monaco-editor/react"; +import { useCallback, useEffect } from "react"; +import schema from "../../../ruff.schema.json"; + +export default function SettingsEditor({ + visible, + source, + onChange, +}: { + visible: boolean; + source: string; + onChange: (source: string) => void; +}) { + const monaco = useMonaco(); + + useEffect(() => { + monaco?.languages.json.jsonDefaults.setDiagnosticsOptions({ + schemas: [ + { + uri: "https://raw.githubusercontent.com/charliermarsh/ruff/main/ruff.schema.json", + fileMatch: ["*"], + schema, + }, + ], + }); + }, [monaco]); + + const handleChange = useCallback( + (value: string | undefined) => { + onChange(value ?? ""); + }, + [onChange] + ); + return ( + + ); +} diff --git a/playground/src/Editor/ShareButton.tsx b/playground/src/Editor/ShareButton.tsx new file mode 100644 index 0000000000..f0adda95fc --- /dev/null +++ b/playground/src/Editor/ShareButton.tsx @@ -0,0 +1,53 @@ +import { useEffect, useState } from "react"; + +export default function ShareButton({ onShare }: { onShare?: () => void }) { + const [copied, setCopied] = useState(false); + + useEffect(() => { + if (copied) { + const timeout = setTimeout(() => setCopied(false), 2000); + return () => clearTimeout(timeout); + } + }, [copied]); + + return copied ? ( + + ) : ( + + ); +} diff --git a/playground/src/Editor/SourceEditor.tsx b/playground/src/Editor/SourceEditor.tsx new file mode 100644 index 0000000000..1c58200f8e --- /dev/null +++ b/playground/src/Editor/SourceEditor.tsx @@ -0,0 +1,114 @@ +/** + * Editor for the Python source code. + */ + +import Editor, { useMonaco } from "@monaco-editor/react"; +import { MarkerSeverity, MarkerTag } from "monaco-editor"; +import { useCallback, useEffect } from "react"; +import { Check } from "../pkg"; + +export type Mode = "JSON" | "Python"; + +export default function SourceEditor({ + visible, + source, + checks, + onChange, +}: { + visible: boolean; + source: string; + checks: Check[]; + onChange: (pythonSource: string) => void; +}) { + const monaco = useMonaco(); + + useEffect(() => { + const editor = monaco?.editor; + const model = editor?.getModels()[0]; + if (!editor || !model) { + return; + } + + editor.setModelMarkers( + model, + "owner", + checks.map((check) => ({ + startLineNumber: check.location.row, + startColumn: check.location.column + 1, + endLineNumber: check.end_location.row, + endColumn: check.end_location.column + 1, + message: `${check.code}: ${check.message}`, + severity: MarkerSeverity.Error, + tags: + check.code === "F401" || check.code === "F841" + ? [MarkerTag.Unnecessary] + : [], + })) + ); + + const codeActionProvider = monaco?.languages.registerCodeActionProvider( + "python", + { + // @ts-expect-error: The type definition is wrong. + provideCodeActions: function (model, position) { + const actions = checks + .filter((check) => position.startLineNumber === check.location.row) + .filter((check) => check.fix) + .map((check) => ({ + title: `Fix ${check.code}`, + id: `fix-${check.code}`, + kind: "quickfix", + edit: check.fix + ? { + edits: [ + { + resource: model.uri, + versionId: model.getVersionId(), + edit: { + range: { + startLineNumber: check.fix.location.row, + startColumn: check.fix.location.column + 1, + endLineNumber: check.fix.end_location.row, + endColumn: check.fix.end_location.column + 1, + }, + text: check.fix.content, + }, + }, + ], + } + : undefined, + })); + return { actions, dispose: () => {} }; + }, + } + ); + + return () => { + codeActionProvider?.dispose(); + }; + }, [checks, monaco]); + + const handleChange = useCallback( + (value: string | undefined) => { + onChange(value ?? ""); + }, + [onChange] + ); + + return ( + + ); +} diff --git a/playground/src/Editor/Themes.tsx b/playground/src/Editor/Themes.tsx new file mode 100644 index 0000000000..1ed533a1ed --- /dev/null +++ b/playground/src/Editor/Themes.tsx @@ -0,0 +1,645 @@ +import { useMonaco } from "@monaco-editor/react"; +import { useEffect } from "react"; + +export default function Themes() { + const monaco = useMonaco(); + + useEffect(() => { + // Generated via `monaco-vscode-textmate-theme-converter`. + // See: https://github.com/ayu-theme/vscode-ayu/blob/91839e8a9dfa78d61e58dbcf9b52272a01fee66a/ayu-light.json. + monaco?.editor.defineTheme("Ayu-Light", { + inherit: false, + base: "vs-dark", + colors: { + focusBorder: "#ffaa33b3", + foreground: "#8a9199", + "widget.shadow": "#00000026", + "selection.background": "#035bd626", + "icon.foreground": "#8a9199", + errorForeground: "#e65050", + descriptionForeground: "#8a9199", + "textBlockQuote.background": "#f3f4f5", + "textLink.foreground": "#ffaa33", + "textLink.activeForeground": "#ffaa33", + "textPreformat.foreground": "#5c6166", + "button.background": "#ffaa33", + "button.foreground": "#f8f9fa", + "button.hoverBackground": "#f9a52e", + "button.secondaryBackground": "#8a919933", + "button.secondaryForeground": "#5c6166", + "button.secondaryHoverBackground": "#8a919980", + "dropdown.background": "#fcfcfc", + "dropdown.foreground": "#8a9199", + "dropdown.border": "#8a919945", + "input.background": "#fcfcfc", + "input.border": "#8a919945", + "input.foreground": "#5c6166", + "input.placeholderForeground": "#8a919980", + "inputOption.activeBorder": "#f4a0284d", + "inputOption.activeBackground": "#ffaa3333", + "inputOption.activeForeground": "#f4a028", + "inputValidation.errorBackground": "#fcfcfc", + "inputValidation.errorBorder": "#e65050", + "inputValidation.infoBackground": "#f8f9fa", + "inputValidation.infoBorder": "#55b4d4", + "inputValidation.warningBackground": "#f8f9fa", + "inputValidation.warningBorder": "#f2ae49", + "scrollbar.shadow": "#6b7d8f00", + "scrollbarSlider.background": "#8a919966", + "scrollbarSlider.hoverBackground": "#8a919999", + "scrollbarSlider.activeBackground": "#8a9199b3", + "badge.background": "#ffaa3333", + "badge.foreground": "#f4a028", + "progressBar.background": "#ffaa33", + "list.activeSelectionBackground": "#56728f1f", + "list.activeSelectionForeground": "#5c6166", + "list.focusBackground": "#56728f1f", + "list.focusForeground": "#5c6166", + "list.focusOutline": "#56728f1f", + "list.highlightForeground": "#ffaa33", + "list.deemphasizedForeground": "#e65050", + "list.hoverBackground": "#56728f1f", + "list.inactiveSelectionBackground": "#6b7d8f1f", + "list.inactiveSelectionForeground": "#8a9199", + "list.invalidItemForeground": "#8a91994d", + "list.errorForeground": "#e65050", + "tree.indentGuidesStroke": "#8a919959", + "listFilterWidget.background": "#f3f4f5", + "listFilterWidget.outline": "#ffaa33", + "listFilterWidget.noMatchesOutline": "#e65050", + "list.filterMatchBackground": "#8f30efcc", + "list.filterMatchBorder": "#9f40ffcc", + "activityBar.background": "#f8f9fa", + "activityBar.foreground": "#8a9199cc", + "activityBar.inactiveForeground": "#8a919999", + "activityBar.border": "#f8f9fa", + "activityBar.activeBorder": "#ffaa33b3", + "activityBarBadge.background": "#ffaa33", + "activityBarBadge.foreground": "#f8f9fa", + "sideBar.background": "#f8f9fa", + "sideBar.border": "#f8f9fa", + "sideBarTitle.foreground": "#8a9199", + "sideBarSectionHeader.background": "#f8f9fa", + "sideBarSectionHeader.foreground": "#8a9199", + "sideBarSectionHeader.border": "#f8f9fa", + "minimap.background": "#f8f9fa", + "minimap.selectionHighlight": "#035bd626", + "minimap.errorHighlight": "#e65050", + "minimap.findMatchHighlight": "#9f40ff2b", + "minimapGutter.addedBackground": "#6cbf43", + "minimapGutter.modifiedBackground": "#478acc", + "minimapGutter.deletedBackground": "#ff7383", + "editorGroup.border": "#6b7d8f1f", + "editorGroup.background": "#f3f4f5", + "editorGroupHeader.noTabsBackground": "#f8f9fa", + "editorGroupHeader.tabsBackground": "#f8f9fa", + "editorGroupHeader.tabsBorder": "#f8f9fa", + "tab.activeBackground": "#f8f9fa", + "tab.activeForeground": "#5c6166", + "tab.border": "#f8f9fa", + "tab.activeBorder": "#ffaa33", + "tab.unfocusedActiveBorder": "#8a9199", + "tab.inactiveBackground": "#f8f9fa", + "tab.inactiveForeground": "#8a9199", + "tab.unfocusedActiveForeground": "#8a9199", + "tab.unfocusedInactiveForeground": "#8a9199", + "editor.background": "#f8f9fa", + "editor.foreground": "#5c6166", + "editorLineNumber.foreground": "#8a919966", + "editorLineNumber.activeForeground": "#8a9199cc", + "editorCursor.foreground": "#ffaa33", + "editor.inactiveSelectionBackground": "#035bd612", + "editor.selectionBackground": "#035bd626", + "editor.selectionHighlightBackground": "#6cbf4326", + "editor.selectionHighlightBorder": "#6cbf4300", + "editor.wordHighlightBackground": "#478acc14", + "editor.wordHighlightStrongBackground": "#6cbf4314", + "editor.wordHighlightBorder": "#478acc80", + "editor.wordHighlightStrongBorder": "#6cbf4380", + "editor.findMatchBackground": "#9f40ff2b", + "editor.findMatchBorder": "#9f40ff2b", + "editor.findMatchHighlightBackground": "#9f40ffcc", + "editor.findMatchHighlightBorder": "#8f30efcc", + "editor.findRangeHighlightBackground": "#9f40ff40", + "editor.rangeHighlightBackground": "#9f40ff33", + "editor.lineHighlightBackground": "#8a91991a", + "editorLink.activeForeground": "#ffaa33", + "editorWhitespace.foreground": "#8a919966", + "editorIndentGuide.background": "#8a91992e", + "editorIndentGuide.activeBackground": "#8a919959", + "editorRuler.foreground": "#8a91992e", + "editorCodeLens.foreground": "#787b8099", + "editorBracketMatch.background": "#8a91994d", + "editorBracketMatch.border": "#8a91994d", + "editor.snippetTabstopHighlightBackground": "#6cbf4333", + "editorOverviewRuler.border": "#6b7d8f1f", + "editorOverviewRuler.modifiedForeground": "#478acc", + "editorOverviewRuler.addedForeground": "#6cbf43", + "editorOverviewRuler.deletedForeground": "#ff7383", + "editorOverviewRuler.errorForeground": "#e65050", + "editorOverviewRuler.warningForeground": "#ffaa33", + "editorOverviewRuler.bracketMatchForeground": "#8a9199b3", + "editorOverviewRuler.wordHighlightForeground": "#478acc66", + "editorOverviewRuler.wordHighlightStrongForeground": "#6cbf4366", + "editorOverviewRuler.findMatchForeground": "#9f40ff2b", + "editorError.foreground": "#e65050", + "editorWarning.foreground": "#ffaa33", + "editorGutter.modifiedBackground": "#478acccc", + "editorGutter.addedBackground": "#6cbf43cc", + "editorGutter.deletedBackground": "#ff7383cc", + "diffEditor.insertedTextBackground": "#6cbf431f", + "diffEditor.removedTextBackground": "#ff73831f", + "diffEditor.diagonalFill": "#6b7d8f1f", + "editorWidget.background": "#f3f4f5", + "editorWidget.border": "#6b7d8f1f", + "editorHoverWidget.background": "#f3f4f5", + "editorHoverWidget.border": "#6b7d8f1f", + "editorSuggestWidget.background": "#f3f4f5", + "editorSuggestWidget.border": "#6b7d8f1f", + "editorSuggestWidget.highlightForeground": "#ffaa33", + "editorSuggestWidget.selectedBackground": "#56728f1f", + "debugExceptionWidget.border": "#6b7d8f1f", + "debugExceptionWidget.background": "#f3f4f5", + "editorMarkerNavigation.background": "#f3f4f5", + "peekView.border": "#56728f1f", + "peekViewTitle.background": "#56728f1f", + "peekViewTitleDescription.foreground": "#8a9199", + "peekViewTitleLabel.foreground": "#5c6166", + "peekViewEditor.background": "#f3f4f5", + "peekViewEditor.matchHighlightBackground": "#9f40ffcc", + "peekViewEditor.matchHighlightBorder": "#8f30efcc", + "peekViewResult.background": "#f3f4f5", + "peekViewResult.fileForeground": "#5c6166", + "peekViewResult.lineForeground": "#8a9199", + "peekViewResult.matchHighlightBackground": "#9f40ffcc", + "peekViewResult.selectionBackground": "#56728f1f", + "panel.background": "#f8f9fa", + "panel.border": "#6b7d8f1f", + "panelTitle.activeBorder": "#ffaa33", + "panelTitle.activeForeground": "#5c6166", + "panelTitle.inactiveForeground": "#8a9199", + "statusBar.background": "#f8f9fa", + "statusBar.foreground": "#8a9199", + "statusBar.border": "#f8f9fa", + "statusBar.debuggingBackground": "#ed9366", + "statusBar.debuggingForeground": "#fcfcfc", + "statusBar.noFolderBackground": "#f3f4f5", + "statusBarItem.activeBackground": "#8a919933", + "statusBarItem.hoverBackground": "#8a919933", + "statusBarItem.prominentBackground": "#6b7d8f1f", + "statusBarItem.prominentHoverBackground": "#00000030", + "statusBarItem.remoteBackground": "#ffaa33", + "statusBarItem.remoteForeground": "#fcfcfc", + "titleBar.activeBackground": "#f8f9fa", + "titleBar.activeForeground": "#5c6166", + "titleBar.inactiveBackground": "#f8f9fa", + "titleBar.inactiveForeground": "#8a9199", + "titleBar.border": "#f8f9fa", + "extensionButton.prominentForeground": "#fcfcfc", + "extensionButton.prominentBackground": "#ffaa33", + "extensionButton.prominentHoverBackground": "#f9a52e", + "pickerGroup.border": "#6b7d8f1f", + "pickerGroup.foreground": "#8a919980", + "debugToolBar.background": "#f3f4f5", + "debugIcon.breakpointForeground": "#ed9366", + "debugIcon.breakpointDisabledForeground": "#ed936680", + "debugConsoleInputIcon.foreground": "#ffaa33", + "welcomePage.tileBackground": "#f8f9fa", + "welcomePage.tileShadow": "#00000026", + "welcomePage.progress.background": "#8a91991a", + "welcomePage.buttonBackground": "#ffaa3366", + "walkThrough.embeddedEditorBackground": "#f3f4f5", + "gitDecoration.modifiedResourceForeground": "#478accb3", + "gitDecoration.deletedResourceForeground": "#ff7383b3", + "gitDecoration.untrackedResourceForeground": "#6cbf43b3", + "gitDecoration.ignoredResourceForeground": "#8a919980", + "gitDecoration.conflictingResourceForeground": "", + "gitDecoration.submoduleResourceForeground": "#a37accb3", + "settings.headerForeground": "#5c6166", + "settings.modifiedItemIndicator": "#478acc", + "keybindingLabel.background": "#8a91991a", + "keybindingLabel.foreground": "#5c6166", + "keybindingLabel.border": "#5c61661a", + "keybindingLabel.bottomBorder": "#5c61661a", + "terminal.background": "#f8f9fa", + "terminal.foreground": "#5c6166", + "terminal.ansiBlack": "#000000", + "terminal.ansiRed": "#ea6c6d", + "terminal.ansiGreen": "#6cbf43", + "terminal.ansiYellow": "#eca944", + "terminal.ansiBlue": "#3199e1", + "terminal.ansiMagenta": "#9e75c7", + "terminal.ansiCyan": "#46ba94", + "terminal.ansiWhite": "#c7c7c7", + "terminal.ansiBrightBlack": "#686868", + "terminal.ansiBrightRed": "#f07171", + "terminal.ansiBrightGreen": "#86b300", + "terminal.ansiBrightYellow": "#f2ae49", + "terminal.ansiBrightBlue": "#399ee6", + "terminal.ansiBrightMagenta": "#a37acc", + "terminal.ansiBrightCyan": "#4cbf99", + "terminal.ansiBrightWhite": "#d1d1d1", + }, + rules: [ + { + fontStyle: "italic", + foreground: "#787b8099", + token: "comment", + }, + { + foreground: "#86b300", + token: "string", + }, + { + foreground: "#86b300", + token: "constant.other.symbol", + }, + { + foreground: "#4cbf99", + token: "string.regexp", + }, + { + foreground: "#4cbf99", + token: "constant.character", + }, + { + foreground: "#4cbf99", + token: "constant.other", + }, + { + foreground: "#a37acc", + token: "constant.numeric", + }, + { + foreground: "#a37acc", + token: "constant.language", + }, + { + foreground: "#5c6166", + token: "variable", + }, + { + foreground: "#5c6166", + token: "variable.parameter.function-call", + }, + { + foreground: "#f07171", + token: "variable.member", + }, + { + fontStyle: "italic", + foreground: "#55b4d4", + token: "variable.language", + }, + { + foreground: "#fa8d3e", + token: "storage", + }, + { + foreground: "#fa8d3e", + token: "keyword", + }, + { + foreground: "#ed9366", + token: "keyword.operator", + }, + { + foreground: "#5c6166b3", + token: "punctuation.separator", + }, + { + foreground: "#5c6166b3", + token: "punctuation.terminator", + }, + { + foreground: "#5c6166", + token: "punctuation.section", + }, + { + foreground: "#ed9366", + token: "punctuation.accessor", + }, + { + foreground: "#fa8d3e", + token: "punctuation.definition.template-expression", + }, + { + foreground: "#fa8d3e", + token: "punctuation.section.embedded", + }, + { + foreground: "#5c6166", + token: "meta.embedded", + }, + { + foreground: "#399ee6", + token: "source.java storage.type", + }, + { + foreground: "#399ee6", + token: "source.haskell storage.type", + }, + { + foreground: "#399ee6", + token: "source.c storage.type", + }, + { + foreground: "#55b4d4", + token: "entity.other.inherited-class", + }, + { + foreground: "#fa8d3e", + token: "storage.type.function", + }, + { + foreground: "#55b4d4", + token: "source.java storage.type.primitive", + }, + { + foreground: "#f2ae49", + token: "entity.name.function", + }, + { + foreground: "#a37acc", + token: "variable.parameter", + }, + { + foreground: "#a37acc", + token: "meta.parameter", + }, + { + foreground: "#f2ae49", + token: "variable.function", + }, + { + foreground: "#f2ae49", + token: "variable.annotation", + }, + { + foreground: "#f2ae49", + token: "meta.function-call.generic", + }, + { + foreground: "#f2ae49", + token: "support.function.go", + }, + { + foreground: "#f07171", + token: "support.function", + }, + { + foreground: "#f07171", + token: "support.macro", + }, + { + foreground: "#86b300", + token: "entity.name.import", + }, + { + foreground: "#86b300", + token: "entity.name.package", + }, + { + foreground: "#399ee6", + token: "entity.name", + }, + { + foreground: "#55b4d4", + token: "entity.name.tag", + }, + { + foreground: "#55b4d4", + token: "meta.tag.sgml", + }, + { + foreground: "#399ee6", + token: "support.class.component", + }, + { + foreground: "#55b4d480", + token: "punctuation.definition.tag.end", + }, + { + foreground: "#55b4d480", + token: "punctuation.definition.tag.begin", + }, + { + foreground: "#55b4d480", + token: "punctuation.definition.tag", + }, + { + foreground: "#f2ae49", + token: "entity.other.attribute-name", + }, + { + fontStyle: "italic", + foreground: "#ed9366", + token: "support.constant", + }, + { + foreground: "#55b4d4", + token: "support.type", + }, + { + foreground: "#55b4d4", + token: "support.class", + }, + { + foreground: "#55b4d4", + token: "source.go storage.type", + }, + { + foreground: "#e6ba7e", + token: "meta.decorator variable.other", + }, + { + foreground: "#e6ba7e", + token: "meta.decorator punctuation.decorator", + }, + { + foreground: "#e6ba7e", + token: "storage.type.annotation", + }, + { + foreground: "#e65050", + token: "invalid", + }, + { + foreground: "#c594c5", + token: "meta.diff", + }, + { + foreground: "#c594c5", + token: "meta.diff.header", + }, + { + foreground: "#f2ae49", + token: "source.ruby variable.other.readwrite", + }, + { + foreground: "#399ee6", + token: "source.css entity.name.tag", + }, + { + foreground: "#399ee6", + token: "source.sass entity.name.tag", + }, + { + foreground: "#399ee6", + token: "source.scss entity.name.tag", + }, + { + foreground: "#399ee6", + token: "source.less entity.name.tag", + }, + { + foreground: "#399ee6", + token: "source.stylus entity.name.tag", + }, + { + foreground: "#787b8099", + token: "source.css support.type", + }, + { + foreground: "#787b8099", + token: "source.sass support.type", + }, + { + foreground: "#787b8099", + token: "source.scss support.type", + }, + { + foreground: "#787b8099", + token: "source.less support.type", + }, + { + foreground: "#787b8099", + token: "source.stylus support.type", + }, + { + fontStyle: "normal", + foreground: "#55b4d4", + token: "support.type.property-name", + }, + { + foreground: "#787b8099", + token: "constant.numeric.line-number.find-in-files - match", + }, + { + foreground: "#fa8d3e", + token: "constant.numeric.line-number.match", + }, + { + foreground: "#86b300", + token: "entity.name.filename.find-in-files", + }, + { + foreground: "#e65050", + token: "message.error", + }, + { + fontStyle: "bold", + foreground: "#86b300", + token: "markup.heading", + }, + { + fontStyle: "bold", + foreground: "#86b300", + token: "markup.heading entity.name", + }, + { + foreground: "#55b4d4", + token: "markup.underline.link", + }, + { + foreground: "#55b4d4", + token: "string.other.link", + }, + { + fontStyle: "italic", + foreground: "#f07171", + token: "markup.italic", + }, + { + fontStyle: "bold", + foreground: "#f07171", + token: "markup.bold", + }, + { + fontStyle: "bold italic", + token: "markup.italic markup.bold", + }, + { + fontStyle: "bold italic", + token: "markup.bold markup.italic", + }, + { + background: "#5c616605", + token: "markup.raw", + }, + { + background: "#5c61660f", + token: "markup.raw.inline", + }, + { + fontStyle: "bold", + background: "#5c61660f", + foreground: "#787b8099", + token: "meta.separator", + }, + { + foreground: "#4cbf99", + fontStyle: "italic", + token: "markup.quote", + }, + { + foreground: "#f2ae49", + token: "markup.list punctuation.definition.list.begin", + }, + { + foreground: "#6cbf43", + token: "markup.inserted", + }, + { + foreground: "#478acc", + token: "markup.changed", + }, + { + foreground: "#ff7383", + token: "markup.deleted", + }, + { + foreground: "#e6ba7e", + token: "markup.strike", + }, + { + background: "#5c61660f", + foreground: "#55b4d4", + token: "markup.table", + }, + { + foreground: "#ed9366", + token: "text.html.markdown markup.inline.raw", + }, + { + background: "#787b8099", + foreground: "#787b8099", + token: "text.html.markdown meta.dummy.line-break", + }, + { + background: "#5c6166", + foreground: "#787b8099", + token: "punctuation.definition.markdown", + }, + // Edits. + { + foreground: "#fa8d3e", + token: "number", + }, + ], + encodedTokensColors: [], + }); + }, [monaco]); + + return null; +} diff --git a/playground/src/Editor/VersionTag.tsx b/playground/src/Editor/VersionTag.tsx new file mode 100644 index 0000000000..ace2993115 --- /dev/null +++ b/playground/src/Editor/VersionTag.tsx @@ -0,0 +1,26 @@ +import classNames from "classnames"; +import { ReactNode } from "react"; + +export default function VersionTag({ children }: { children: ReactNode }) { + return ( +
+ {children} +
+ ); +} diff --git a/playground/src/Editor/config.ts b/playground/src/Editor/config.ts new file mode 100644 index 0000000000..94fc254b0e --- /dev/null +++ b/playground/src/Editor/config.ts @@ -0,0 +1,63 @@ +import lzstring from "lz-string"; +import { OptionGroup } from "../ruff_options"; + +export type Config = { [K: string]: any }; + +/** + * Parse an encoded value from the options export. + * + * TODO(charlie): Use JSON for the default values. + */ +function parse(value: any): any { + if (value == "None") { + return null; + } + return JSON.parse(value); +} + +/** + * The default configuration for the playground. + */ +export function defaultConfig(availableOptions: OptionGroup[]): Config { + const config: Config = {}; + for (const group of availableOptions) { + if (group.name == "globals") { + for (const field of group.fields) { + config[field.name] = parse(field.default); + } + } else { + config[group.name] = {}; + for (const field of group.fields) { + config[group.name][field.name] = parse(field.default); + } + } + } + return config; +} + +/** + * Persist the configuration to a URL. + */ +export function persist(configSource: string, pythonSource: string) { + window.location.hash = lzstring.compressToEncodedURIComponent( + configSource + "$$$" + pythonSource + ); +} + +/** + * Restore the configuration from a URL. + */ +export function restore(): [string, string] | null { + const value = lzstring.decompressFromEncodedURIComponent( + window.location.hash.slice(1) + ); + + if (value) { + const parts = value.split("$$$"); + const configSource = parts[0]; + const pythonSource = parts[1]; + return [configSource, pythonSource]; + } else { + return null; + } +} diff --git a/playground/src/Editor/index.tsx b/playground/src/Editor/index.tsx new file mode 100644 index 0000000000..32edbc014f --- /dev/null +++ b/playground/src/Editor/index.tsx @@ -0,0 +1,3 @@ +import Editor from "./Editor"; + +export default Editor; diff --git a/playground/src/Options.tsx b/playground/src/Options.tsx deleted file mode 100644 index 375d04429f..0000000000 --- a/playground/src/Options.tsx +++ /dev/null @@ -1,72 +0,0 @@ -import { Config } from "./config"; -import { AVAILABLE_OPTIONS } from "./ruff_options"; - -function OptionEntry({ - config, - defaultConfig, - groupName, - fieldName, - onChange, -}: { - config: Config | null; - defaultConfig: Config; - groupName: string; - fieldName: string; - onChange: (groupName: string, fieldName: string, value: string) => void; -}) { - const value = - config && config[groupName] && config[groupName][fieldName] - ? config[groupName][fieldName] - : ""; - - return ( - - - - ); -} - -export function Options({ - config, - defaultConfig, - onChange, -}: { - config: Config | null; - defaultConfig: Config; - onChange: (groupName: string, fieldName: string, value: string) => void; -}) { - return ( -
- {AVAILABLE_OPTIONS.map((group) => ( -
- {group.name} -
-
    - {group.fields.map((field) => ( -
  • - -
  • - ))} -
-
-
- ))} -
- ); -} diff --git a/playground/src/config.ts b/playground/src/config.ts deleted file mode 100644 index 273272e849..0000000000 --- a/playground/src/config.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { OptionGroup } from "./ruff_options"; - -export type Config = { [key: string]: { [key: string]: string } }; - -export function getDefaultConfig(availableOptions: OptionGroup[]): Config { - const config: Config = {}; - availableOptions.forEach((group) => { - config[group.name] = {}; - group.fields.forEach((f) => { - config[group.name][f.name] = f.default; - }); - }); - return config; -} - -/** - * Convert the config in the application to something Ruff accepts. - * - * Application config is always nested one level. Ruff allows for some - * top-level options. - * - * Any option value is parsed as JSON to convert it to a native JS object. - * If that fails, e.g. while a user is typing, we let the application handle that - * and show an error. - */ -export function toRuffConfig(config: Config): any { - const convertValue = (value: string): any => { - return value === "None" ? null : JSON.parse(value); - }; - - const result: any = {}; - Object.keys(config).forEach((group_name) => { - const fields = config[group_name]; - if (!fields || Object.keys(fields).length === 0) { - return; - } - - if (group_name === "globals") { - Object.keys(fields).forEach((field_name) => { - result[field_name] = convertValue(fields[field_name]); - }); - } else { - result[group_name] = {}; - - Object.keys(fields).forEach((field_name) => { - result[group_name][field_name] = convertValue(fields[field_name]); - }); - } - }); - - return result; -} diff --git a/playground/src/constants.ts b/playground/src/constants.ts new file mode 100644 index 0000000000..3b33cff135 --- /dev/null +++ b/playground/src/constants.ts @@ -0,0 +1,40 @@ +import { defaultConfig } from "./Editor/config"; +import { AVAILABLE_OPTIONS } from "./ruff_options"; + +export const DEFAULT_PYTHON_SOURCE = + "import os\n" + + "\n" + + "# Define a function that takes an integer n and returns the nth number in the Fibonacci\n" + + "# sequence.\n" + + "def fibonacci(n):\n" + + ' """Compute the nth number in the Fibonacci sequence."""\n' + + " x = 1\n" + + " if n == 0:\n" + + " return 0\n" + + " elif n == 1:\n" + + " return 1\n" + + " else:\n" + + " return fibonacci(n - 1) + fibonacci(n - 2)\n" + + "\n" + + "\n" + + "# Use a for loop to generate and print the first 10 numbers in the Fibonacci sequence.\n" + + "for i in range(10):\n" + + " print(fibonacci(i))\n" + + "\n" + + "# Output:\n" + + "# 0\n" + + "# 1\n" + + "# 1\n" + + "# 2\n" + + "# 3\n" + + "# 5\n" + + "# 8\n" + + "# 13\n" + + "# 21\n" + + "# 34\n"; + +export const DEFAULT_CONFIG_SOURCE = JSON.stringify( + defaultConfig(AVAILABLE_OPTIONS), + null, + 2 +); diff --git a/playground/src/index.css b/playground/src/index.css new file mode 100644 index 0000000000..3e52427419 --- /dev/null +++ b/playground/src/index.css @@ -0,0 +1,24 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +* { + box-sizing: border-box; +} + +body, +html, +#root { + margin: 0; + height: 100%; + width: 100%; +} + +.shadow-copied { + --tw-shadow: 0 0 0 1px #f07171, inset 0 0 0 1px #f07171; + --tw-shadow-colored: 0 0 0 1px var(--tw-shadow-color), + inset 0 0 0 1px var(--tw-shadow-color); + + box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), + var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow); +} diff --git a/playground/src/main.tsx b/playground/src/main.tsx index 7d6d78e120..0bfe007ea6 100644 --- a/playground/src/main.tsx +++ b/playground/src/main.tsx @@ -1,10 +1,10 @@ import React from "react"; import ReactDOM from "react-dom/client"; -import App from "./App"; -import "./style.css"; +import Editor from "./Editor"; +import "./index.css"; ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( - + ); diff --git a/playground/src/ruff_options.ts b/playground/src/ruff_options.ts index c0be322c53..be50567516 100644 --- a/playground/src/ruff_options.ts +++ b/playground/src/ruff_options.ts @@ -225,7 +225,7 @@ export const AVAILABLE_OPTIONS: OptionGroup[] = [ {"name": "pydocstyle", "fields": [ { "name": "convention", - "default": '"convention"', + "default": 'None', "type": 'Convention', }, ]}, diff --git a/playground/src/style.css b/playground/src/style.css deleted file mode 100644 index da649ebfc2..0000000000 --- a/playground/src/style.css +++ /dev/null @@ -1,60 +0,0 @@ -* { - box-sizing: border-box; -} - -body, -html, -#root, -#app { - margin: 0; - height: 100%; - width: 100%; -} - -#app { - display: flex; -} - -.options { - height: 100vh; - overflow-y: scroll; - padding: 1em; - min-width: 300px; - border-right: 1px solid lightgray; -} - -.options ul { - padding-left: 1em; - list-style-type: none; -} - -.options li { - margin-bottom: 0.3em; -} - -.options details { - margin-bottom: 1em; -} - -.options summary { - font-size: 1.3rem; -} - -.options input { - display: block; - width: 100%; -} - -.editor { - padding: 1em; -} - -#error { - position: fixed; - bottom: 0; - width: 100%; - min-height: 1em; - padding: 1em; - background: darkred; - color: white; -} diff --git a/playground/src/custom.d.ts b/playground/src/third-party.d.ts similarity index 100% rename from playground/src/custom.d.ts rename to playground/src/third-party.d.ts diff --git a/playground/tailwind.config.cjs b/playground/tailwind.config.cjs new file mode 100644 index 0000000000..a44675389c --- /dev/null +++ b/playground/tailwind.config.cjs @@ -0,0 +1,17 @@ +/** @type {import('tailwindcss').Config} */ +const defaultTheme = require("tailwindcss/defaultTheme"); + +module.exports = { + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + theme: { + extend: { + colors: { + ayu: "#f07171", + }, + fontFamily: { + sans: ["Inter var", ...defaultTheme.fontFamily.sans], + }, + }, + }, + plugins: [], +}; diff --git a/src/lib_wasm.rs b/src/lib_wasm.rs index 2e324ebc37..715b4a064d 100644 --- a/src/lib_wasm.rs +++ b/src/lib_wasm.rs @@ -16,6 +16,8 @@ use crate::settings::{flags, Settings}; use crate::source_code_locator::SourceCodeLocator; use crate::source_code_style::SourceCodeStyleDetector; +const VERSION: &str = env!("CARGO_PKG_VERSION"); + #[wasm_bindgen(typescript_custom_section)] const TYPES: &'static str = r#" export interface Check { @@ -59,6 +61,11 @@ pub fn run() { console_log::init_with_level(Level::Debug).expect("Initializing logger went wrong."); } +#[wasm_bindgen] +pub fn current_version() -> JsValue { + JsValue::from(VERSION) +} + #[wasm_bindgen] pub fn check(contents: &str, options: JsValue) -> Result { let options: Options = serde_wasm_bindgen::from_value(options).map_err(|e| e.to_string())?; diff --git a/src/pydocstyle/settings.rs b/src/pydocstyle/settings.rs index ca75c2333a..31daa36f55 100644 --- a/src/pydocstyle/settings.rs +++ b/src/pydocstyle/settings.rs @@ -17,7 +17,7 @@ pub enum Convention { #[serde(deny_unknown_fields, rename_all = "kebab-case", rename = "Pydocstyle")] pub struct Options { #[option( - default = r#""convention""#, + default = r#"None"#, value_type = "Convention", example = r#" # Use Google-style docstrings.