1
0
mirror of synced 2026-01-01 18:05:46 -05:00

Merge pull request #32807 from github/repo-sync

Repo sync
This commit is contained in:
docs-bot
2024-05-06 05:35:42 -07:00
committed by GitHub
17 changed files with 773 additions and 121 deletions

215
package-lock.json generated
View File

@@ -153,7 +153,7 @@
"typescript": "^5.4.4",
"unist-util-remove": "^4.0.0",
"unist-util-visit-parents": "6.0.1",
"vitest": "1.5.0",
"vitest": "1.6.0",
"website-scraper": "^5.3.1"
},
"engines": {
@@ -2669,9 +2669,9 @@
}
},
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.14.3.tgz",
"integrity": "sha512-X9alQ3XM6I9IlSlmC8ddAvMSyG1WuHk5oUnXGw+yUBs3BFoTizmG1La/Gr8fVJvDWAq+zlYTZ9DBgrlKRVY06g==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.17.2.tgz",
"integrity": "sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==",
"cpu": [
"arm"
],
@@ -2682,9 +2682,9 @@
]
},
"node_modules/@rollup/rollup-android-arm64": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.14.3.tgz",
"integrity": "sha512-eQK5JIi+POhFpzk+LnjKIy4Ks+pwJ+NXmPxOCSvOKSNRPONzKuUvWE+P9JxGZVxrtzm6BAYMaL50FFuPe0oWMQ==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.17.2.tgz",
"integrity": "sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==",
"cpu": [
"arm64"
],
@@ -2695,9 +2695,9 @@
]
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.14.3.tgz",
"integrity": "sha512-Od4vE6f6CTT53yM1jgcLqNfItTsLt5zE46fdPaEmeFHvPs5SjZYlLpHrSiHEKR1+HdRfxuzXHjDOIxQyC3ptBA==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz",
"integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==",
"cpu": [
"arm64"
],
@@ -2708,9 +2708,9 @@
]
},
"node_modules/@rollup/rollup-darwin-x64": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.14.3.tgz",
"integrity": "sha512-0IMAO21axJeNIrvS9lSe/PGthc8ZUS+zC53O0VhF5gMxfmcKAP4ESkKOCwEi6u2asUrt4mQv2rjY8QseIEb1aw==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.17.2.tgz",
"integrity": "sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==",
"cpu": [
"x64"
],
@@ -2721,9 +2721,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.14.3.tgz",
"integrity": "sha512-ge2DC7tHRHa3caVEoSbPRJpq7azhG+xYsd6u2MEnJ6XzPSzQsTKyXvh6iWjXRf7Rt9ykIUWHtl0Uz3T6yXPpKw==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.17.2.tgz",
"integrity": "sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==",
"cpu": [
"arm"
],
@@ -2734,9 +2734,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.14.3.tgz",
"integrity": "sha512-ljcuiDI4V3ySuc7eSk4lQ9wU8J8r8KrOUvB2U+TtK0TiW6OFDmJ+DdIjjwZHIw9CNxzbmXY39wwpzYuFDwNXuw==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.17.2.tgz",
"integrity": "sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==",
"cpu": [
"arm"
],
@@ -2747,9 +2747,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.14.3.tgz",
"integrity": "sha512-Eci2us9VTHm1eSyn5/eEpaC7eP/mp5n46gTRB3Aar3BgSvDQGJZuicyq6TsH4HngNBgVqC5sDYxOzTExSU+NjA==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz",
"integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==",
"cpu": [
"arm64"
],
@@ -2760,9 +2760,9 @@
]
},
"node_modules/@rollup/rollup-linux-arm64-musl": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.14.3.tgz",
"integrity": "sha512-UrBoMLCq4E92/LCqlh+blpqMz5h1tJttPIniwUgOFJyjWI1qrtrDhhpHPuFxULlUmjFHfloWdixtDhSxJt5iKw==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.17.2.tgz",
"integrity": "sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==",
"cpu": [
"arm64"
],
@@ -2773,9 +2773,9 @@
]
},
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.14.3.tgz",
"integrity": "sha512-5aRjvsS8q1nWN8AoRfrq5+9IflC3P1leMoy4r2WjXyFqf3qcqsxRCfxtZIV58tCxd+Yv7WELPcO9mY9aeQyAmw==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.17.2.tgz",
"integrity": "sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==",
"cpu": [
"ppc64"
],
@@ -2786,9 +2786,9 @@
]
},
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.14.3.tgz",
"integrity": "sha512-sk/Qh1j2/RJSX7FhEpJn8n0ndxy/uf0kI/9Zc4b1ELhqULVdTfN6HL31CDaTChiBAOgLcsJ1sgVZjWv8XNEsAQ==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.17.2.tgz",
"integrity": "sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==",
"cpu": [
"riscv64"
],
@@ -2799,9 +2799,9 @@
]
},
"node_modules/@rollup/rollup-linux-s390x-gnu": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.14.3.tgz",
"integrity": "sha512-jOO/PEaDitOmY9TgkxF/TQIjXySQe5KVYB57H/8LRP/ux0ZoO8cSHCX17asMSv3ruwslXW/TLBcxyaUzGRHcqg==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.17.2.tgz",
"integrity": "sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==",
"cpu": [
"s390x"
],
@@ -2812,9 +2812,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.14.3.tgz",
"integrity": "sha512-8ybV4Xjy59xLMyWo3GCfEGqtKV5M5gCSrZlxkPGvEPCGDLNla7v48S662HSGwRd6/2cSneMQWiv+QzcttLrrOA==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz",
"integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==",
"cpu": [
"x64"
],
@@ -2825,9 +2825,9 @@
]
},
"node_modules/@rollup/rollup-linux-x64-musl": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.14.3.tgz",
"integrity": "sha512-s+xf1I46trOY10OqAtZ5Rm6lzHre/UiLA1J2uOhCFXWkbZrJRkYBPO6FhvGfHmdtQ3Bx793MNa7LvoWFAm93bg==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.17.2.tgz",
"integrity": "sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==",
"cpu": [
"x64"
],
@@ -2838,9 +2838,9 @@
]
},
"node_modules/@rollup/rollup-win32-arm64-msvc": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.14.3.tgz",
"integrity": "sha512-+4h2WrGOYsOumDQ5S2sYNyhVfrue+9tc9XcLWLh+Kw3UOxAvrfOrSMFon60KspcDdytkNDh7K2Vs6eMaYImAZg==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.17.2.tgz",
"integrity": "sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==",
"cpu": [
"arm64"
],
@@ -2851,9 +2851,9 @@
]
},
"node_modules/@rollup/rollup-win32-ia32-msvc": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.14.3.tgz",
"integrity": "sha512-T1l7y/bCeL/kUwh9OD4PQT4aM7Bq43vX05htPJJ46RTI4r5KNt6qJRzAfNfM+OYMNEVBWQzR2Gyk+FXLZfogGw==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.17.2.tgz",
"integrity": "sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==",
"cpu": [
"ia32"
],
@@ -2864,9 +2864,9 @@
]
},
"node_modules/@rollup/rollup-win32-x64-msvc": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.14.3.tgz",
"integrity": "sha512-/BypzV0H1y1HzgYpxqRaXGBRqfodgoBBCcsrujT6QRcakDQdfU+Lq9PENPh5jB4I44YWq+0C2eHsHya+nZY1sA==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.17.2.tgz",
"integrity": "sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==",
"cpu": [
"x64"
],
@@ -3682,13 +3682,13 @@
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
},
"node_modules/@vitest/expect": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.5.0.tgz",
"integrity": "sha512-0pzuCI6KYi2SIC3LQezmxujU9RK/vwC1U9R0rLuGlNGcOuDWxqWKu6nUdFsX9tH1WU0SXtAxToOsEjeUn1s3hA==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.6.0.tgz",
"integrity": "sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==",
"dev": true,
"dependencies": {
"@vitest/spy": "1.5.0",
"@vitest/utils": "1.5.0",
"@vitest/spy": "1.6.0",
"@vitest/utils": "1.6.0",
"chai": "^4.3.10"
},
"funding": {
@@ -3696,12 +3696,12 @@
}
},
"node_modules/@vitest/runner": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.5.0.tgz",
"integrity": "sha512-7HWwdxXP5yDoe7DTpbif9l6ZmDwCzcSIK38kTSIt6CFEpMjX4EpCgT6wUmS0xTXqMI6E/ONmfgRKmaujpabjZQ==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.6.0.tgz",
"integrity": "sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==",
"dev": true,
"dependencies": {
"@vitest/utils": "1.5.0",
"@vitest/utils": "1.6.0",
"p-limit": "^5.0.0",
"pathe": "^1.1.1"
},
@@ -3737,9 +3737,9 @@
}
},
"node_modules/@vitest/snapshot": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.5.0.tgz",
"integrity": "sha512-qpv3fSEuNrhAO3FpH6YYRdaECnnRjg9VxbhdtPwPRnzSfHVXnNzzrpX4cJxqiwgRMo7uRMWDFBlsBq4Cr+rO3A==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.6.0.tgz",
"integrity": "sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==",
"dev": true,
"dependencies": {
"magic-string": "^0.30.5",
@@ -3751,9 +3751,9 @@
}
},
"node_modules/@vitest/spy": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.5.0.tgz",
"integrity": "sha512-vu6vi6ew5N5MMHJjD5PoakMRKYdmIrNJmyfkhRpQt5d9Ewhw9nZ5Aqynbi3N61bvk9UvZ5UysMT6ayIrZ8GA9w==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.6.0.tgz",
"integrity": "sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==",
"dev": true,
"dependencies": {
"tinyspy": "^2.2.0"
@@ -3763,9 +3763,9 @@
}
},
"node_modules/@vitest/utils": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.5.0.tgz",
"integrity": "sha512-BDU0GNL8MWkRkSRdNFvCUCAVOeHaUlVJ9Tx0TYBZyXaaOTmGtUFObzchCivIBrIwKzvZA7A9sCejVhXM2aY98A==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.6.0.tgz",
"integrity": "sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==",
"dev": true,
"dependencies": {
"diff-sequences": "^29.6.3",
@@ -9266,15 +9266,12 @@
}
},
"node_modules/magic-string": {
"version": "0.30.9",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.9.tgz",
"integrity": "sha512-S1+hd+dIrC8EZqKyT9DstTH/0Z+f76kmmvZnkfQVmOpDEF9iVgdYif3Q/pIWHmCoo59bQVGW0kVL3e2nl+9+Sw==",
"version": "0.30.10",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
"integrity": "sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.4.15"
},
"engines": {
"node": ">=12"
}
},
"node_modules/magic-string/node_modules/@jridgewell/sourcemap-codec": {
@@ -12588,9 +12585,9 @@
}
},
"node_modules/rollup": {
"version": "4.14.3",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.14.3.tgz",
"integrity": "sha512-ag5tTQKYsj1bhrFC9+OEWqb5O6VYgtQDO9hPDBMmIbePwhfSr+ExlcU741t8Dhw5DkPCQf6noz0jb36D6W9/hw==",
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.17.2.tgz",
"integrity": "sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==",
"dev": true,
"dependencies": {
"@types/estree": "1.0.5"
@@ -12603,22 +12600,22 @@
"npm": ">=8.0.0"
},
"optionalDependencies": {
"@rollup/rollup-android-arm-eabi": "4.14.3",
"@rollup/rollup-android-arm64": "4.14.3",
"@rollup/rollup-darwin-arm64": "4.14.3",
"@rollup/rollup-darwin-x64": "4.14.3",
"@rollup/rollup-linux-arm-gnueabihf": "4.14.3",
"@rollup/rollup-linux-arm-musleabihf": "4.14.3",
"@rollup/rollup-linux-arm64-gnu": "4.14.3",
"@rollup/rollup-linux-arm64-musl": "4.14.3",
"@rollup/rollup-linux-powerpc64le-gnu": "4.14.3",
"@rollup/rollup-linux-riscv64-gnu": "4.14.3",
"@rollup/rollup-linux-s390x-gnu": "4.14.3",
"@rollup/rollup-linux-x64-gnu": "4.14.3",
"@rollup/rollup-linux-x64-musl": "4.14.3",
"@rollup/rollup-win32-arm64-msvc": "4.14.3",
"@rollup/rollup-win32-ia32-msvc": "4.14.3",
"@rollup/rollup-win32-x64-msvc": "4.14.3",
"@rollup/rollup-android-arm-eabi": "4.17.2",
"@rollup/rollup-android-arm64": "4.17.2",
"@rollup/rollup-darwin-arm64": "4.17.2",
"@rollup/rollup-darwin-x64": "4.17.2",
"@rollup/rollup-linux-arm-gnueabihf": "4.17.2",
"@rollup/rollup-linux-arm-musleabihf": "4.17.2",
"@rollup/rollup-linux-arm64-gnu": "4.17.2",
"@rollup/rollup-linux-arm64-musl": "4.17.2",
"@rollup/rollup-linux-powerpc64le-gnu": "4.17.2",
"@rollup/rollup-linux-riscv64-gnu": "4.17.2",
"@rollup/rollup-linux-s390x-gnu": "4.17.2",
"@rollup/rollup-linux-x64-gnu": "4.17.2",
"@rollup/rollup-linux-x64-musl": "4.17.2",
"@rollup/rollup-win32-arm64-msvc": "4.17.2",
"@rollup/rollup-win32-ia32-msvc": "4.17.2",
"@rollup/rollup-win32-x64-msvc": "4.17.2",
"fsevents": "~2.3.2"
}
},
@@ -14409,9 +14406,9 @@
}
},
"node_modules/vite": {
"version": "5.2.8",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.8.tgz",
"integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==",
"version": "5.2.11",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
"integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==",
"dev": true,
"dependencies": {
"esbuild": "^0.20.1",
@@ -14464,9 +14461,9 @@
}
},
"node_modules/vite-node": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.5.0.tgz",
"integrity": "sha512-tV8h6gMj6vPzVCa7l+VGq9lwoJjW8Y79vst8QZZGiuRAfijU+EEWuc0kFpmndQrWhMMhet1jdSF+40KSZUqIIw==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.6.0.tgz",
"integrity": "sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==",
"dev": true,
"dependencies": {
"cac": "^6.7.14",
@@ -14934,16 +14931,16 @@
}
},
"node_modules/vitest": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-1.5.0.tgz",
"integrity": "sha512-d8UKgR0m2kjdxDWX6911uwxout6GHS0XaGH1cksSIVVG8kRlE7G7aBw7myKQCvDI5dT4j7ZMa+l706BIORMDLw==",
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/vitest/-/vitest-1.6.0.tgz",
"integrity": "sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==",
"dev": true,
"dependencies": {
"@vitest/expect": "1.5.0",
"@vitest/runner": "1.5.0",
"@vitest/snapshot": "1.5.0",
"@vitest/spy": "1.5.0",
"@vitest/utils": "1.5.0",
"@vitest/expect": "1.6.0",
"@vitest/runner": "1.6.0",
"@vitest/snapshot": "1.6.0",
"@vitest/spy": "1.6.0",
"@vitest/utils": "1.6.0",
"acorn-walk": "^8.3.2",
"chai": "^4.3.10",
"debug": "^4.3.4",
@@ -14957,7 +14954,7 @@
"tinybench": "^2.5.1",
"tinypool": "^0.8.3",
"vite": "^5.0.0",
"vite-node": "1.5.0",
"vite-node": "1.6.0",
"why-is-node-running": "^2.2.2"
},
"bin": {
@@ -14972,8 +14969,8 @@
"peerDependencies": {
"@edge-runtime/vm": "*",
"@types/node": "^18.0.0 || >=20.0.0",
"@vitest/browser": "1.5.0",
"@vitest/ui": "1.5.0",
"@vitest/browser": "1.6.0",
"@vitest/ui": "1.6.0",
"happy-dom": "*",
"jsdom": "*"
},

View File

@@ -37,7 +37,7 @@
"fixture-test": "cross-env ROOT=src/fixtures/fixtures npm test -- src/fixtures/tests",
"index": "tsx src/search/scripts/index/index.ts",
"index-elasticsearch": "node src/search/scripts/index-elasticsearch.js",
"index-test-fixtures": "npm run index-elasticsearch -- -l en -l ja -V ghec -V dotcom --index-prefix tests -- src/search/tests/fixtures/search-indexes",
"index-test-fixtures": "./src/search/scripts/index-test-fixtures.sh",
"lint": "eslint '**/*.{js,mjs,ts,tsx}'",
"lint-content": "node src/content-linter/scripts/lint-content.js",
"lint-translation": "vitest src/content-linter/tests/lint-files.js",
@@ -339,7 +339,7 @@
"typescript": "^5.4.4",
"unist-util-remove": "^4.0.0",
"unist-util-visit-parents": "6.0.1",
"vitest": "1.5.0",
"vitest": "1.6.0",
"website-scraper": "^5.3.1"
},
"overrides": {},

View File

@@ -183,6 +183,48 @@ export async function getSearchResults({
return { meta, hits }
}
export async function getAutocompleteSearchResults({ indexName, query, size }) {
const client = getClient()
const matchQueries = getAutocompleteMatchQueries(query.trim(), {
fuzzy: {
minLength: 3,
maxLength: 20,
},
})
const matchQuery = {
bool: {
should: matchQueries,
},
}
const highlight = getHighlightConfiguration(query, ['term'])
const searchQuery = {
index: indexName,
highlight,
size,
query: matchQuery,
// Send absolutely minimal from Elasticsearch to here. Less data => faster.
_source_includes: ['term'],
}
const result = await client.search(searchQuery)
const hitsAll = result.hits
const hits = hitsAll.hits.map((hit) => {
return {
term: hit._source.term,
highlights: (hit.highlight && hit.highlight.term) || [],
}
})
const meta = {
found: hitsAll.total,
}
return { meta, hits }
}
function getMatchQueries(query, { usePrefixSearch, fuzzy }) {
const BOOST_PHRASE = 10.0
const BOOST_TITLE = 4.0
@@ -371,6 +413,46 @@ function getMatchQueries(query, { usePrefixSearch, fuzzy }) {
return matchQueries
}
function getAutocompleteMatchQueries(query, { fuzzy }) {
const BOOST_PHRASE = 4.0
const BOOST_REGULAR = 2.0
const BOOST_FUZZY = 0.1 // make it always last in ranking
const matchQueries = []
// If the query input is multiple words, it's good to know because you can
// make the query do `match_phrase` and you can make `match` query
// with the `AND` operator (`OR` is the default).
const isMultiWordQuery = query.includes(' ') || query.includes('-')
if (isMultiWordQuery) {
matchQueries.push({
match_phrase_prefix: {
term: {
query,
boost: BOOST_PHRASE,
},
},
})
}
matchQueries.push({
match_bool_prefix: {
term: {
query,
boost: BOOST_REGULAR,
},
},
})
if (query.length > fuzzy.minLength && query.length < fuzzy.maxLength) {
matchQueries.push({
fuzzy: {
term: { value: query, boost: BOOST_FUZZY, fuzziness: 'AUTO' },
},
})
}
return matchQueries
}
function getHits(hits, { indexName, debug, includeTopics, highlightFields, include }) {
return hits.map((hit) => {
// Return `hit.highlights[...]` based on the highlight fields requested.
@@ -464,7 +546,16 @@ function getHighlightConfiguration(query, highlights) {
},
}
}
if (highlights.includes('term')) {
fields.term = {
// Fast Vector Highlighter
// Using this requires that you first index these fields
// with {term_vector: 'with_positions_offsets'}
type: 'fvh',
// fragment_size: 200,
// number_of_fragments: 1,
}
}
return {
pre_tags: ['<mark>'],
post_tags: ['</mark>'],

View File

@@ -5,7 +5,9 @@ import { allVersions } from '#src/versions/lib/all-versions.js'
import { POSSIBLE_HIGHLIGHT_FIELDS, DEFAULT_HIGHLIGHT_FIELDS } from './es-search.js'
const DEFAULT_SIZE = 10
const DEFAULT_AUTOCOMPLETE_SIZE = 8
const MAX_SIZE = 50 // How much you return has a strong impact on performance
const MAX_AUTOCOMPLETE_SIZE = 10
const DEFAULT_PAGE = 1
const POSSIBLE_SORTS = ['best', 'relevance']
const DEFAULT_SORT = POSSIBLE_SORTS[0]
@@ -23,6 +25,7 @@ const V1_ADDITIONAL_INCLUDES = ['intro', 'headings']
// In some distant future we can clean up any client enough that this
// aliasing won't be necessary.
const versionAliases = {}
const prefixVersionAliases = {}
Object.values(allVersions).forEach((info) => {
if (info.hasNumberedReleases) {
versionAliases[info.currentRelease] = info.miscVersionName
@@ -30,6 +33,11 @@ Object.values(allVersions).forEach((info) => {
versionAliases[info.version] = info.miscVersionName
versionAliases[info.miscVersionName] = info.miscVersionName
}
// This makes it so you can search for `?version=enterprise-server`
// and that actually means `?version=ghes` because there's an index
// called `github-autocomplete-en-ghes`.
prefixVersionAliases[info.plan] = info.shortName
prefixVersionAliases[info.shortName] = info.shortName
})
function getIndexPrefix() {
@@ -102,11 +110,44 @@ const PARAMS = [
},
]
export function getSearchFromRequest(req, force = {}) {
const AUTOCOMPLETE_PARAMS = [
{ key: 'query' },
{ key: 'language', default_: 'en', validate: (v) => v in languages },
{
key: 'version',
default_: 'free-pro-team',
validate: (v) => {
if (prefixVersionAliases[v] || allVersions[v]) return true
if (Object.values(prefixVersionAliases).includes(v)) return true
const valid = [
...Object.keys(prefixVersionAliases),
...Object.values(prefixVersionAliases),
...Object.keys(allVersions),
]
throw new ValidationError(`'${v}' not in ${valid.join(', ')}`)
},
},
{
key: 'size',
default_: DEFAULT_AUTOCOMPLETE_SIZE,
cast: (v) => parseInt(v, 10),
validate: (v) => v >= 0 && v <= MAX_AUTOCOMPLETE_SIZE,
},
]
export function getAutocompleteSearchFromRequest(req, force = {}) {
const { search, validationErrors } = getSearchFromRequest(req, {}, AUTOCOMPLETE_PARAMS)
if (validationErrors.length === 0) {
const version = prefixVersionAliases[search.version] || allVersions[search.version].shortName
search.indexName = `${getIndexPrefix()}github-autocomplete-${search.language}-${version}`
}
return { search, validationErrors }
}
export function getSearchFromRequest(req, force = {}, params = PARAMS) {
const search = {}
const validationErrors = []
for (const { key, default_, cast, validate, multiple } of PARAMS) {
for (const { key, default_, cast, validate, multiple } of params) {
// This is necessary because when the version or language comes from
// the pathname, we don't want pick these up from the query string.
// This function gets used by /$locale/$version/search
@@ -153,7 +194,10 @@ export function getSearchFromRequest(req, force = {}) {
}
if (!validationErrors.length) {
const version = versionAliases[search.version] || allVersions[search.version].miscVersionName
const version =
prefixVersionAliases[search.version] ||
versionAliases[search.version] ||
allVersions[search.version].miscVersionName
search.indexName = `${getIndexPrefix()}github-docs-${version}-${search.language}` // github-docs-ghes-3.5-en
}

View File

@@ -7,8 +7,8 @@ import {
setFastlySurrogateKey,
SURROGATE_ENUMS,
} from '#src/frame/middleware/set-fastly-surrogate-key.js'
import { getSearchResults } from './es-search.js'
import { getSearchFromRequest } from './get-search-request.js'
import { getAutocompleteSearchResults, getSearchResults } from './es-search.js'
import { getAutocompleteSearchFromRequest, getSearchFromRequest } from './get-search-request.js'
const router = express.Router()
@@ -69,6 +69,52 @@ router.get(
}),
)
export const autocompleteValidationMiddleware = (req, res, next) => {
const { search, validationErrors } = getAutocompleteSearchFromRequest(req)
if (validationErrors.length) {
// There might be multiple things bad about the query parameters,
// but we send a 400 on the first possible one in the API.
return res.status(400).json(validationErrors[0])
}
req.search = search
return next()
}
router.get(
'/autocomplete/v1',
autocompleteValidationMiddleware,
catchMiddlewareError(async (req, res) => {
const { indexName, query, size } = req.search
const options = {
indexName,
query,
size,
}
try {
const { meta, hits } = await getAutocompleteSearchResults(options)
if (process.env.NODE_ENV !== 'development') {
searchCacheControl(res)
// We can cache this without purging it after every deploy
// because the API search is only used as a proxy for local
// and preview environments.
setFastlySurrogateKey(res, SURROGATE_ENUMS.MANUAL)
}
// The v1 version of the output matches perfectly what comes out
// of the getSearchResults() function.
res.status(200).json({ meta, hits })
} catch (error) {
// If getSearchResult() throws an error that might be 404 inside
// elasticsearch, if we don't capture that here, it will propagate
// to the next middleware.
await handleGetSearchResultsError(req, res, error, options)
}
}),
)
// We have more than one place where we do `try{...} catch error( THIS )`
// which is slightly different depending on the "sub-version" (e.g. /legacy)
// This function is a single place to take care of all of these error handlings
@@ -93,4 +139,9 @@ router.get('/', (req, res) => {
res.redirect(307, req.originalUrl.replace('/search', '/search/v1'))
})
// Alias for the latest autocomplete version
router.get('/autocomplete', (req, res) => {
res.redirect(307, req.originalUrl.replace('/search/autocomplete', '/search/autocomplete/v1'))
})
export default router

View File

@@ -0,0 +1,12 @@
#!/bin/bash
# This exists as a bash script because the commands are a bit too long
# and complex to express inside `package.json`.
set -e
# For general site-search
npm run index-elasticsearch -- -l en -l ja -V ghec -V dotcom --index-prefix tests -- src/search/tests/fixtures/search-indexes
# For autocomplete search
npm run index -- autocomplete src/search/tests/fixtures/data -l en -l ja -v fpt -v ghec --index-prefix tests

View File

@@ -24,6 +24,7 @@ type Options = {
retries?: number
sleepTime?: number
verbose?: boolean
indexPrefix?: string
}
export async function indexAutocomplete(options: Options) {
@@ -38,7 +39,12 @@ export async function indexAutocomplete(options: Options) {
for (const language of languages) {
for (const version of versions) {
const records = loadRecords({ version, language, dataRepoRoot })
const { alias, name } = await createIndex(client, language, version)
const { alias, name } = await createIndex(
client,
language,
version,
options.indexPrefix || '',
)
await populate(client, records, {
alias,
name,
@@ -109,7 +115,12 @@ type IndexInfo = {
name: string
}
async function createIndex(client: Client, language: string, version: Version): Promise<IndexInfo> {
async function createIndex(
client: Client,
language: string,
version: Version,
indexPrefix: string,
): Promise<IndexInfo> {
const settings: estypes.IndicesIndexSettings = {
analysis: {
analyzer: {
@@ -126,7 +137,11 @@ async function createIndex(client: Client, language: string, version: Version):
// XXX SNOWBALL?
}
const indexName = `github-autocomplete-${language}-${shortVersionNames[version] || version}`
if (indexPrefix && !indexPrefix.endsWith('_')) {
indexPrefix += '_'
}
const indexName = `${indexPrefix}github-autocomplete-${language}-${shortVersionNames[version] || version}`
const thisAlias = `${indexName}__${utcTimestamp()}`
const mappings: estypes.MappingTypeMapping = {

View File

@@ -25,6 +25,7 @@ program
]),
)
.option('--verbose', 'Verbose output')
.option('--index-prefix <prefix>', 'Prefix for the index names', '')
.argument('<data-root>', 'path to the docs-internal-data repo')
.action((root: string, options) => {
const languages = options.language ? options.language : languageKeys
@@ -36,7 +37,8 @@ program
versions.push(v)
}
}
return indexAutocomplete({ dataRepoRoot: root, languages, versions })
const indexPrefix = options.indexPrefix || ''
return indexAutocomplete({ dataRepoRoot: root, languages, versions, indexPrefix })
})
program.parse(process.argv)

View File

@@ -0,0 +1,136 @@
/**
* To be able to run these tests you need to index the fixtures!
* And you need to have an Elasticsearch URL to connect to for the server.
*
* To index the fixtures, run:
*
* ELASTICSEARCH_URL=http://localhost:9200 npm run index-test-fixtures
*
* This will replace any "real" Elasticsearch indexes you might have so
* once you're done working on vitest tests you need to index real
* content again.
*/
import { expect, test, vi } from 'vitest'
import { describeIfElasticsearchURL } from '#src/tests/helpers/conditional-runs.js'
import { get } from '#src/tests/helpers/e2etest.js'
if (!process.env.ELASTICSEARCH_URL) {
console.warn(
'None of the API search middleware tests are run because ' +
"the environment variable 'ELASTICSEARCH_URL' is currently not set.",
)
}
// This suite only runs if $ELASTICSEARCH_URL is set.
describeIfElasticsearchURL('search/autocomplete v1 middleware', () => {
vi.setConfig({ testTimeout: 60 * 1000 })
test('basic search', async () => {
const sp = new URLSearchParams()
// To see why this will work,
// see src/search/tests/fixtures/data
sp.set('query', 'fo')
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(200)
const results = JSON.parse(res.body)
expect(results.meta).toBeTruthy()
expect(results.meta.found.value).toBeGreaterThanOrEqual(1)
expect(results.meta.found.relation).toBeTruthy()
// Might be empty but at least an array
expect(results.hits).toBeTruthy()
// The work "fork" matches "fo"
const hit = results.hits[0]
expect(hit.term).toBe('fork')
expect(hit.highlights).toBeTruthy()
expect(hit.highlights[0]).toBe('<mark>fork</mark>')
// Check that it can be cached at the CDN
expect(res.headers['set-cookie']).toBeUndefined()
expect(res.headers['cache-control']).toContain('public')
expect(res.headers['cache-control']).toMatch(/max-age=[1-9]/)
expect(res.headers['surrogate-control']).toContain('public')
expect(res.headers['surrogate-control']).toMatch(/max-age=[1-9]/)
expect(res.headers['surrogate-key']).toBe('manual-purge')
})
test('invalid version', async () => {
const sp = new URLSearchParams()
sp.set('query', 'fo')
sp.set('version', 'never-heard-of')
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(400)
expect(JSON.parse(res.body).error).toBeTruthy()
})
test('variations on version name', async () => {
const sp = new URLSearchParams()
sp.set('query', 'fo')
sp.set('version', 'enterprise-cloud')
{
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(200)
}
sp.set('version', 'ghec')
{
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(200)
}
sp.set('version', 'fpt')
{
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(200)
}
sp.set('version', 'free-pro-team@latest')
{
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(200)
}
})
test('invalid language', async () => {
const sp = new URLSearchParams()
sp.set('query', 'fo')
sp.set('language', 'xx')
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(400)
expect(JSON.parse(res.body).error).toBeTruthy()
})
test('fuzzy autocomplete search', async () => {
const sp = new URLSearchParams()
sp.set('query', 'forc')
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(200)
const results = JSON.parse(res.body)
// The work "fork" matches "fo"
const hit = results.hits[0]
expect(hit.term).toBe('fork')
expect(hit.highlights).toBeTruthy()
expect(hit.highlights[0]).toBe('<mark>fork</mark>')
})
test('invalid query', async () => {
const sp = new URLSearchParams()
// No query at all
{
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(400)
}
// Empty query
{
sp.set('query', '')
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(400)
}
// Empty when trimmed
{
sp.set('query', ' ')
const res = await get('/api/search/autocomplete/v1?' + sp)
expect(res.statusCode).toBe(400)
}
})
})

View File

@@ -0,0 +1,26 @@
{
"github": 631,
"api": 213,
"rest": 198,
"rest api": 196,
"endpoints": 176,
"api endpoints": 172,
"rest api endpoints": 172,
"managing": 165,
"organization": 155,
"repository": 144,
"using": 126,
"code": 81,
"app": 79,
"actions": 76,
"creating": 76,
"security": 75,
"codespaces": 70,
"pull": 70,
"configuring": 64,
"project": 61,
"copilot": 58,
"github actions": 57,
"access": 56,
"codeql": 54
}

View File

@@ -0,0 +1,26 @@
{
"github": 631,
"api": 213,
"rest": 198,
"rest api": 196,
"endpoints": 176,
"api endpoints": 172,
"rest api endpoints": 172,
"managing": 165,
"organization": 155,
"repository": 144,
"using": 126,
"code": 81,
"app": 79,
"actions": 76,
"creating": 76,
"security": 75,
"codespaces": 70,
"pull": 70,
"configuring": 64,
"project": 61,
"copilot": 58,
"github actions": 57,
"access": 56,
"codeql": 54
}

View File

@@ -0,0 +1,52 @@
{
"github": 608,
"api": 204,
"rest": 192,
"rest api": 192,
"api \u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8": 169,
"rest api \u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8": 169,
"\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8": 169,
"organization": 110,
"codespaces": 58,
"codeql": 54,
"copilot": 51,
"actions": 49,
"github codespaces": 46,
"\u306b\u3064\u3044\u3066": 46,
"github actions": 45,
"github copilot": 42,
"app": 41,
"git": 41,
"classic": 36,
"project": 36,
"github app": 35,
"issue": 33,
"codespace": 31,
"dependabot": 31,
"oauth": 31,
"cli": 30,
"code": 30,
"desktop": 30,
"github desktop": 30,
"enterprise": 29,
"projects": 28,
"pull": 28,
"github enterprise": 26,
"\u3067\u306e": 26,
"pages": 25,
"pull request": 25,
"request": 25,
"github pages": 23,
"project classic": 23,
"azure": 21,
"importer": 20,
"database": 19,
"webhook": 19,
"team": 18,
"\u30ea\u30dd\u30b8\u30c8\u30ea": 18,
"marketplace": 17,
"\u306e\u4f7f\u7528": 17,
"github marketplace": 16,
"ssh": 16,
"\u30ab\u30b9\u30bf\u30e0": 16
}

View File

@@ -0,0 +1,52 @@
{
"github": 608,
"api": 204,
"rest": 192,
"rest api": 192,
"api \u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8": 169,
"rest api \u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8": 169,
"\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8": 169,
"organization": 110,
"codespaces": 58,
"codeql": 54,
"copilot": 51,
"actions": 49,
"github codespaces": 46,
"\u306b\u3064\u3044\u3066": 46,
"github actions": 45,
"github copilot": 42,
"app": 41,
"git": 41,
"classic": 36,
"project": 36,
"github app": 35,
"issue": 33,
"codespace": 31,
"dependabot": 31,
"oauth": 31,
"cli": 30,
"code": 30,
"desktop": 30,
"github desktop": 30,
"enterprise": 29,
"projects": 28,
"pull": 28,
"github enterprise": 26,
"\u3067\u306e": 26,
"pages": 25,
"pull request": 25,
"request": 25,
"github pages": 23,
"project classic": 23,
"azure": 21,
"importer": 20,
"database": 19,
"webhook": 19,
"team": 18,
"\u30ea\u30dd\u30b8\u30c8\u30ea": 18,
"marketplace": 17,
"\u306e\u4f7f\u7528": 17,
"github marketplace": 16,
"ssh": 16,
"\u30ab\u30b9\u30bf\u30e0": 16
}

View File

@@ -0,0 +1,51 @@
{
"copilot": 141.3,
"inputs": 98.3,
"codeowners": 79.9,
"personal access token": 73.7,
"scim": 73.7,
"emu": 67.6,
"google": 61.4,
"ssh": 55.3,
"enterprise managed users": 55.3,
"enterprise": 49.1,
"audit log": 49.1,
"octocat": 49.1,
"rulesets": 43.0,
"teams": 43.0,
"saml": 43.0,
"oidc": 43.0,
"copilot api": 36.9,
"input": 36.9,
"release": 36.9,
"ssh key": 36.9,
"actions": 31.4,
"public code": 30.7,
"copilot enterprise": 30.7,
"license": 30.7,
"outside collaborators": 30.7,
"enterprise managed user": 30.7,
"github actions": 24.6,
"invite": 24.6,
"merge queue": 24.6,
"repository roles": 24.6,
"api": 24.6,
"workflow_dispatch": 24.6,
"github app": 24.6,
"oauth": 24.6,
"support": 24.6,
"dependabot": 24.6,
"personal access tokens": 24.6,
"secrets": 24.6,
"graphql": 24.6,
"token": 24.6,
"rest api": 24.6,
"audit logs": 24.6,
"pages": 18.4,
"security manager": 18.4,
"fork": 18.4,
"push": 18.4,
"enterprise policy": 18.4,
"environments": 18.4,
"okta": 18.4
}

View File

@@ -0,0 +1,51 @@
{
"copilot": 141.3,
"inputs": 98.3,
"codeowners": 79.9,
"personal access token": 73.7,
"scim": 73.7,
"emu": 67.6,
"google": 61.4,
"ssh": 55.3,
"enterprise managed users": 55.3,
"enterprise": 49.1,
"audit log": 49.1,
"octocat": 49.1,
"rulesets": 43.0,
"teams": 43.0,
"saml": 43.0,
"oidc": 43.0,
"copilot api": 36.9,
"input": 36.9,
"release": 36.9,
"ssh key": 36.9,
"actions": 31.4,
"public code": 30.7,
"copilot enterprise": 30.7,
"license": 30.7,
"outside collaborators": 30.7,
"enterprise managed user": 30.7,
"github actions": 24.6,
"invite": 24.6,
"merge queue": 24.6,
"repository roles": 24.6,
"api": 24.6,
"workflow_dispatch": 24.6,
"github app": 24.6,
"oauth": 24.6,
"support": 24.6,
"dependabot": 24.6,
"personal access tokens": 24.6,
"secrets": 24.6,
"graphql": 24.6,
"token": 24.6,
"rest api": 24.6,
"audit logs": 24.6,
"pages": 18.4,
"security manager": 18.4,
"fork": 18.4,
"push": 18.4,
"enterprise policy": 18.4,
"environments": 18.4,
"okta": 18.4
}

View File

@@ -0,0 +1,23 @@
{
"youtube": 43.0,
"ssh": 20.6,
"copilot": 18.4,
"google": 14.0,
"\u30ea\u30fc\u30b8\u30e7\u30f3": 13.7,
"workflow_run": 13.7,
"\u65e5\u672c\u8a9e": 13.7,
"\u691c\u7d22": 13.7,
"workflow_dispatch": 13.4,
"\u8a00\u8a9e": 13.4,
"\u5909\u6570": 13.4,
"uses": 12.6,
"\u30c8\u30fc\u30af\u30f3": 12.6,
"fork": 12.6,
"japanese": 12.6,
"permissions": 12.3,
"\u5bb9\u91cf": 12.3,
"actions/checkout": 12.3,
"github.event": 12.3,
"homebrew": 12.3,
"copilot workspace": 12.3
}

View File

@@ -0,0 +1,23 @@
{
"youtube": 43.0,
"ssh": 20.6,
"copilot": 18.4,
"google": 14.0,
"\u30ea\u30fc\u30b8\u30e7\u30f3": 13.7,
"workflow_run": 13.7,
"\u65e5\u672c\u8a9e": 13.7,
"\u691c\u7d22": 13.7,
"workflow_dispatch": 13.4,
"\u8a00\u8a9e": 13.4,
"\u5909\u6570": 13.4,
"uses": 12.6,
"\u30c8\u30fc\u30af\u30f3": 12.6,
"fork": 12.6,
"japanese": 12.6,
"permissions": 12.3,
"\u5bb9\u91cf": 12.3,
"actions/checkout": 12.3,
"github.event": 12.3,
"homebrew": 12.3,
"copilot workspace": 12.3
}