mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-09 14:44:51 +03:00
Merge remote-tracking branch 'main/master'
# Conflicts: # README.md # package.json # src/services/RedocNormalizedOptions.ts # tslint.json # yarn.lock
This commit is contained in:
commit
4cc3706585
6
.github/CONTRIBUTING.md
vendored
6
.github/CONTRIBUTING.md
vendored
|
@ -36,7 +36,7 @@ $ yarn install # or npm
|
|||
# dev-server, watch and auto reload playground
|
||||
$ yarn start
|
||||
|
||||
# start playground app in production environement
|
||||
# start playground app in production environment
|
||||
$ yarn start:prod
|
||||
|
||||
# runt tslint
|
||||
|
@ -84,11 +84,11 @@ There are some other scripts available in the `scripts` section of the `package.
|
|||
|
||||
- **`src`**: contains the source code. The codebase is written in Typescript. CSS styles are managed with [Styled components](https://www.styled-components.com/). State is managed by [MobX](https://github.com/mobxjs/mobx)
|
||||
|
||||
- **`src/common-elements`**: containts common Styled elements or components used in multiple places
|
||||
- **`src/common-elements`**: contains common Styled elements or components used in multiple places
|
||||
- **`src/components`**: contains main visual components
|
||||
- **`src/services`**: contains different services used by ReDoc including MobX stores
|
||||
- **`src/services/models`**: contains classes for OpenAPI entities (e.g. Response, Operations, etc)
|
||||
- **`src/types`**: contains extra typescript typings including OpenAPI doc typings
|
||||
- **`src/utils`**: utility functions
|
||||
- **`src/styled-components.ts`**: - reexprots styled-components with proper typescript annotations using theme
|
||||
- **`src/styled-components.ts`**: - reexports styled-components with proper typescript annotations using theme
|
||||
- **`src/theme.ts`**: - default theme (colors, fonts, etc) used by all the components
|
||||
|
|
21
.travis.yml
21
.travis.yml
|
@ -4,23 +4,22 @@ node_js:
|
|||
cache:
|
||||
yarn: true
|
||||
directories:
|
||||
# we also need to cache folder with Cypress binary
|
||||
- ~/.cache
|
||||
- "~/.cache"
|
||||
env:
|
||||
global:
|
||||
- GH_REF: github.com/Redocly/redoc.git
|
||||
- GIT_AUTHOR_EMAIL: redoc-bot@users.noreply.github.com
|
||||
- GIT_AUTHOR_NAME: RedocBot
|
||||
- secure: H2GClDJ7TEQaWgnk8d2fIVDpLwG3rTmN8TalUzrCqXGoG6ylCVmlwzKLgfPPWrVgSA7QTdfNV0ab7c2KyPoZBinHmeGMSuKNLVbhOXRc2VFxTBntBTuyJhfCgQEpUKvJesJUuv5RuBn//wC7VZcVVNc06TZDEe8+aDVYQuCRMXZJ4X3e6nSZ64QX2veyVcr+TjnRsZPkeBVcK9hngvuaxLb/hbJ85CvjiseZRt47PGIcrEpMn9n2GMw1m0fNnPoN+MBTSCnIklTmdjPG7t4GUSLmD6H0lNLdXuehYqmQAHgYrLec1aiFlV57QaDoDZrq2hSf4vDmCB/FVydGhD5JunI67pujoV2OnD1V80eUZhYNWOYsJ2Nfp4NxgXsPUcE6zWLYsLfktMPZADhOXInQRACt1cnx8zMYKLnch1RY/ZqjSg0nPtRjLzQ0lNsw5leixvBdBnMjxYHVyAWVwg8WiJMaLO9vog2Qnxg1NTacHO2CsOmm2rw6stpg7ndp/+nOleRlfUKggjt0Tn3FjwCIXeGup2P2EBa+WW2YMAaoMFofYviR5vRlKBgdKo9fsAruaO1r6nm2EdAjOlniyw92bEfU/qOey1nVp/oK2S82uT5In8KB7vl6rF3ak7WAsT9Q5vZUhsrG+eE4PVyIyWNBhs4A7pSwZGHDR/MYtp0E2ug=
|
||||
- secure: apiavCfCQngL9Een1m7MIXMf3bqO3rY4YY59TMBl/yFKi80CEsHPHhgVUkl6hC+aM5PeBt/vgjh37rHMX31j/pcSZ4Z8SO/4Bwr36iHfhSxSEuAQog8P07qWqH7wYYWGIVmF682stgl0fYF+GN92sx/6edFVzsWVECf2G7imtICKSTbhKGm3Dhn2JwGnhD7eyfgZ33omgiaswumdu0xABoXDfqSZR+16fC4Ap5rhv3fXO9ndvRNy1STn376nT+my6e86UrQL4aS/S+HNHgIe1BUs+5cOp6Jgw6t0ie7phY0EAiECsRxy9K4e3Dctv9m6+Wma4+vy65MS0zGyrqey6oyV4l827sCOjrD1qcqc9bX6FlMSouVoNfE4ZjINNAbgigTaiLSoDSPcf5I5smkkM2ezzFOMSZwZxNdaNL2LKb97vc8m/ZUkv0sKZyT7oqVL7aJweEivsSHj5l2KR8Z7XrVB1y2eI6GvyTSa/d+CL4dSRzjh8+IRN047YBrdTKD5IkdT0upfoBu14WPUfFmLKxX+iMCslXRWb6kwojhrWNYmZvL65KRAzJ6+eIPDG/W5QUOpYyYT77bLlBQjVo6NmVvl9v3HMECq9CHH0ivKFBGPiKMOx7cJkTax3FuyznOW2WCXB9kTb5Zk9toaiNlSp9L6ll/h2Eyxa6n6sWUgmmM=
|
||||
- secure: vVRg9BKGBwF2MbXQnEccFL+XW0/7RaBmge9k7jbGYScBwkP3XjnQ/Xaj0cvTz2CM2EqXsbpwfvr4Jo+enW/E3MGy5RiEzv5hUe/jIFRR0gfAFbZxSTvg5xiFhTDffqQk0fncO4jXu+wPO5lZ2CMRWzyXz3i1MZhjMcAgoDr1+TRss/EGXLNHxr2RM88tpUW0fV2prIRoyGqhCgnYZtrm7hmr41Ej+itg1MqZLml/Rjkt3KsNgI+z0O5Qn3QSAO8GtPZqeftQxAjevOmxZGcssxY8EJvqbjAujr4y51WncXpEmCRPSY2J9R5+fkgZurqwnJapbQpjwKYemok3ps7EHg2gWkAlmPdQO4LKpbffGkM/o5b+8+HdIuQZugsSWQD9hUSftTAFLcfA1isi7V2lHE1m8bX/vk9zIyDdcPSwIaFe9y+w3PexwFmTjPLq+nia/UY2kARFZMEIFAJby6gkA70DcAJ50QOM86InJu5DSzGbIssgTGAXCn0TPPyGveaurVLw8x61j3yh8LDF46gUHey3rqv6WjpCM9h/vg7X/gq5ve/5Q2KHscUKfs/sA53Mt7qPeqRZY1QCaaRjzqJO/ZraHqWWeKmPKaWhPGR0kYEnkvB+K9GZ+HNSWCltjCO4SJ1xeEl7CRqQxAwdiMATF5SKqyiC+bn5oc35mFgbRF8=
|
||||
- secure: ela1tn4wkJQZ8O4iv+4pIZi5cebxeCStVF1tEUe6qa6WWgJYVXmS2tEv3QQ36NUBFrP58Y6yl10XguPnvj/2BCqcZI4FUBHh3BfiBoUtXxDCVKI5LtlniNiOFGUwfzEeYka8T51zFlcUXSCCaxHkRZbmBsIzeJ39UwTi5fy0qwLv9GgL0czhwm8I8sZ8gyWdGmqpXNFEsb9JP4ZA3mw2qpWkGpGAqQPD9XSCkU3LmX1/ltwsBMAgGYKLLo7vU8d5KV2c8L1Gnxfl6BvfmqUD/dsas/1rnk08rU2nez5ekuQa2tJRkDLOv8bqvrGRLjHSUa3yPuisC6SsDGSU7/3DcozZyYsz7WQ6WI8tYabyjqqeJTF1N8a5T3IbZaZNV1J4JHOO9Cb/y7gIg4edANg6tbe7MzZpdEPRBnw6OkdTdirpNsWQ/jnfpY1hn6mraQZz/q8yaz3W21NjbBJhVnvfh5gWLKQ3YAAziCBhmmrThFhUu0czz+G920MuFo477TBcxvlrE7CaNJ0Q6yYkDehEPOv3jvEs1QVHPwuRrlaLTbBhrlTICKZ58gdX30O8N4i0Xgp/v6qrC03bplnMQc8E/uC61wcVLJixnlZVp8FODpUvPjsxVFkpuNSOIAaiqcERmoiPXx05Epzmr78hjU5rYCx/1MmVoeB4gs9YO+4guD4=
|
||||
- secure: SEqTg6WoGPPpcWzJ03ZfcSBb3nZ2Mdhug0ec2PszuzYO3libCb9usiqi+jils9z6qyXsL6ecz8HYazDGOUepnubhIpI5otLgfn9XiapjMT06Bj//AjbKpH7eu3TJSpJMzoRHZrKIE1y9ZKIBqKwl9Xs7ko+1oa+MLhrLuxXkoi0JqRB5UzkQtJRDoxVNjysnLQn+hsfnm+yuqPHZd2+Loy++q//WHuf9bwJrlkXn2ICYQIX5oQGlxNO6ui+OZklb0YknvyO5GdQeoKaHYru3MMKKCIS6I7AG9wLmPs5Ou3T0Ia0Xx4/7xazs0rH4NCVpIceSYc3v6evR37pp8MsFTC3BzjL1V3slTnmitC1KSNM8ndGRUg1nsCBkJysnR3HpX6SHuCH+UzOuMxEjwiPdSRnzJPEbTHa1HqMfTkTJMbm4zhp7W4/ozX4TtjUB0ql6NoQE2n0Z3aYgR2C78TmzaPQun8EgredWnCID1FedyexaNcw4HyZ2rXlcvG3rBzSwLHH5PePT9skyqy6KtIaL0MlAP556ilgUeyCZfCNdTmzCvPDZuqaeLRezWDdsKnRfTkxIW80QWlmZ6sW0hynJV5JN2Oghk9Tr+QzgV4ZF68FHwoU9YXCTyX4w5iTYq/GjvfTBqB3VSGPOz3PwU7r47tmaYzPj+I44zqktgxyuxDo=
|
||||
- GH_REF: github.com/Redocly/redoc.git
|
||||
- GIT_AUTHOR_EMAIL: redoc-bot@users.noreply.github.com
|
||||
- GIT_AUTHOR_NAME: RedocBot
|
||||
- secure: H2GClDJ7TEQaWgnk8d2fIVDpLwG3rTmN8TalUzrCqXGoG6ylCVmlwzKLgfPPWrVgSA7QTdfNV0ab7c2KyPoZBinHmeGMSuKNLVbhOXRc2VFxTBntBTuyJhfCgQEpUKvJesJUuv5RuBn//wC7VZcVVNc06TZDEe8+aDVYQuCRMXZJ4X3e6nSZ64QX2veyVcr+TjnRsZPkeBVcK9hngvuaxLb/hbJ85CvjiseZRt47PGIcrEpMn9n2GMw1m0fNnPoN+MBTSCnIklTmdjPG7t4GUSLmD6H0lNLdXuehYqmQAHgYrLec1aiFlV57QaDoDZrq2hSf4vDmCB/FVydGhD5JunI67pujoV2OnD1V80eUZhYNWOYsJ2Nfp4NxgXsPUcE6zWLYsLfktMPZADhOXInQRACt1cnx8zMYKLnch1RY/ZqjSg0nPtRjLzQ0lNsw5leixvBdBnMjxYHVyAWVwg8WiJMaLO9vog2Qnxg1NTacHO2CsOmm2rw6stpg7ndp/+nOleRlfUKggjt0Tn3FjwCIXeGup2P2EBa+WW2YMAaoMFofYviR5vRlKBgdKo9fsAruaO1r6nm2EdAjOlniyw92bEfU/qOey1nVp/oK2S82uT5In8KB7vl6rF3ak7WAsT9Q5vZUhsrG+eE4PVyIyWNBhs4A7pSwZGHDR/MYtp0E2ug=
|
||||
- secure: apiavCfCQngL9Een1m7MIXMf3bqO3rY4YY59TMBl/yFKi80CEsHPHhgVUkl6hC+aM5PeBt/vgjh37rHMX31j/pcSZ4Z8SO/4Bwr36iHfhSxSEuAQog8P07qWqH7wYYWGIVmF682stgl0fYF+GN92sx/6edFVzsWVECf2G7imtICKSTbhKGm3Dhn2JwGnhD7eyfgZ33omgiaswumdu0xABoXDfqSZR+16fC4Ap5rhv3fXO9ndvRNy1STn376nT+my6e86UrQL4aS/S+HNHgIe1BUs+5cOp6Jgw6t0ie7phY0EAiECsRxy9K4e3Dctv9m6+Wma4+vy65MS0zGyrqey6oyV4l827sCOjrD1qcqc9bX6FlMSouVoNfE4ZjINNAbgigTaiLSoDSPcf5I5smkkM2ezzFOMSZwZxNdaNL2LKb97vc8m/ZUkv0sKZyT7oqVL7aJweEivsSHj5l2KR8Z7XrVB1y2eI6GvyTSa/d+CL4dSRzjh8+IRN047YBrdTKD5IkdT0upfoBu14WPUfFmLKxX+iMCslXRWb6kwojhrWNYmZvL65KRAzJ6+eIPDG/W5QUOpYyYT77bLlBQjVo6NmVvl9v3HMECq9CHH0ivKFBGPiKMOx7cJkTax3FuyznOW2WCXB9kTb5Zk9toaiNlSp9L6ll/h2Eyxa6n6sWUgmmM=
|
||||
- secure: vVRg9BKGBwF2MbXQnEccFL+XW0/7RaBmge9k7jbGYScBwkP3XjnQ/Xaj0cvTz2CM2EqXsbpwfvr4Jo+enW/E3MGy5RiEzv5hUe/jIFRR0gfAFbZxSTvg5xiFhTDffqQk0fncO4jXu+wPO5lZ2CMRWzyXz3i1MZhjMcAgoDr1+TRss/EGXLNHxr2RM88tpUW0fV2prIRoyGqhCgnYZtrm7hmr41Ej+itg1MqZLml/Rjkt3KsNgI+z0O5Qn3QSAO8GtPZqeftQxAjevOmxZGcssxY8EJvqbjAujr4y51WncXpEmCRPSY2J9R5+fkgZurqwnJapbQpjwKYemok3ps7EHg2gWkAlmPdQO4LKpbffGkM/o5b+8+HdIuQZugsSWQD9hUSftTAFLcfA1isi7V2lHE1m8bX/vk9zIyDdcPSwIaFe9y+w3PexwFmTjPLq+nia/UY2kARFZMEIFAJby6gkA70DcAJ50QOM86InJu5DSzGbIssgTGAXCn0TPPyGveaurVLw8x61j3yh8LDF46gUHey3rqv6WjpCM9h/vg7X/gq5ve/5Q2KHscUKfs/sA53Mt7qPeqRZY1QCaaRjzqJO/ZraHqWWeKmPKaWhPGR0kYEnkvB+K9GZ+HNSWCltjCO4SJ1xeEl7CRqQxAwdiMATF5SKqyiC+bn5oc35mFgbRF8=
|
||||
- secure: ela1tn4wkJQZ8O4iv+4pIZi5cebxeCStVF1tEUe6qa6WWgJYVXmS2tEv3QQ36NUBFrP58Y6yl10XguPnvj/2BCqcZI4FUBHh3BfiBoUtXxDCVKI5LtlniNiOFGUwfzEeYka8T51zFlcUXSCCaxHkRZbmBsIzeJ39UwTi5fy0qwLv9GgL0czhwm8I8sZ8gyWdGmqpXNFEsb9JP4ZA3mw2qpWkGpGAqQPD9XSCkU3LmX1/ltwsBMAgGYKLLo7vU8d5KV2c8L1Gnxfl6BvfmqUD/dsas/1rnk08rU2nez5ekuQa2tJRkDLOv8bqvrGRLjHSUa3yPuisC6SsDGSU7/3DcozZyYsz7WQ6WI8tYabyjqqeJTF1N8a5T3IbZaZNV1J4JHOO9Cb/y7gIg4edANg6tbe7MzZpdEPRBnw6OkdTdirpNsWQ/jnfpY1hn6mraQZz/q8yaz3W21NjbBJhVnvfh5gWLKQ3YAAziCBhmmrThFhUu0czz+G920MuFo477TBcxvlrE7CaNJ0Q6yYkDehEPOv3jvEs1QVHPwuRrlaLTbBhrlTICKZ58gdX30O8N4i0Xgp/v6qrC03bplnMQc8E/uC61wcVLJixnlZVp8FODpUvPjsxVFkpuNSOIAaiqcERmoiPXx05Epzmr78hjU5rYCx/1MmVoeB4gs9YO+4guD4=
|
||||
- secure: Pc86j2/rgCPAEWcjzPbbVFkL2SwNt4CpeXP69zedMi9RomQblMJa9R0wbAT6H5VCnPky2cpmxkzjFWOc91N9crzceg6aOoWkPr6pTTnTv+EL70i6+XSrAFpkgRjszprxnU1Bz+GcYEjP/zR8479fx8ooSl7MwHOaP7XiQyaBQAbY1CPlmpT+b4Ut7Fm5QnD90/NgPjbKkngl0kVUfNFdFOSfJ3QWLyFCUUSQ4DlxccJOTIaOH/n8u9Nz4NTuuHE3XeRuEsuj2SJutJnFBUYwsvugrdPvKWiubkewJfylp6EwABzByENsg6XxW9SIq80lMc3Oi7ld9L2lAgpj+8/42olnbMzH0F0rw/p1ccPAdVwQVV6YFaqCzivK5A5aX5LmGKwJ6SR9k1PgcWP6sKKMIsIEObbyM88Tke3QkreEz+cLg/3jjko7Vpb0tbqh8BtbpWV+exL4rX3r2C5Mb1Es1W597hN5LSczWYFgw0ZETpfbVZg6Ri1iZks0wpsT/E+c0q2scUaBVrdTZseHxUPB7mPDlXL1l9/i4sOxPyBHZtJRAzeTT/fOXfj4vuD+ihspXzoRRLaQbizlb8FpyPA47XdmBDpXi3OBiaIFLwvybEn7qM7rqvWxdz6vvCZv0t/AN3t3Qvh2vHKCshHecaa8NoJQHWrdFMHeecYHyeoujZ8=
|
||||
addons:
|
||||
chrome: stable
|
||||
apt:
|
||||
packages:
|
||||
- libgconf-2-4 # for cypress
|
||||
- libgconf-2-4
|
||||
before_script: npm run bundle
|
||||
script: npm test && ([ "${TRAVIS_PULL_REQUEST}" = "false" ] && npm run e2e-ci || npm
|
||||
run e2e)
|
||||
|
|
118
CHANGELOG.md
118
CHANGELOG.md
|
@ -1,3 +1,99 @@
|
|||
# [2.0.0-rc.23](https://github.com/Redocly/redoc/compare/v2.0.0-rc.22...v2.0.0-rc.23) (2020-02-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix broken sticky sidebar in Chrome 80 ([1a2a7dd](https://github.com/Redocly/redoc/commit/1a2a7dd8331cedd6ced4c18accf0b417549b3ff3)), closes [#1167](https://github.com/Redocly/redoc/issues/1167)
|
||||
|
||||
|
||||
|
||||
# [2.0.0-rc.22](https://github.com/Redocly/redoc/compare/v2.0.0-rc.21...v2.0.0-rc.22) (2020-01-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not process oneOf if inherited from parent with discriminator ([5248415](https://github.com/Redocly/redoc/commit/52484157912d908daea8255d0b7d684b33258d7a))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add HTTP syntax highlighting ([#1157](https://github.com/Redocly/redoc/issues/1157)) ([27a4af7](https://github.com/Redocly/redoc/commit/27a4af707686d56280753473b4294ee4af096534))
|
||||
|
||||
|
||||
|
||||
# [2.0.0-rc.21](https://github.com/Redocly/redoc/compare/v2.0.0-rc.20...v2.0.0-rc.21) (2020-01-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* empty servers behaviour per OAS spec ([ed1db0c](https://github.com/Redocly/redoc/commit/ed1db0c9027087ae0ae923e390e3e1d638a647ae)), closes [#1151](https://github.com/Redocly/redoc/issues/1151)
|
||||
* fix duplicated content in tags when using md headings ([a260c84](https://github.com/Redocly/redoc/commit/a260c8414c34a259a70a20ebcd20ecbb06c3d250)), closes [#1150](https://github.com/Redocly/redoc/issues/1150) [#1152](https://github.com/Redocly/redoc/issues/1152)
|
||||
* use mobile menu background color value from theme ([#1144](https://github.com/Redocly/redoc/issues/1144)) ([41a9b3c](https://github.com/Redocly/redoc/commit/41a9b3c18228d236d182d3c15c9abc35ae72a0d5))
|
||||
|
||||
|
||||
|
||||
# [2.0.0-rc.20](https://github.com/Redocly/redoc/compare/v2.0.0-rc.19...v2.0.0-rc.20) (2019-12-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* fix missing parameters ([942d782](https://github.com/Redocly/redoc/commit/942d782b5a8d08767a7538741b75587cf1e67f44)), closes [#1142](https://github.com/Redocly/redoc/issues/1142)
|
||||
|
||||
|
||||
|
||||
# [2.0.0-rc.19](https://github.com/Redocly/redoc/compare/v2.0.0-rc.18...v2.0.0-rc.19) (2019-12-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* change the title of "Security Scheme Type" to match "HTTP Authorization Scheme" ([#1126](https://github.com/Redocly/redoc/issues/1126)) ([289c8e6](https://github.com/Redocly/redoc/commit/289c8e6ae1ff00371f86d3f2646607c64bc30050))
|
||||
* do not URI-encode parameter values for better readability ([6aeb0bf](https://github.com/Redocly/redoc/commit/6aeb0bf68df3f03f2ca1317f8b5787545bd363f1)), closes [#1138](https://github.com/Redocly/redoc/issues/1138)
|
||||
* fix sortByRequired (stabilise sort) ([#1136](https://github.com/Redocly/redoc/issues/1136)) ([d92434d](https://github.com/Redocly/redoc/commit/d92434d11b08e8b0f6be5453ec69aa1d0e0df79f)), closes [#1104](https://github.com/Redocly/redoc/issues/1104) [#1121](https://github.com/Redocly/redoc/issues/1121) [#1061](https://github.com/Redocly/redoc/issues/1061)
|
||||
* h2 padding on mobile ([7ed1a7e](https://github.com/Redocly/redoc/commit/7ed1a7ef0e7978a0dfb40afcc72c3362466f9624)), closes [#1118](https://github.com/Redocly/redoc/issues/1118)
|
||||
* python comment stripped in headings ([4a25aae](https://github.com/Redocly/redoc/commit/4a25aaef69fad814836392ea7e41eb32c182a261)), closes [#1116](https://github.com/Redocly/redoc/issues/1116)
|
||||
* remove hardcoded fontFamily for oneOf labels ([094ce91](https://github.com/Redocly/redoc/commit/094ce914e3f9cfe567b39db4ea88208014d8b686)), closes [#1120](https://github.com/Redocly/redoc/issues/1120)
|
||||
* search-box use theme ([1bf490c](https://github.com/Redocly/redoc/commit/1bf490c05b343d262f8819bf1ddc433e070be1b9))
|
||||
* support discriminator mapping 1-n ([6e390f9](https://github.com/Redocly/redoc/commit/6e390f9c7909da0b5d1d6fc571ab4ad92e715d6e)), closes [#1111](https://github.com/Redocly/redoc/issues/1111)
|
||||
* wrap json examples in code tag ([#1064](https://github.com/Redocly/redoc/issues/1064)) ([dc5430e](https://github.com/Redocly/redoc/commit/dc5430e53def780a81612d269cc3aea3f8785eea))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* display `multipleOf` constrains ([#1065](https://github.com/Redocly/redoc/issues/1065)) ([3e90133](https://github.com/Redocly/redoc/commit/3e901336643b988ae45ae86c485005b8865e6e04))
|
||||
* enable menuToggle by default ([5d81abe](https://github.com/Redocly/redoc/commit/5d81abeb28c1e4f2826e41424c10163834c37e45))
|
||||
* new option hideSchemaTitles ([11cc4c4](https://github.com/Redocly/redoc/commit/11cc4c4c3e04a7e5bf3a9ebba20d10fa882a49e5))
|
||||
* new option payloadSampleIdx ([eaaa99d](https://github.com/Redocly/redoc/commit/eaaa99d68e2392273e8d9c0173db3b546e035d5f))
|
||||
* **cli:** Fallback on the spec's title before falling back on… ([#1073](https://github.com/Redocly/redoc/issues/1073)) ([e01eea4](https://github.com/Redocly/redoc/commit/e01eea445c93d74b66533c860d76bb3aff4d6df2))
|
||||
|
||||
|
||||
|
||||
# [2.0.0-rc.18](https://github.com/Redocly/redoc/compare/v2.0.0-rc.17...v2.0.0-rc.18) (2019-10-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* add oneOf buttons vertical space when wrapped to new line ([cd9fd61](https://github.com/Redocly/redoc/commit/cd9fd61))
|
||||
* improve mime-type dropdown font ([ce885f8](https://github.com/Redocly/redoc/commit/ce885f8))
|
||||
|
||||
|
||||
|
||||
# [2.0.0-rc.17](https://github.com/Redocly/redoc/compare/v2.0.0-rc.16...v2.0.0-rc.17) (2019-10-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* active menu item scroll into view ([0a01e9a](https://github.com/Redocly/redoc/commit/0a01e9a))
|
||||
* changed several components style font-family to monospace ([#1063](https://github.com/Redocly/redoc/issues/1063)) ([0c20e64](https://github.com/Redocly/redoc/commit/0c20e64)), closes [#909](https://github.com/Redocly/redoc/issues/909)
|
||||
* no quotes for default values in header fields. ([#1059](https://github.com/Redocly/redoc/issues/1059)) ([b5af71d](https://github.com/Redocly/redoc/commit/b5af71d))
|
||||
* types over-pluralization ([#1057](https://github.com/Redocly/redoc/issues/1057)) ([4494f80](https://github.com/Redocly/redoc/commit/4494f80)), closes [#1053](https://github.com/Redocly/redoc/issues/1053)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* added support for file paths as --options cli argument ([#1049](https://github.com/Redocly/redoc/issues/1049)) ([4adb927](https://github.com/Redocly/redoc/commit/4adb927))
|
||||
|
||||
|
||||
|
||||
# [2.0.0-rc.16](https://github.com/Redocly/redoc/compare/v2.0.0-rc.15...v2.0.0-rc.16) (2019-09-30)
|
||||
|
||||
|
||||
|
@ -17,7 +113,7 @@
|
|||
* do not crash on empty scopes ([e787d9e](https://github.com/Redocly/redoc/commit/e787d9e)), closes [#1044](https://github.com/Redocly/redoc/issues/1044)
|
||||
* false-positive recursive detection with allOf at the same level ([faa74d6](https://github.com/Redocly/redoc/commit/faa74d6))
|
||||
* fix scrollYOffset when SSR ([21258a5](https://github.com/Redocly/redoc/commit/21258a5))
|
||||
* left menu item before group is not highligted ([67e2a8f](https://github.com/Redocly/redoc/commit/67e2a8f)), closes [#1033](https://github.com/Redocly/redoc/issues/1033)
|
||||
* left menu item before group is not highlighted ([67e2a8f](https://github.com/Redocly/redoc/commit/67e2a8f)), closes [#1033](https://github.com/Redocly/redoc/issues/1033)
|
||||
* remove excessive whitespace between md sections on small screens ([e318fb3](https://github.com/Redocly/redoc/commit/e318fb3)), closes [#874](https://github.com/Redocly/redoc/issues/874)
|
||||
* use url-template dependency ([#1008](https://github.com/Redocly/redoc/issues/1008)) ([32a464a](https://github.com/Redocly/redoc/commit/32a464a)), closes [#1007](https://github.com/Redocly/redoc/issues/1007)
|
||||
|
||||
|
@ -70,7 +166,7 @@
|
|||
|
||||
* do not add extra slashes to pattern ([70d1ee9](https://github.com/Redocly/redoc/commit/70d1ee9)), closes [#983](https://github.com/Redocly/redoc/issues/983)
|
||||
* dropdown fixes related to object description ([0504ad4](https://github.com/Redocly/redoc/commit/0504ad4))
|
||||
* incorrect serialization of parameter sample with hypen ([f7dd658](https://github.com/Redocly/redoc/commit/f7dd658))
|
||||
* incorrect serialization of parameter sample with hyphen ([f7dd658](https://github.com/Redocly/redoc/commit/f7dd658))
|
||||
* redoc-cli: Add missing content type header on compressed responses of `/` path
|
||||
|
||||
|
||||
|
@ -144,7 +240,7 @@
|
|||
|
||||
### Bug Fixes
|
||||
|
||||
* broken schema talbes with long enums ([3a74b74](https://github.com/Rebilly/ReDoc/commit/3a74b74))
|
||||
* broken schema tables with long enums ([3a74b74](https://github.com/Rebilly/ReDoc/commit/3a74b74))
|
||||
* deep linking sometimes not working when sent over messengers ([2491d97](https://github.com/Rebilly/ReDoc/commit/2491d97))
|
||||
|
||||
|
||||
|
@ -162,7 +258,7 @@
|
|||
* IE11 add missing fetch and URL polyfills ([d2ce1bd](https://github.com/Rebilly/ReDoc/commit/d2ce1bd)), closes [#875](https://github.com/Rebilly/ReDoc/issues/875)
|
||||
* ignore empty x-tagGroups array ([#869](https://github.com/Rebilly/ReDoc/issues/869)) ([4366a0d](https://github.com/Rebilly/ReDoc/commit/4366a0d))
|
||||
* incorrect detected schema title for deeply inherited schemas ([7d7b4e3](https://github.com/Rebilly/ReDoc/commit/7d7b4e3))
|
||||
* pluralize arrray of types ([fdcac30](https://github.com/Rebilly/ReDoc/commit/fdcac30))
|
||||
* pluralize array of types ([fdcac30](https://github.com/Rebilly/ReDoc/commit/fdcac30))
|
||||
* remove huge space after Authentication section ([548fae3](https://github.com/Rebilly/ReDoc/commit/548fae3)), closes [#872](https://github.com/Rebilly/ReDoc/issues/872)
|
||||
* remove query string from server URL ([#895](https://github.com/Rebilly/ReDoc/issues/895)) ([64453ff](https://github.com/Rebilly/ReDoc/commit/64453ff))
|
||||
* remove tabs top margin ([5c187f3](https://github.com/Rebilly/ReDoc/commit/5c187f3))
|
||||
|
@ -246,7 +342,7 @@
|
|||
* improve scrolling performance in Chrome with non-wrapped json examples ([a69c402](https://github.com/Rebilly/ReDoc/commit/a69c402))
|
||||
* nested oneOf button spacing ([3673720](https://github.com/Rebilly/ReDoc/commit/3673720)), closes [#719](https://github.com/Rebilly/ReDoc/issues/719)
|
||||
* onLoaded callback not run on spec error ([e77df0c](https://github.com/Rebilly/ReDoc/commit/e77df0c)), closes [#690](https://github.com/Rebilly/ReDoc/issues/690)
|
||||
* theme improvments by [@stasiukanya](https://github.com/stasiukanya) ([e2d0cd5](https://github.com/Rebilly/ReDoc/commit/e2d0cd5))
|
||||
* theme improvements by [@stasiukanya](https://github.com/stasiukanya) ([e2d0cd5](https://github.com/Rebilly/ReDoc/commit/e2d0cd5))
|
||||
* **cli:** old peer dependency issue with styled-components ([#699](https://github.com/Rebilly/ReDoc/issues/699)) ([9e2853c](https://github.com/Rebilly/ReDoc/commit/9e2853c))
|
||||
|
||||
|
||||
|
@ -318,7 +414,7 @@
|
|||
|
||||
### Bug Fixes
|
||||
|
||||
* addd indent to array schema internals ([865f3ce](https://github.com/Rebilly/ReDoc/commit/865f3ce))
|
||||
* add indent to array schema internals ([865f3ce](https://github.com/Rebilly/ReDoc/commit/865f3ce))
|
||||
* fix oneOf/anyOf titles ([39b930d](https://github.com/Rebilly/ReDoc/commit/39b930d)), closes [#618](https://github.com/Rebilly/ReDoc/issues/618) [#621](https://github.com/Rebilly/ReDoc/issues/621)
|
||||
|
||||
|
||||
|
@ -364,7 +460,7 @@
|
|||
### Bug Fixes
|
||||
|
||||
* add some spacing between operation description and parameters ([597688e](https://github.com/Rebilly/ReDoc/commit/597688e))
|
||||
* description is not rendered if doesn't containt markdown headings ([90ed717](https://github.com/Rebilly/ReDoc/commit/90ed717)), closes [#591](https://github.com/Rebilly/ReDoc/issues/591)
|
||||
* description is not rendered if doesn't contain markdown headings ([90ed717](https://github.com/Rebilly/ReDoc/commit/90ed717)), closes [#591](https://github.com/Rebilly/ReDoc/issues/591)
|
||||
* download button downloads index.html instead of spec with CLI ([334f904](https://github.com/Rebilly/ReDoc/commit/334f904)), closes [#594](https://github.com/Rebilly/ReDoc/issues/594)
|
||||
* fix Authentication section is not rendered ([2ecc8bc](https://github.com/Rebilly/ReDoc/commit/2ecc8bc)), closes [#590](https://github.com/Rebilly/ReDoc/issues/590)
|
||||
* fix linebreaks in multiparagraph field descriptions ([8fb9cd6](https://github.com/Rebilly/ReDoc/commit/8fb9cd6))
|
||||
|
@ -675,7 +771,7 @@
|
|||
|
||||
### Bug Fixes
|
||||
|
||||
* Path parameters are not correctly overriden ([c406dc5](https://github.com/Rebilly/ReDoc/commit/c406dc5)), closes [#400](https://github.com/Rebilly/ReDoc/issues/400)
|
||||
* Path parameters are not correctly overridden ([c406dc5](https://github.com/Rebilly/ReDoc/commit/c406dc5)), closes [#400](https://github.com/Rebilly/ReDoc/issues/400)
|
||||
* Use parentNode instead of parentElement to fix IE11 crash ([e8adb60](https://github.com/Rebilly/ReDoc/commit/e8adb60)), closes [#406](https://github.com/Rebilly/ReDoc/issues/406)
|
||||
|
||||
|
||||
|
@ -837,7 +933,7 @@
|
|||
* do not ignore path level parameters ([14f8408](https://github.com/Rebilly/Redoc/commit/14f8408))
|
||||
* improve rendering of types ([17da7b7](https://github.com/Rebilly/Redoc/commit/17da7b7))
|
||||
* move title propagation to the correct place ([0b0bc99](https://github.com/Rebilly/Redoc/commit/0b0bc99))
|
||||
* owerwrite text-align to left ([bfee3ed](https://github.com/Rebilly/Redoc/commit/bfee3ed))
|
||||
* overwrite text-align to left ([bfee3ed](https://github.com/Rebilly/Redoc/commit/bfee3ed))
|
||||
|
||||
|
||||
### Features
|
||||
|
@ -899,7 +995,7 @@ Complete rewrite also means that this rewrite may introduce issues, but they sho
|
|||
|
||||
### Deprecations
|
||||
|
||||
- Fonts are not loaded by ReDoc so you should load them. Default fonts can be loaded as bellow:
|
||||
- Fonts are not loaded by ReDoc so you should load them. Default fonts can be loaded as below:
|
||||
|
||||
```html
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||
|
@ -1268,7 +1364,7 @@ closes [#321](https://github.com/Rebilly/ReDoc/issues/321)
|
|||
### Bug fixes
|
||||
* Update webpack to the latest beta ([#143](https://github.com/Rebilly/ReDoc/issues/143))
|
||||
* Fix read-only fields appear in request samples ([#142](https://github.com/Rebilly/ReDoc/issues/142))
|
||||
* A few more minor UI improvemnts
|
||||
* A few more minor UI improvements
|
||||
|
||||
### Features/Improvements
|
||||
* Major performance optimization with new option `lazy-rendering`
|
||||
|
|
48
README.md
48
README.md
|
@ -214,7 +214,7 @@ ReDoc makes use of the following [vendor extensions](https://swagger.io/specific
|
|||
* [`x-traitTag`](docs/redoc-vendor-extensions.md#x-traitTag) - useful for handling out common things like Pagination, Rate-Limits, etc
|
||||
* [`x-code-samples`](docs/redoc-vendor-extensions.md#x-code-samples) - specify operation code samples
|
||||
* [`x-examples`](docs/redoc-vendor-extensions.md#x-examples) - specify JSON example for requests
|
||||
* [`x-nullable`](docs/redoc-vendor-extensions.md#nullable) - mark schema param as a nullable
|
||||
* [`x-nullable`](docs/redoc-vendor-extensions.md#x-nullable) - mark schema param as a nullable
|
||||
* [`x-displayName`](docs/redoc-vendor-extensions.md#x-displayname) - specify human-friendly names for the menu categories
|
||||
* [`x-tagGroups`](docs/redoc-vendor-extensions.md#x-tagGroups) - group tags by categories in the side menu
|
||||
* [`x-servers`](docs/redoc-vendor-extensions.md#x-servers) - ability to specify different servers for API (backported from OpenAPI 3.0)
|
||||
|
@ -224,31 +224,33 @@ ReDoc makes use of the following [vendor extensions](https://swagger.io/specific
|
|||
### `<redoc>` options object
|
||||
You can use all of the following options with standalone version on <redoc> tag by kebab-casing them, e.g. `scrollYOffset` becomes `scroll-y-offset` and `expandResponses` becomes `expand-responses`.
|
||||
|
||||
* `untrustedSpec` - if set, the spec is considered untrusted and all HTML/markdown is sanitized to prevent XSS. **Disabled by default** for performance reasons. **Enable this option if you work with untrusted user data!**
|
||||
* `disableSearch` - disable search indexing and search box.
|
||||
* `expandDefaultServerVariables` - enable expanding default server variables, default `false`.
|
||||
* `expandResponses` - specify which responses to expand by default by response codes. Values should be passed as comma-separated list without spaces e.g. `expandResponses="200,201"`. Special value `"all"` expands all responses by default. Be careful: this option can slow-down documentation rendering time.
|
||||
* `enableConsole` - you should set true if you want to use the built-in console, default `false`
|
||||
* `hideDownloadButton` - do not show "Download" spec button. **THIS DOESN'T MAKE YOUR SPEC PRIVATE**, it just hides the button.
|
||||
* `hideHostname` - if set, the protocol and hostname is not shown in the operation definition.
|
||||
* `hideLoading` - do not show loading animation. Useful for small docs.
|
||||
* `hideSingleRequestSampleTab` - do not show the request sample tab for requests with only one sample.
|
||||
* `jsonSampleExpandLevel` - set the default expand level for JSON payload samples (responses and request body). Special value 'all' expands all levels. The default value is `2`.
|
||||
* `lazyRendering` - _Not implemented yet_ ~~if set, enables lazy rendering mode in ReDoc. This mode is useful for APIs with big number of operations (e.g. > 50). In this mode ReDoc shows initial screen ASAP and then renders the rest operations asynchronously while showing progress bar on the top. Check out the [demo](\\redocly.github.io/redoc) for the example.~~
|
||||
* `menuToggle` - if true clicking second time on expanded menu item will collapse it, default `false`.
|
||||
* `nativeScrollbars` - use native scrollbar for sidemenu instead of perfect-scroll (scrolling performance optimization for big specs).
|
||||
* `noAutoAuth` - do not inject Authentication section automatically.
|
||||
* `onlyRequiredInSamples` - shows only required fields in request samples.
|
||||
* `pathInMiddlePanel` - show path link and HTTP verb in the middle panel instead of the right one.
|
||||
* `requiredPropsFirst` - show required properties first ordered in the same order as in `required` array.
|
||||
* `scrollYOffset` - If set, specifies a vertical scroll-offset. This is often useful when there are fixed positioned elements at the top of the page, such as navbars, headers etc;
|
||||
`scrollYOffset` can be specified in various ways:
|
||||
* **number**: A fixed number of pixels to be used as offset;
|
||||
* **selector**: selector of the element to be used for specifying the offset. The distance from the top of the page to the element's bottom will be used as offset;
|
||||
* **function**: A getter function. Must return a number representing the offset (in pixels);
|
||||
* **number**: A fixed number of pixels to be used as offset.
|
||||
* **selector**: selector of the element to be used for specifying the offset. The distance from the top of the page to the element's bottom will be used as offset.
|
||||
* **function**: A getter function. Must return a number representing the offset (in pixels).
|
||||
* `showExtensions` - show vendor extensions ("x-" fields). Extensions used by ReDoc are ignored. Can be boolean or an array of `string` with names of extensions to display.
|
||||
* `sortPropsAlphabetically` - sort properties alphabetically.
|
||||
* `suppressWarnings` - if set, warnings are not rendered at the top of documentation (they still are logged to the console).
|
||||
* `lazyRendering` - _Not implemented yet_ ~~if set, enables lazy rendering mode in ReDoc. This mode is useful for APIs with big number of operations (e.g. > 50). In this mode ReDoc shows initial screen ASAP and then renders the rest operations asynchronously while showing progress bar on the top. Check out the [demo](\\redocly.github.io/redoc) for the example.~~
|
||||
* `hideHostname` - if set, the protocol and hostname is not shown in the operation definition.
|
||||
* `expandResponses` - specify which responses to expand by default by response codes. Values should be passed as comma-separated list without spaces e.g. `expandResponses="200,201"`. Special value `"all"` expands all responses by default. Be careful: this option can slow-down documentation rendering time.
|
||||
* `requiredPropsFirst` - show required properties first ordered in the same order as in `required` array.
|
||||
* `sortPropsAlphabetically` - sort properties alphabetically
|
||||
* `showExtensions` - show vendor extensions ("x-" fields). Extensions used by ReDoc are ignored. Can be boolean or an array of `string` with names of extensions to display
|
||||
* `noAutoAuth` - do not inject Authentication section automatically
|
||||
* `pathInMiddlePanel` - show path link and HTTP verb in the middle panel instead of the right one
|
||||
* `hideLoading` - do not show loading animation. Useful for small docs
|
||||
* `nativeScrollbars` - use native scrollbar for sidemenu instead of perfect-scroll (scrolling performance optimization for big specs)
|
||||
* `hideDownloadButton` - do not show "Download" spec button. **THIS DOESN'T MAKE YOUR SPEC PRIVATE**, it just hides the button.
|
||||
* `disableSearch` - disable search indexing and search box
|
||||
* `onlyRequiredInSamples` - shows only required fields in request samples.
|
||||
* `jsonSampleExpandLevel` - set the default expand level for JSON payload samples (responses and request body). Special value 'all' expands all levels. The default value is `2`.
|
||||
* `menuToggle` - if true clicking second time on expanded menu item will collapse it, default `false`
|
||||
* `enableConsole` - you should set true if you want to use the built-in console, default `false`
|
||||
* `expandDefaultServerVariables` - enable expanding default server variables, default `false`
|
||||
* `theme` - ReDoc theme. Not documented yet. For details check source code: [theme.ts](https://github.com/Redocly/redoc/blob/master/src/theme.ts)
|
||||
* `payloadSampleIdx` - if set, payload sample will be inserted at this index or last. Indexes start from 0.
|
||||
* `theme` - ReDoc theme. Not documented yet. For details check source code: [theme.ts](https://github.com/Redocly/redoc/blob/master/src/theme.ts).
|
||||
* `untrustedSpec` - if set, the spec is considered untrusted and all HTML/markdown is sanitized to prevent XSS. **Disabled by default** for performance reasons. **Enable this option if you work with untrusted user data!**
|
||||
|
||||
## Advanced usage of standalone version
|
||||
Instead of adding `spec-url` attribute to the `<redoc>` element you can initialize ReDoc via globally exposed `Redoc` object:
|
||||
|
|
|
@ -32,7 +32,7 @@ const configDir = './benchmark/revisions/config.js';
|
|||
console.log(`Writing config "${configDir}"`);
|
||||
fs.writeFileSync(configDir, configFile);
|
||||
|
||||
console.log('Starging benchmark server');
|
||||
console.log('Starting benchmark server');
|
||||
const proc = spawn('npm', ['run', 'start:benchmark']);
|
||||
|
||||
proc.stdout.on('data', data => {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# To run:
|
||||
# To display the command line options:
|
||||
# $ docker run --rm -it redoc-cli --help
|
||||
# .. will display the comand line help
|
||||
# .. will display the command line help
|
||||
#
|
||||
# To turn `swagger.yml` file in the current directory, to html documentation 'redoc-static.html'
|
||||
# $ docker run --rm -it -v $PWD:/data redoc-cli bundle swagger.yml
|
||||
|
|
40
cli/index.ts
40
cli/index.ts
|
@ -14,7 +14,14 @@ import * as zlib from 'zlib';
|
|||
import { createStore, loadAndBundleSpec, Redoc } from 'redoc';
|
||||
|
||||
import { watch } from 'chokidar';
|
||||
import { createReadStream, existsSync, readFileSync, ReadStream, writeFileSync } from 'fs';
|
||||
import {
|
||||
createReadStream,
|
||||
existsSync,
|
||||
lstatSync,
|
||||
readFileSync,
|
||||
ReadStream,
|
||||
writeFileSync,
|
||||
} from 'fs';
|
||||
import * as mkdirp from 'mkdirp';
|
||||
|
||||
import * as YargsParser from 'yargs';
|
||||
|
@ -99,7 +106,6 @@ YargsParser.command(
|
|||
yargs.options('title', {
|
||||
describe: 'Page Title',
|
||||
type: 'string',
|
||||
default: 'ReDoc documentation',
|
||||
});
|
||||
|
||||
yargs.options('disableGoogleFont', {
|
||||
|
@ -197,7 +203,7 @@ async function serve(port: number, pathToSpec: string, options: Options = {}) {
|
|||
const watcher = watch(pathToSpecDirectory, watchOptions);
|
||||
const log = console.log.bind(console);
|
||||
|
||||
const handlePath = async path => {
|
||||
const handlePath = async _path => {
|
||||
try {
|
||||
spec = await loadAndBundleSpec(pathToSpec);
|
||||
pageHTML = await getPageHTML(spec, pathToSpec, options);
|
||||
|
@ -291,7 +297,7 @@ async function getPageHTML(
|
|||
? '<script src="https://unpkg.com/redoc@next/bundles/redoc.standalone.js"></script>'
|
||||
: `<script>${redocStandaloneSrc}</script>`) + css
|
||||
: '<script src="redoc.standalone.js"></script>',
|
||||
title,
|
||||
title: title || spec.info.title || 'ReDoc documentation',
|
||||
disableGoogleFont,
|
||||
templateOptions,
|
||||
});
|
||||
|
@ -357,13 +363,23 @@ function handleError(error: Error) {
|
|||
}
|
||||
|
||||
function getObjectOrJSON(options) {
|
||||
try {
|
||||
return options && typeof options === 'string'
|
||||
? JSON.parse(options) : options
|
||||
? options
|
||||
: {};
|
||||
} catch (e) {
|
||||
console.log(`Encountered error:\n${options}\nis not a valid JSON.`);
|
||||
handleError(e);
|
||||
switch (typeof options) {
|
||||
case 'object':
|
||||
return options;
|
||||
case 'string':
|
||||
try {
|
||||
if (existsSync(options) && lstatSync(options).isFile()) {
|
||||
return JSON.parse(readFileSync(options, 'utf-8'));
|
||||
} else {
|
||||
return JSON.parse(options);
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(
|
||||
`Encountered error:\n\n${options}\n\nis neither a file with a valid JSON object neither a stringified JSON object.`,
|
||||
);
|
||||
handleError(e);
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "redoc-cli",
|
||||
"version": "0.9.2",
|
||||
"version": "0.9.6",
|
||||
"description": "ReDoc's Command Line Interface",
|
||||
"main": "index.js",
|
||||
"bin": "index.js",
|
||||
|
@ -19,7 +19,7 @@
|
|||
"node-libs-browser": "^2.2.1",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"redoc": "2.0.0-rc.16",
|
||||
"redoc": "2.0.0-rc.23",
|
||||
"styled-components": "^4.3.2",
|
||||
"tslib": "^1.10.0",
|
||||
"yargs": "^13.3.0"
|
||||
|
|
212
cli/yarn.lock
212
cli/yarn.lock
|
@ -78,6 +78,13 @@
|
|||
dependencies:
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/runtime@^7.6.3":
|
||||
version "7.7.6"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f"
|
||||
integrity sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw==
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.2"
|
||||
|
||||
"@babel/template@^7.1.0":
|
||||
version "7.4.4"
|
||||
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.4.tgz#f4b88d1225689a08f5bc3a17483545be9e4ed237"
|
||||
|
@ -264,11 +271,6 @@ better-ajv-errors@^0.6.1:
|
|||
jsonpointer "^4.0.1"
|
||||
leven "^2.1.0"
|
||||
|
||||
big.js@^5.2.2:
|
||||
version "5.2.2"
|
||||
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
|
||||
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
|
||||
|
||||
binary-extensions@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c"
|
||||
|
@ -475,10 +477,10 @@ color-name@1.1.3:
|
|||
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
|
||||
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
|
||||
|
||||
commander@~2.20.0:
|
||||
version "2.20.0"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422"
|
||||
integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==
|
||||
commander@~2.20.3:
|
||||
version "2.20.3"
|
||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||
|
||||
console-browserify@^1.1.0:
|
||||
version "1.1.0"
|
||||
|
@ -619,20 +621,15 @@ diffie-hellman@^5.0.0:
|
|||
miller-rabin "^4.0.0"
|
||||
randombytes "^2.0.0"
|
||||
|
||||
dom-walk@^0.1.0:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
|
||||
integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=
|
||||
|
||||
domain-browser@^1.1.1:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda"
|
||||
integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==
|
||||
|
||||
dompurify@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.0.3.tgz#5cc4965a487d54aedba6ba9634b137cfbd7eb50d"
|
||||
integrity sha512-q006uOkD2JGSJgF0qBt7rVhUvUPBWCxpGayALmHvXx2iNlMfNVz7PDGeXEUjNGgIDjADz59VZCv6UE3U8XRWVw==
|
||||
dompurify@^2.0.7:
|
||||
version "2.0.7"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.0.7.tgz#f8266ad38fe1602fb5b3222f31eedbf5c16c4fd5"
|
||||
integrity sha512-S3O0lk6rFJtO01ZTzMollCOGg+WAtCwS3U5E2WSDY/x/sy7q70RjEC4Dmrih5/UqzLLB9XoKJ8KqwBxaNvBu4A==
|
||||
|
||||
elliptic@^6.0.0:
|
||||
version "6.5.0"
|
||||
|
@ -652,11 +649,6 @@ emoji-regex@^7.0.1:
|
|||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
||||
|
||||
emojis-list@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
|
||||
integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k=
|
||||
|
||||
end-of-stream@^1.1.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
|
||||
|
@ -725,11 +717,6 @@ fast-json-stable-stringify@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
|
||||
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
|
||||
|
||||
fast-levenshtein@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
|
||||
integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
|
@ -783,14 +770,6 @@ glob-parent@^5.0.0:
|
|||
dependencies:
|
||||
is-glob "^4.0.1"
|
||||
|
||||
global@^4.3.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
|
||||
integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
|
||||
dependencies:
|
||||
min-document "^2.19.0"
|
||||
process "^0.11.10"
|
||||
|
||||
globals@^11.1.0:
|
||||
version "11.12.0"
|
||||
resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e"
|
||||
|
@ -808,7 +787,7 @@ grapheme-splitter@^1.0.4:
|
|||
resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e"
|
||||
integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==
|
||||
|
||||
handlebars@*, handlebars@^4.1.2:
|
||||
handlebars@*:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67"
|
||||
integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw==
|
||||
|
@ -819,6 +798,17 @@ handlebars@*, handlebars@^4.1.2:
|
|||
optionalDependencies:
|
||||
uglify-js "^3.1.4"
|
||||
|
||||
handlebars@^4.1.2:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.6.0.tgz#33af6c3eda930d7a924f5d8f1c6d8edc3180512e"
|
||||
integrity sha512-i1ZUP7Qp2JdkMaFon2a+b0m5geE8Z4ZTLaGkgrObkEd+OkUKyRbRWw4KxuFCoHfdETSY1yf9/574eVoNSiK7pw==
|
||||
dependencies:
|
||||
neo-async "^2.6.0"
|
||||
optimist "^0.6.1"
|
||||
source-map "^0.6.1"
|
||||
optionalDependencies:
|
||||
uglify-js "^3.1.4"
|
||||
|
||||
has-flag@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
|
||||
|
@ -849,13 +839,6 @@ hmac-drbg@^1.0.0:
|
|||
minimalistic-assert "^1.0.0"
|
||||
minimalistic-crypto-utils "^1.0.1"
|
||||
|
||||
hoist-non-react-statics@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b"
|
||||
integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA==
|
||||
dependencies:
|
||||
react-is "^16.7.0"
|
||||
|
||||
http2-client@^1.2.5:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/http2-client/-/http2-client-1.3.2.tgz#80e31d90275844c0ccad8020b2de342a538a7971"
|
||||
|
@ -999,13 +982,6 @@ json-to-ast@^2.0.3:
|
|||
code-error-fragment "0.0.230"
|
||||
grapheme-splitter "^1.0.4"
|
||||
|
||||
json5@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
|
||||
integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
|
||||
dependencies:
|
||||
minimist "^1.2.0"
|
||||
|
||||
jsonpointer@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
|
||||
|
@ -1023,15 +999,6 @@ leven@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580"
|
||||
integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA=
|
||||
|
||||
loader-utils@^1.1.0:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
|
||||
integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
|
||||
dependencies:
|
||||
big.js "^5.2.2"
|
||||
emojis-list "^2.0.0"
|
||||
json5 "^1.0.1"
|
||||
|
||||
locate-path@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e"
|
||||
|
@ -1052,10 +1019,10 @@ loose-envify@^1.1.0, loose-envify@^1.4.0:
|
|||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
lunr@2.3.6:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.6.tgz#f278beee7ffd56ad86e6e478ce02ab2b98c78dd5"
|
||||
integrity sha512-swStvEyDqQ85MGpABCMBclZcLI/pBIlu8FFDtmX197+oEgKloJ67QnB+Tidh0340HmLMs39c4GrkPY3cmkXp6Q==
|
||||
lunr@2.3.8:
|
||||
version "2.3.8"
|
||||
resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.8.tgz#a8b89c31f30b5a044b97d2d28e2da191b6ba2072"
|
||||
integrity sha512-oxMeX/Y35PNFuZoHp+jUj5OSEmLCaIH4KTFJh7a93cHBoFmpw2IoPs22VIz7vyO2YUnx2Tn9dzIwO2P/4quIRg==
|
||||
|
||||
map-age-cleaner@^0.1.1:
|
||||
version "0.1.3"
|
||||
|
@ -1092,11 +1059,16 @@ mem@^4.0.0:
|
|||
mimic-fn "^2.0.0"
|
||||
p-is-promise "^2.0.0"
|
||||
|
||||
memoize-one@^5.0.0, memoize-one@~5.0.5:
|
||||
memoize-one@^5.0.0:
|
||||
version "5.0.5"
|
||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.5.tgz#8cd3809555723a07684afafcd6f756072ac75d7e"
|
||||
integrity sha512-ey6EpYv0tEaIbM/nTDOpHciXUvd+ackQrJgEzBwemhZZIWZjcyodqEcrmqDy2BKRTM3a65kKBV4WtLXJDt26SQ==
|
||||
|
||||
memoize-one@~5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0"
|
||||
integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==
|
||||
|
||||
merge-anything@^2.2.4:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/merge-anything/-/merge-anything-2.4.0.tgz#86959caf02bb8969d1ae5e1b652862bc5fe54e44"
|
||||
|
@ -1117,13 +1089,6 @@ mimic-fn@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
min-document@^2.19.0:
|
||||
version "2.19.0"
|
||||
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
|
||||
integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=
|
||||
dependencies:
|
||||
dom-walk "^0.1.0"
|
||||
|
||||
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
|
||||
|
@ -1139,11 +1104,6 @@ minimist@0.0.8:
|
|||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
|
||||
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
|
||||
|
||||
minimist@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
|
||||
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
|
||||
|
||||
minimist@~0.0.1:
|
||||
version "0.0.10"
|
||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf"
|
||||
|
@ -1156,17 +1116,17 @@ mkdirp@^0.5.1:
|
|||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
mobx-react-lite@1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-1.4.0.tgz#193beb5fdddf17ae61542f65ff951d84db402351"
|
||||
integrity sha512-5xCuus+QITQpzKOjAOIQ/YxNhOl/En+PlNJF+5QU4Qxn9gnNMJBbweAdEW3HnuVQbfqDYEUnkGs5hmkIIStehg==
|
||||
mobx-react-lite@^1.4.2:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/mobx-react-lite/-/mobx-react-lite-1.5.1.tgz#8eac90985b4d2bee475dd90a0d4d903be578f154"
|
||||
integrity sha512-40Gn8hFq+MuNHqCaeSo2adN4WvpWkIeSYZVJWzRzm0rbEf0BFow6Ir9IefErql0pX9q650TN1JAQXvrXxKR8Mg==
|
||||
|
||||
mobx-react@^6.1.3:
|
||||
version "6.1.3"
|
||||
resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-6.1.3.tgz#ad07880ea60cdcdb2a7e2a0d54e01379710cf00a"
|
||||
integrity sha512-eT/jO9dYIoB1AlZwI2VC3iX0gPOeOIqZsiwg7tDJV1B7Z69h+TZZL3dgOE0UeS2zoHhGeKbP+K+OLeLMnnkGnA==
|
||||
mobx-react@^6.1.4:
|
||||
version "6.1.4"
|
||||
resolved "https://registry.yarnpkg.com/mobx-react/-/mobx-react-6.1.4.tgz#818e7991c321c05bd9b8156d94be17dad165501e"
|
||||
integrity sha512-wzrJF1RflhyLh8ne4FJfMbG8ZgRFmZ62b4nbyhJzwQpAmrkSnSsAWG9mIff4ffV/Q7OU+uOYf7rXvSmiuUe4cw==
|
||||
dependencies:
|
||||
mobx-react-lite "1.4.0"
|
||||
mobx-react-lite "^1.4.2"
|
||||
|
||||
mobx@^4.2.0:
|
||||
version "4.13.0"
|
||||
|
@ -1430,12 +1390,12 @@ picomatch@^2.0.4:
|
|||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
|
||||
integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
|
||||
|
||||
polished@^3.4.1:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.yarnpkg.com/polished/-/polished-3.4.1.tgz#1eb5597ec1792206365635811d465751f5cbf71c"
|
||||
integrity sha512-GflTnlP5rrpDoigjczEkS6Ye7NDA4sFvAnlr5hSDrEvjiVj97Xzev3hZlLi3UB27fpxyTS9rWU64VzVLWkG+mg==
|
||||
polished@^3.4.2:
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/polished/-/polished-3.4.2.tgz#b4780dad81d64df55615fbfc77acb52fd17d88cd"
|
||||
integrity sha512-9Rch6iMZckABr6EFCLPZsxodeBpXMo9H4fRlfR/9VjMEyy5xpo1/WgXlJGgSjPyVhEZNycbW7UmYMNyWS5MI0g==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.4.5"
|
||||
"@babel/runtime" "^7.6.3"
|
||||
|
||||
postcss-value-parser@^3.3.0:
|
||||
version "3.3.1"
|
||||
|
@ -1459,7 +1419,7 @@ process@^0.11.10:
|
|||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
|
||||
prop-types@^15.5.0, prop-types@^15.5.4, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@^15.5.0, prop-types@^15.5.4, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
|
@ -1540,30 +1500,11 @@ react-dropdown@^1.6.4:
|
|||
dependencies:
|
||||
classnames "^2.2.3"
|
||||
|
||||
react-hot-loader@^4.12.14:
|
||||
version "4.12.14"
|
||||
resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.12.14.tgz#81ca06ffda0b90aad15d6069339f73ed6428340a"
|
||||
integrity sha512-ecxH4eBvEaJ9onT8vkEmK1FAAJUh1PqzGqds9S3k+GeihSp7nKAp4fOxytO+Ghr491LiBD38jaKyDXYnnpI9pQ==
|
||||
dependencies:
|
||||
fast-levenshtein "^2.0.6"
|
||||
global "^4.3.0"
|
||||
hoist-non-react-statics "^3.3.0"
|
||||
loader-utils "^1.1.0"
|
||||
prop-types "^15.6.1"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
shallowequal "^1.1.0"
|
||||
source-map "^0.7.3"
|
||||
|
||||
react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1:
|
||||
react-is@^16.6.0, react-is@^16.8.1:
|
||||
version "16.8.6"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
|
||||
integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
|
||||
|
||||
react-lifecycles-compat@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
|
||||
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
|
||||
|
||||
react-tabs@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/react-tabs/-/react-tabs-3.0.0.tgz#60311a17c755eb6aa9b3310123e67db421605127"
|
||||
|
@ -1602,31 +1543,30 @@ readdirp@^3.1.1:
|
|||
dependencies:
|
||||
picomatch "^2.0.4"
|
||||
|
||||
redoc@2.0.0-rc.16:
|
||||
version "2.0.0-rc.16"
|
||||
resolved "https://registry.yarnpkg.com/redoc/-/redoc-2.0.0-rc.16.tgz#01d5dafba6ae266a5934dc9904b87bc8a175b222"
|
||||
integrity sha512-5YWk7NBebYZ8xMbKXA1sD++QsSh7NbnB2sStJRKLeP/rU4oX586SIqHXl+MW1OhIZW44mYFMHpYzxpZKCllk9w==
|
||||
redoc@2.0.0-rc.23:
|
||||
version "2.0.0-rc.23"
|
||||
resolved "https://registry.yarnpkg.com/redoc/-/redoc-2.0.0-rc.23.tgz#3b8a47d9357e6ee52a0d93d08fb03ce00f424728"
|
||||
integrity sha512-ifrewYzrCrGBv6bFSh5FEnDTywVm6IL/VEb7PUpVPCC1lMceMAB1HrlyKlBCyNqjq9LcRO+y9q881LfPXS4PUw==
|
||||
dependencies:
|
||||
classnames "^2.2.6"
|
||||
decko "^1.2.0"
|
||||
dompurify "^2.0.3"
|
||||
dompurify "^2.0.7"
|
||||
eventemitter3 "^4.0.0"
|
||||
json-pointer "^0.6.0"
|
||||
json-schema-ref-parser "^6.1.0"
|
||||
lunr "2.3.6"
|
||||
lunr "2.3.8"
|
||||
mark.js "^8.11.1"
|
||||
marked "^0.7.0"
|
||||
memoize-one "~5.0.5"
|
||||
mobx-react "^6.1.3"
|
||||
memoize-one "~5.1.1"
|
||||
mobx-react "^6.1.4"
|
||||
openapi-sampler "1.0.0-beta.15"
|
||||
perfect-scrollbar "^1.4.0"
|
||||
polished "^3.4.1"
|
||||
polished "^3.4.2"
|
||||
prismjs "^1.17.1"
|
||||
prop-types "^15.7.2"
|
||||
react-dropdown "^1.6.4"
|
||||
react-hot-loader "^4.12.14"
|
||||
react-tabs "^3.0.0"
|
||||
slugify "^1.3.5"
|
||||
slugify "^1.3.6"
|
||||
stickyfill "^1.1.1"
|
||||
swagger2openapi "^5.3.1"
|
||||
tslib "^1.10.0"
|
||||
|
@ -1716,11 +1656,6 @@ sha.js@^2.4.0, sha.js@^2.4.8:
|
|||
inherits "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
shallowequal@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8"
|
||||
integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==
|
||||
|
||||
shebang-command@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||
|
@ -1782,10 +1717,10 @@ signal-exit@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
|
||||
|
||||
slugify@^1.3.5:
|
||||
version "1.3.5"
|
||||
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.3.5.tgz#90210678818b6d533cb060083aed0e8238133508"
|
||||
integrity sha512-5VCnH7aS13b0UqWOs7Ef3E5rkhFe8Od+cp7wybFv5mv/sYSRkucZlJX0bamAJky7b2TTtGvrJBWVdpdEicsSrA==
|
||||
slugify@^1.3.6:
|
||||
version "1.3.6"
|
||||
resolved "https://registry.yarnpkg.com/slugify/-/slugify-1.3.6.tgz#ba5fd6159b570fe4811d02ea9b1f4906677638c3"
|
||||
integrity sha512-wA9XS475ZmGNlEnYYLPReSfuz/c3VQsEMoU43mi6OnKMCdbnFXd4/Yg7J0lBv8jkPolacMpOrWEaoYxuE1+hoQ==
|
||||
|
||||
source-map@^0.5.0:
|
||||
version "0.5.7"
|
||||
|
@ -1797,11 +1732,6 @@ source-map@^0.6.1, source-map@~0.6.1:
|
|||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
|
||||
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
|
||||
|
||||
source-map@^0.7.3:
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
|
||||
integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==
|
||||
|
||||
sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
|
@ -1995,11 +1925,11 @@ tty-browserify@0.0.0:
|
|||
integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.6.0.tgz#704681345c53a8b2079fb6cec294b05ead242ff5"
|
||||
integrity sha512-W+jrUHJr3DXKhrsS7NUVxn3zqMOFn0hL/Ei6v0anCIMoKC93TjcflTagwIHLW7SfMFfiQuktQyFVCFHGUE0+yg==
|
||||
version "3.7.4"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.4.tgz#e6d83a1aa32ff448bd1679359ab13d8db0fe0743"
|
||||
integrity sha512-tinYWE8X1QfCHxS1lBS8yiDekyhSXOO6R66yNOCdUJeojxxw+PX2BHAz/BWyW7PQ7pkiWVxJfIEbiDxyLWvUGg==
|
||||
dependencies:
|
||||
commander "~2.20.0"
|
||||
commander "~2.20.3"
|
||||
source-map "~0.6.1"
|
||||
|
||||
url-template@^2.0.8:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
# DockerHub cd into Dockerfile location before buil
|
||||
# DockerHub cd into Dockerfile location before build
|
||||
# So we have to undo this.
|
||||
cd ../..
|
||||
docker build -f config/docker/Dockerfile -t $IMAGE_NAME .
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
},
|
||||
{
|
||||
"name": "Contacts",
|
||||
"description": "Contacts are Customer's address book.\nAll contact information used in Invoices, Subscriptions, Transacions, etc is enlisted here. Hovewer, changing a Contact won't change corresponding contact information in related resources\n"
|
||||
"description": "Contacts are Customer's address book.\nAll contact information used in Invoices, Subscriptions, Transacions, etc is enlisted here. However, changing a Contact won't change corresponding contact information in related resources\n"
|
||||
},
|
||||
{
|
||||
"name": "Coupons",
|
||||
|
@ -93,7 +93,7 @@
|
|||
},
|
||||
{
|
||||
"name": "Files",
|
||||
"description": "A File is an entity that can store a phyiscal file and some metadata. It also provides an easy access to\nits size, mime-type, user-defined tags and description thus allowing easy sorting and searching among stored\nfiles.\nThere are several methods of file uploading available: multipart/form-data encoded form, RAW POST (by sending\nfile contents as POST body), fetching from URL (by providing the file URL via 'url' param)\nAttachment is an entity that is used to link a File to one or multiple objects like Customer, Dispute, Payment,\nTransaction, Subscription, Plan, Product, Invoice, Note. That allows to quickly find and use files related to\nthose specific entities.\n"
|
||||
"description": "A File is an entity that can store a physical file and some metadata. It also provides an easy access to\nits size, mime-type, user-defined tags and description thus allowing easy sorting and searching among stored\nfiles.\nThere are several methods of file uploading available: multipart/form-data encoded form, RAW POST (by sending\nfile contents as POST body), fetching from URL (by providing the file URL via 'url' param)\nAttachment is an entity that is used to link a File to one or multiple objects like Customer, Dispute, Payment,\nTransaction, Subscription, Plan, Product, Invoice, Note. That allows to quickly find and use files related to\nthose specific entities.\n"
|
||||
},
|
||||
{
|
||||
"name": "Gateway Accounts",
|
||||
|
@ -15623,7 +15623,7 @@
|
|||
"description": "Reset user password\n",
|
||||
"responses": {
|
||||
"201": {
|
||||
"description": "Password was reseted successfully",
|
||||
"description": "Password was reset successfully",
|
||||
"headers": {
|
||||
"Rate-Limit-Limit": {
|
||||
"description": "The number of allowed requests in the current period",
|
||||
|
@ -23851,17 +23851,17 @@
|
|||
"type": "string"
|
||||
},
|
||||
"totpRequired": {
|
||||
"description": "The user setting of two-factor authentification",
|
||||
"description": "The user setting of two-factor authentication",
|
||||
"readOnly": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"totpSecret": {
|
||||
"description": "The user TOTP key for authentification app (if TOTP enabled)",
|
||||
"description": "The user TOTP key for authentication app (if TOTP enabled)",
|
||||
"readOnly": true,
|
||||
"type": "string"
|
||||
},
|
||||
"totpUrl": {
|
||||
"description": "The user link to QR-code for TOTP authentification app (if TOTP enabled)",
|
||||
"description": "The user link to QR-code for TOTP authentication app (if TOTP enabled)",
|
||||
"readOnly": true,
|
||||
"type": "string",
|
||||
"format": "url"
|
||||
|
@ -24250,7 +24250,7 @@
|
|||
},
|
||||
"bodyHtml": {
|
||||
"type": "string",
|
||||
"description": "Leave empty to recieve \"text/plain\" email.\nThe template palceholders are allowed.\n"
|
||||
"description": "Leave empty to receive \"text/plain\" email.\nThe template palceholders are allowed.\n"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
@ -26495,15 +26495,15 @@
|
|||
}
|
||||
},
|
||||
"totpRequired": {
|
||||
"description": "The user setting of two-factor authentification",
|
||||
"description": "The user setting of two-factor authentication",
|
||||
"type": "boolean"
|
||||
},
|
||||
"totpSecret": {
|
||||
"description": "The user TOTP key for authentification app (if TOTP enabled)",
|
||||
"description": "The user TOTP key for authentication app (if TOTP enabled)",
|
||||
"type": "string"
|
||||
},
|
||||
"totpUrl": {
|
||||
"description": "The user link to QR-code for TOTP authentification app (if TOTP enabled)",
|
||||
"description": "The user link to QR-code for TOTP authentication app (if TOTP enabled)",
|
||||
"type": "string",
|
||||
"format": "url"
|
||||
},
|
||||
|
@ -26984,7 +26984,7 @@
|
|||
"collectionExpand": {
|
||||
"name": "expand",
|
||||
"in": "query",
|
||||
"description": "Expand response to get full related object intead of ID. See the expand guide for more info.",
|
||||
"description": "Expand response to get full related object instead of ID. See the expand guide for more info.",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ const demos = [
|
|||
value: 'https://api.apis.guru/v2/specs/googleapis.com/calendar/v3/swagger.yaml',
|
||||
label: 'Google Calendar',
|
||||
},
|
||||
{ value: 'https://api.apis.guru/v2/specs/slack.com/1.0.6/swagger.yaml', label: 'Slack' },
|
||||
{ value: 'https://api.apis.guru/v2/specs/slack.com/1.2.0/swagger.yaml', label: 'Slack' },
|
||||
{ value: 'https://api.apis.guru/v2/specs/zoom.us/2.0.0/swagger.yaml', label: 'Zoom.us' },
|
||||
{
|
||||
value: 'https://api.apis.guru/v2/specs/graphhopper.com/1.0/swagger.yaml',
|
||||
|
|
|
@ -84,6 +84,14 @@ x-tagGroups:
|
|||
paths:
|
||||
/pet:
|
||||
parameters:
|
||||
- name: Accept-Language
|
||||
in: header
|
||||
description: "The language you prefer for messages. Supported values are en-AU, en-CA, en-GB, en-US"
|
||||
example: en-US
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
default: en-AU
|
||||
- name: cookieParam
|
||||
in: cookie
|
||||
description: Some cookie
|
||||
|
@ -296,7 +304,7 @@ paths:
|
|||
tags:
|
||||
- pet
|
||||
summary: Finds Pets by status
|
||||
description: Multiple status values can be provided with comma seperated strings
|
||||
description: Multiple status values can be provided with comma separated strings
|
||||
operationId: findPetsByStatus
|
||||
parameters:
|
||||
- name: status
|
||||
|
@ -341,7 +349,7 @@ paths:
|
|||
- pet
|
||||
summary: Finds Pets by tags
|
||||
description: >-
|
||||
Muliple tags can be provided with comma seperated strings. Use tag1,
|
||||
Multiple tags can be provided with comma separated strings. Use tag1,
|
||||
tag2, tag3 for testing.
|
||||
operationId: findPetsByTags
|
||||
deprecated: true
|
||||
|
@ -621,7 +629,7 @@ paths:
|
|||
type: integer
|
||||
format: int32
|
||||
X-Expires-After:
|
||||
description: date in UTC when toekn expires
|
||||
description: date in UTC when token expires
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
|
@ -676,6 +684,7 @@ components:
|
|||
type: string
|
||||
description: The measured skill for hunting
|
||||
default: lazy
|
||||
example: adventurous
|
||||
enum:
|
||||
- clueless
|
||||
- lazy
|
||||
|
@ -727,6 +736,7 @@ components:
|
|||
type: number
|
||||
description: Average amount of honey produced per day in ounces
|
||||
example: 3.14
|
||||
multipleOf: .01
|
||||
required:
|
||||
- honeyPerDay
|
||||
Id:
|
||||
|
@ -765,7 +775,7 @@ components:
|
|||
type: boolean
|
||||
default: false
|
||||
readOnly: true
|
||||
rqeuestId:
|
||||
requestId:
|
||||
description: Unique Request Id
|
||||
type: string
|
||||
writeOnly: true
|
||||
|
@ -888,7 +898,6 @@ components:
|
|||
type: string
|
||||
pattern: '/^\+(?:[0-9]-?){6,14}[0-9]$/'
|
||||
example: +1-202-555-0192
|
||||
nullable: true
|
||||
userStatus:
|
||||
description: User status
|
||||
type: integer
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import * as React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
// tslint:disable-next-line
|
||||
import { AppContainer } from 'react-hot-loader';
|
||||
// import DevTools from 'mobx-react-devtools';
|
||||
|
||||
|
|
|
@ -631,7 +631,7 @@ paths:
|
|||
X-Expires-After:
|
||||
type: string
|
||||
format: date-time
|
||||
description: date in UTC when toekn expires
|
||||
description: date in UTC when token expires
|
||||
'400':
|
||||
description: Invalid username/password supplied
|
||||
/user/logout:
|
||||
|
|
|
@ -42,7 +42,7 @@ describe('Servers', () => {
|
|||
// TODO add cy-data attributes
|
||||
cy.get('[data-section-id="operation/addPet"]').should(
|
||||
'contain',
|
||||
'http://localhost:' + win.location.port + '/e2e/pet',
|
||||
'http://localhost:' + win.location.port + '/pet',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -57,7 +57,7 @@ describe('Servers', () => {
|
|||
// TODO add cy-data attributes
|
||||
cy.get('[data-section-id="operation/addPet"]').should(
|
||||
'contain',
|
||||
'http://localhost:' + win.location.port + '/e2e/pet',
|
||||
'http://localhost:' + win.location.port + '/pet',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
112
package.json
112
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "redoc",
|
||||
"version": "2.0.0-rc.16",
|
||||
"version": "2.0.0-rc.23",
|
||||
"description": "ReDoc",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -40,7 +40,7 @@
|
|||
"bundle": "npm run bundle:clean && npm run bundle:lib && npm run bundle:standalone",
|
||||
"declarations": "tsc --emitDeclarationOnly -p tsconfig.lib.json && cp -R src/types typings/",
|
||||
"stats": "webpack --env.standalone --json --profile --mode=production > stats.json",
|
||||
"prettier": "prettier --write \"src/**/*.{ts,tsx}\"",
|
||||
"prettier": "prettier --write \"cli/index.ts\" \"src/**/*.{ts,tsx}\"",
|
||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 1",
|
||||
"lint": "tslint --project tsconfig.json",
|
||||
"benchmark": "node ./benchmark/benchmark.js",
|
||||
|
@ -52,77 +52,78 @@
|
|||
"docker:build": "docker build -f config/docker/Dockerfile -t redoc ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "7.5.5",
|
||||
"@babel/plugin-syntax-decorators": "7.2.0",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.2.0",
|
||||
"@babel/plugin-syntax-jsx": "7.2.0",
|
||||
"@babel/plugin-syntax-typescript": "7.3.3",
|
||||
"@cypress/webpack-preprocessor": "4.1.0",
|
||||
"@hot-loader/react-dom": "^16.8.6",
|
||||
"@types/chai": "4.1.7",
|
||||
"@types/dompurify": "^0.0.33",
|
||||
"@types/enzyme": "^3.10.3",
|
||||
"@babel/core": "7.7.5",
|
||||
"@babel/plugin-syntax-decorators": "7.7.4",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
|
||||
"@babel/plugin-syntax-jsx": "7.7.4",
|
||||
"@babel/plugin-syntax-typescript": "7.7.4",
|
||||
"@cypress/webpack-preprocessor": "4.1.1",
|
||||
"@hot-loader/react-dom": "^16.11.0",
|
||||
"@types/chai": "4.2.7",
|
||||
"@types/dompurify": "^2.0.0",
|
||||
"@types/enzyme": "^3.10.4",
|
||||
"@types/enzyme-to-json": "^1.5.3",
|
||||
"@types/jest": "^24.0.15",
|
||||
"@types/jest": "^24.0.23",
|
||||
"@types/json-pointer": "^1.0.30",
|
||||
"@types/lodash": "^4.14.136",
|
||||
"@types/lodash": "^4.14.149",
|
||||
"@types/lunr": "^2.3.2",
|
||||
"@types/mark.js": "^8.11.4",
|
||||
"@types/marked": "^0.6.5",
|
||||
"@types/mark.js": "^8.11.5",
|
||||
"@types/marked": "^0.7.2",
|
||||
"@types/prismjs": "^1.16.0",
|
||||
"@types/promise": "^7.1.30",
|
||||
"@types/prop-types": "^15.7.1",
|
||||
"@types/prop-types": "^15.7.3",
|
||||
"@types/qs": "^6.5.1",
|
||||
"@types/react": "^16.8.23",
|
||||
"@types/react-dom": "^16.8.5",
|
||||
"@types/react": "^16.9.16",
|
||||
"@types/react-dom": "^16.9.4",
|
||||
"@types/react-hot-loader": "^4.1.0",
|
||||
"@types/react-tabs": "^2.3.1",
|
||||
"@types/styled-components": "^4.1.18",
|
||||
"@types/styled-components": "^4.4.1",
|
||||
"@types/tapable": "1.0.4",
|
||||
"@types/webpack": "^4.32.1",
|
||||
"@types/webpack-env": "^1.14.0",
|
||||
"@types/yargs": "^13.0.0",
|
||||
"@types/webpack": "^4.41.0",
|
||||
"@types/webpack-env": "^1.14.1",
|
||||
"@types/yargs": "^13.0.3",
|
||||
"babel-loader": "8.0.6",
|
||||
"babel-plugin-styled-components": "^1.10.6",
|
||||
"beautify-benchmark": "^0.2.4",
|
||||
"bundlesize": "^0.18.0",
|
||||
"conventional-changelog-cli": "^2.0.23",
|
||||
"copy-webpack-plugin": "^5.0.4",
|
||||
"core-js": "^3.1.4",
|
||||
"coveralls": "^3.0.5",
|
||||
"css-loader": "^3.1.0",
|
||||
"cypress": "~3.4.0",
|
||||
"conventional-changelog-cli": "^2.0.28",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"core-js": "^3.5.0",
|
||||
"coveralls": "^3.0.9",
|
||||
"css-loader": "^3.3.0",
|
||||
"cypress": "~3.7.0",
|
||||
"deploy-to-gh-pages": "^1.3.7",
|
||||
"enzyme": "^3.10.0",
|
||||
"enzyme-adapter-react-16": "^1.14.0",
|
||||
"enzyme-to-json": "^3.3.5",
|
||||
"fork-ts-checker-webpack-plugin": "1.4.3",
|
||||
"enzyme-adapter-react-16": "^1.15.1",
|
||||
"enzyme-to-json": "^3.4.3",
|
||||
"fork-ts-checker-webpack-plugin": "3.1.1",
|
||||
"html-webpack-plugin": "^3.1.0",
|
||||
"jest": "^24.8.0",
|
||||
"jest": "^24.9.0",
|
||||
"license-checker": "^25.0.1",
|
||||
"lodash": "^4.17.15",
|
||||
"mobx": "^4.3.1",
|
||||
"prettier": "^1.18.2",
|
||||
"prettier-eslint": "^9.0.0",
|
||||
"prettier": "^1.19.1",
|
||||
"prettier-eslint": "^9.0.1",
|
||||
"raf": "^3.4.1",
|
||||
"react": "^16.8.6",
|
||||
"react-dom": "^16.8.6",
|
||||
"rimraf": "^2.6.3",
|
||||
"react": "^16.12.0",
|
||||
"react-hot-loader": "^4.12.18",
|
||||
"react-dom": "^16.12.0",
|
||||
"rimraf": "^3.0.0",
|
||||
"shelljs": "^0.8.3",
|
||||
"source-map-loader": "^0.2.4",
|
||||
"style-loader": "^0.23.1",
|
||||
"styled-components": "^4.3.2",
|
||||
"ts-jest": "24.0.2",
|
||||
"ts-loader": "6.0.4",
|
||||
"ts-node": "^8.3.0",
|
||||
"tslint": "^5.18.0",
|
||||
"tslint-react": "^4.0.0",
|
||||
"typescript": "^3.5.3",
|
||||
"style-loader": "^1.0.1",
|
||||
"styled-components": "^4.4.1",
|
||||
"ts-jest": "24.2.0",
|
||||
"ts-loader": "6.2.1",
|
||||
"ts-node": "^8.5.4",
|
||||
"tslint": "^5.20.1",
|
||||
"tslint-react": "^4.1.0",
|
||||
"typescript": "^3.7.3",
|
||||
"unfetch": "^4.1.0",
|
||||
"url-polyfill": "^1.1.7",
|
||||
"webpack": "^4.38.0",
|
||||
"webpack-cli": "^3.3.6",
|
||||
"webpack-dev-server": "^3.7.2",
|
||||
"webpack": "^4.41.2",
|
||||
"webpack-cli": "^3.3.10",
|
||||
"webpack-dev-server": "^3.9.0",
|
||||
"webpack-node-externals": "^1.6.0",
|
||||
"workerize-loader": "^1.0.4",
|
||||
"yaml-js": "^0.2.3"
|
||||
|
@ -140,27 +141,26 @@
|
|||
"brace": "^0.11.1",
|
||||
"classnames": "^2.2.6",
|
||||
"decko": "^1.2.0",
|
||||
"dompurify": "^1.0.11",
|
||||
"dompurify": "^2.0.7",
|
||||
"eventemitter3": "^4.0.0",
|
||||
"json-pointer": "^0.6.0",
|
||||
"json-schema-ref-parser": "^6.1.0",
|
||||
"lunr": "2.3.6",
|
||||
"lunr": "2.3.8",
|
||||
"mark.js": "^8.11.1",
|
||||
"marked": "^0.7.0",
|
||||
"memoize-one": "^5.0.5",
|
||||
"mobx-react": "^6.1.1",
|
||||
"memoize-one": "~5.1.1",
|
||||
"mobx-react": "^6.1.4",
|
||||
"openapi-sampler": "1.0.0-beta.15",
|
||||
"perfect-scrollbar": "^1.4.0",
|
||||
"polished": "^3.4.1",
|
||||
"polished": "^3.4.2",
|
||||
"prismjs": "^1.17.1",
|
||||
"prop-types": "^15.7.2",
|
||||
"qs": "^6.5.2",
|
||||
"react-ace": "^6.0.0",
|
||||
"react-dropdown": "^1.6.4",
|
||||
"react-hot-loader": "^4.12.10",
|
||||
"react-switch": "^5.0.1",
|
||||
"react-tabs": "^3.0.0",
|
||||
"slugify": "^1.3.4",
|
||||
"slugify": "^1.3.6",
|
||||
"stickyfill": "^1.1.1",
|
||||
"swagger2openapi": "^5.3.1",
|
||||
"tslib": "^1.10.0",
|
||||
|
|
|
@ -55,7 +55,7 @@ export const StyledDropdown = styled(Dropdown)`
|
|||
display: block;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
right: 0.6em;
|
||||
right: 0.3em;
|
||||
top: 50%;
|
||||
margin-top: -0.125em;
|
||||
width: 0;
|
||||
|
@ -97,7 +97,7 @@ export const StyledDropdown = styled(Dropdown)`
|
|||
export const SimpleDropdown = styled(StyledDropdown)`
|
||||
margin-left: 10px;
|
||||
text-transform: none;
|
||||
font-size: 0.929em;
|
||||
font-size: 0.969em;
|
||||
|
||||
.Dropdown-control {
|
||||
font-size: 1em;
|
||||
|
|
|
@ -64,7 +64,7 @@ export const PropertyNameCell = styled(PropertyCell)`
|
|||
line-height: 20px;
|
||||
white-space: nowrap;
|
||||
font-size: 0.929em;
|
||||
font-family: ${props => props.theme.typography.headings.fontFamily};
|
||||
font-family: ${props => props.theme.typography.code.fontFamily};
|
||||
|
||||
&.deprecated {
|
||||
${deprecatedCss};
|
||||
|
|
|
@ -72,7 +72,6 @@ export const ExampleValue = styled(FieldLabel)`
|
|||
padding: 0 ${theme.spacing.unit}px;
|
||||
border: 1px solid ${transparentize(0.9, theme.colors.text.primary)};
|
||||
font-family: ${theme.typography.code.fontFamily};
|
||||
color: ${theme.typography.code.color};
|
||||
}`};
|
||||
& + & {
|
||||
margin-left: 0;
|
||||
|
@ -91,6 +90,7 @@ export const ConstraintItem = styled(FieldLabel)`
|
|||
margin: 0 ${theme.spacing.unit}px;
|
||||
padding: 0 ${theme.spacing.unit}px;
|
||||
border: 1px solid ${transparentize(0.9, theme.colors.primary.main)};
|
||||
font-family: ${theme.typography.code.fontFamily};
|
||||
}`};
|
||||
& + & {
|
||||
margin-left: 0;
|
||||
|
|
|
@ -11,13 +11,14 @@ export const OneOfLabel = styled.span`
|
|||
font-size: 0.9em;
|
||||
margin-right: 10px;
|
||||
color: ${props => props.theme.colors.primary.main};
|
||||
font-family: Montserrat;
|
||||
font-family: ${props => props.theme.typography.headings.fontFamily};
|
||||
}
|
||||
`;
|
||||
|
||||
export const OneOfButton = styled.li<{ active: boolean }>`
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
margin-bottom: 5px;
|
||||
font-size: 0.8em;
|
||||
cursor: pointer;
|
||||
border: 1px solid ${props => props.theme.colors.primary.main};
|
||||
|
|
|
@ -76,7 +76,7 @@ export class SectionItem extends React.Component<ContentItemProps> {
|
|||
return (
|
||||
<>
|
||||
<Row>
|
||||
<MiddlePanel compact={level !== 1}>
|
||||
<MiddlePanel compact={false}>
|
||||
<Header>
|
||||
<ShareLink to={this.props.item.id} />
|
||||
{name}
|
||||
|
|
|
@ -27,16 +27,19 @@ export class FieldDetails extends React.PureComponent<FieldProps> {
|
|||
static contextType = OptionsContext;
|
||||
render() {
|
||||
const { showExamples, field, renderDiscriminatorSwitch } = this.props;
|
||||
const { enumSkipQuotes } = this.context;
|
||||
const { enumSkipQuotes, hideSchemaTitles } = this.context;
|
||||
|
||||
const { schema, description, example, deprecated } = field;
|
||||
|
||||
const rawDefault = !!enumSkipQuotes || field.in === 'header'; // having quotes around header field default values is confusing and inappropriate
|
||||
|
||||
let exampleField: JSX.Element | null = null;
|
||||
|
||||
if (showExamples && example !== undefined) {
|
||||
const label = l('example') + ':';
|
||||
if (field.in && (field.style || field.serializationMime)) {
|
||||
const serializedValue = serializeParameterValue(field, example);
|
||||
// decode for better readability in examples: see https://github.com/Redocly/redoc/issues/1138
|
||||
const serializedValue = decodeURIComponent(serializeParameterValue(field, example));
|
||||
exampleField = <FieldDetail label={label} value={serializedValue} raw={true} />;
|
||||
} else {
|
||||
exampleField = <FieldDetail label={label} value={example} />;
|
||||
|
@ -56,10 +59,10 @@ export class FieldDetails extends React.PureComponent<FieldProps> {
|
|||
>{' '}
|
||||
</TypeFormat>
|
||||
)}
|
||||
{schema.title && <TypeTitle> ({schema.title}) </TypeTitle>}
|
||||
{schema.title && !hideSchemaTitles && <TypeTitle> ({schema.title}) </TypeTitle>}
|
||||
<ConstraintsView constraints={schema.constraints} />
|
||||
{schema.nullable && <NullableLabel> {l('nullable')} </NullableLabel>}
|
||||
{schema.pattern && <PatternLabel>{schema.pattern}</PatternLabel>}
|
||||
{schema.pattern && <PatternLabel> {schema.pattern} </PatternLabel>}
|
||||
{schema.isCircular && <RecursiveLabel> {l('recursive')} </RecursiveLabel>}
|
||||
</div>
|
||||
{deprecated && (
|
||||
|
@ -67,7 +70,7 @@ export class FieldDetails extends React.PureComponent<FieldProps> {
|
|||
<Badge type="warning"> {l('deprecated')} </Badge>
|
||||
</div>
|
||||
)}
|
||||
<FieldDetail raw={enumSkipQuotes} label={l('default') + ':'} value={schema.default} />
|
||||
<FieldDetail raw={rawDefault} label={l('default') + ':'} value={schema.default} />
|
||||
{!renderDiscriminatorSwitch && <EnumValues type={schema.type} values={schema.enum} />}{' '}
|
||||
{exampleField}
|
||||
{<Extensions extensions={{ ...field.extensions, ...schema.extensions }} />}
|
||||
|
|
|
@ -25,7 +25,7 @@ export class AdvancedMarkdown extends React.Component<AdvancedMarkdownProps> {
|
|||
renderWithOptionsAndStore(options: RedocNormalizedOptions, store?: AppStore) {
|
||||
const { source, htmlWrap = i => i } = this.props;
|
||||
if (!store) {
|
||||
throw new Error('When using componentes in markdown, store prop must be provided');
|
||||
throw new Error('When using components in markdown, store prop must be provided');
|
||||
}
|
||||
|
||||
const renderer = new MarkdownRenderer(options);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { OperationModel, RedocNormalizedOptions } from '../../services';
|
||||
import { isPayloadSample, OperationModel, RedocNormalizedOptions } from '../../services';
|
||||
import { PayloadSamples } from '../PayloadSamples/PayloadSamples';
|
||||
import { SourceCodeWithCopy } from '../SourceCode/SourceCode';
|
||||
|
||||
|
@ -19,15 +19,10 @@ export class RequestSamples extends React.Component<RequestSamplesProps> {
|
|||
|
||||
render() {
|
||||
const { operation } = this.props;
|
||||
const requestBodyContent = operation.requestBody && operation.requestBody.content;
|
||||
const hasBodySample = requestBodyContent && requestBodyContent.hasSample;
|
||||
const samples = operation.codeSamples;
|
||||
|
||||
const hasSamples = hasBodySample || samples.length > 0;
|
||||
const hideTabList =
|
||||
samples.length + (hasBodySample ? 1 : 0) === 1
|
||||
? this.context.hideSingleRequestSampleTab
|
||||
: false;
|
||||
const hasSamples = samples.length > 0;
|
||||
const hideTabList = samples.length === 1 ? this.context.hideSingleRequestSampleTab : false;
|
||||
return (
|
||||
(hasSamples && (
|
||||
<div>
|
||||
|
@ -35,23 +30,21 @@ export class RequestSamples extends React.Component<RequestSamplesProps> {
|
|||
|
||||
<Tabs defaultIndex={0}>
|
||||
<TabList hidden={hideTabList}>
|
||||
{hasBodySample && <Tab key="payload"> Payload </Tab>}
|
||||
{samples.map(sample => (
|
||||
<Tab key={sample.lang + '_' + (sample.label || '')}>
|
||||
{sample.label !== undefined ? sample.label : sample.lang}
|
||||
</Tab>
|
||||
))}
|
||||
</TabList>
|
||||
{hasBodySample && (
|
||||
<TabPanel key="payload">
|
||||
<div>
|
||||
<PayloadSamples content={requestBodyContent!} />
|
||||
</div>
|
||||
</TabPanel>
|
||||
)}
|
||||
{samples.map(sample => (
|
||||
<TabPanel key={sample.lang}>
|
||||
<SourceCodeWithCopy lang={sample.lang} source={sample.source} />
|
||||
<TabPanel key={sample.lang + '_' + (sample.label || '')}>
|
||||
{isPayloadSample(sample) ? (
|
||||
<div>
|
||||
<PayloadSamples content={sample.requestBodyContent} />
|
||||
</div>
|
||||
) : (
|
||||
<SourceCodeWithCopy lang={sample.lang} source={sample.source} />
|
||||
)}
|
||||
</TabPanel>
|
||||
))}
|
||||
</Tabs>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import { darken } from 'polished';
|
||||
import { darken, getLuminance, lighten } from 'polished';
|
||||
import styled from '../../styled-components';
|
||||
import { MenuItemLabel } from '../SideMenu/styled.elements';
|
||||
|
||||
|
@ -17,7 +17,12 @@ export const SearchInput = styled.input.attrs(() => ({
|
|||
padding: 5px ${props => props.theme.spacing.unit * 2}px 5px
|
||||
${props => props.theme.spacing.unit * 4}px;
|
||||
border: 0;
|
||||
border-bottom: 1px solid ${({ theme }) => darken(0.1, theme.menu.backgroundColor)};
|
||||
border-bottom: 1px solid
|
||||
${({ theme }) =>
|
||||
(getLuminance(theme.menu.backgroundColor) > 0.5 ? darken : lighten)(
|
||||
0.1,
|
||||
theme.menu.backgroundColor,
|
||||
)};
|
||||
font-family: ${({ theme }) => theme.typography.fontFamily};
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
|
@ -53,11 +58,12 @@ export const SearchIcon = styled((props: { className?: string }) => (
|
|||
|
||||
export const SearchResultsBox = styled.div`
|
||||
padding: ${props => props.theme.spacing.unit}px 0;
|
||||
background-color: #ededed;
|
||||
background-color: ${({ theme }) => darken(0.05, theme.menu.backgroundColor)}};
|
||||
color: ${props => props.theme.menu.textColor};
|
||||
min-height: 150px;
|
||||
max-height: 250px;
|
||||
border-top: 1px solid #e1e1e1;
|
||||
border-bottom: 1px solid #e1e1e1;
|
||||
border-top: ${({ theme }) => darken(0.1, theme.menu.backgroundColor)}};
|
||||
border-bottom: ${({ theme }) => darken(0.1, theme.menu.backgroundColor)}};
|
||||
margin-top: 10px;
|
||||
line-height: 1.4;
|
||||
font-size: 0.9em;
|
||||
|
@ -66,17 +72,14 @@ export const SearchResultsBox = styled.div`
|
|||
padding-top: 6px;
|
||||
padding-bottom: 6px;
|
||||
|
||||
&:hover {
|
||||
background-color: #e1e1e1;
|
||||
&:hover,
|
||||
&.active {
|
||||
background-color: ${({ theme }) => darken(0.1, theme.menu.backgroundColor)};
|
||||
}
|
||||
|
||||
> svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background-color: #e1e1e1;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
|
|
|
@ -108,7 +108,7 @@ export class SecurityDefs extends React.PureComponent<SecurityDefsProps, Securit
|
|||
<table className="security-details">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th> Security scheme type: </th>
|
||||
<th> Security Scheme Type </th>
|
||||
<td> {AUTH_TYPES[scheme.type] || scheme.type} </td>
|
||||
<td> Value </td>
|
||||
</tr>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// import { observe } from 'mobx';
|
||||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
|
||||
|
@ -15,7 +16,7 @@ export interface MenuItemProps {
|
|||
|
||||
@observer
|
||||
export class MenuItem extends React.Component<MenuItemProps> {
|
||||
ref: Element | null;
|
||||
ref = React.createRef<HTMLLabelElement>();
|
||||
|
||||
activate = (evt: React.MouseEvent<HTMLElement>) => {
|
||||
this.props.onActivate!(this.props.item);
|
||||
|
@ -31,28 +32,19 @@ export class MenuItem extends React.Component<MenuItemProps> {
|
|||
}
|
||||
|
||||
scrollIntoViewIfActive() {
|
||||
if (this.props.item.active && this.ref) {
|
||||
this.ref.scrollIntoViewIfNeeded();
|
||||
if (this.props.item.active && this.ref.current) {
|
||||
this.ref.current.scrollIntoViewIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
saveRef = ref => {
|
||||
this.ref = ref;
|
||||
};
|
||||
|
||||
render() {
|
||||
const { item, withoutChildren } = this.props;
|
||||
return (
|
||||
<MenuItemLi
|
||||
onClick={this.activate}
|
||||
depth={item.depth}
|
||||
ref={this.saveRef}
|
||||
data-item-id={item.id}
|
||||
>
|
||||
<MenuItemLi onClick={this.activate} depth={item.depth} data-item-id={item.id}>
|
||||
{item.type === 'operation' ? (
|
||||
<OperationMenuItemContent {...this.props} item={item as OperationModel} />
|
||||
) : (
|
||||
<MenuItemLabel depth={item.depth} active={item.active} type={item.type}>
|
||||
<MenuItemLabel depth={item.depth} active={item.active} type={item.type} ref={this.ref}>
|
||||
<MenuItemTitle title={item.name}>
|
||||
{item.name}
|
||||
{this.props.children}
|
||||
|
@ -81,10 +73,23 @@ export interface OperationMenuItemContentProps {
|
|||
|
||||
@observer
|
||||
export class OperationMenuItemContent extends React.Component<OperationMenuItemContentProps> {
|
||||
ref = React.createRef<HTMLLabelElement>();
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.props.item.active && this.ref.current) {
|
||||
this.ref.current.scrollIntoViewIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { item } = this.props;
|
||||
return (
|
||||
<MenuItemLabel depth={item.depth} active={item.active} deprecated={item.deprecated}>
|
||||
<MenuItemLabel
|
||||
depth={item.depth}
|
||||
active={item.active}
|
||||
deprecated={item.deprecated}
|
||||
ref={this.ref}
|
||||
>
|
||||
<OperationBadge type={item.httpVerb}>{shortenHTTPVerb(item.httpVerb)}</OperationBadge>
|
||||
<MenuItemTitle width="calc(100% - 38px)">
|
||||
{item.name}
|
||||
|
|
|
@ -104,7 +104,7 @@ export const menuItemDepth = {
|
|||
font-size: 0.929em;
|
||||
text-transform: ${({ theme }) => theme.menu.level1Items.textTransform};
|
||||
&:hover {
|
||||
color: ${props => props.theme.colors.primary.main};
|
||||
color: ${props => props.theme.menu.activeTextColor};
|
||||
}
|
||||
`,
|
||||
2: css`
|
||||
|
@ -126,7 +126,7 @@ export const MenuItemLabel = styled.label.attrs((props: MenuItemLabelType) => ({
|
|||
}),
|
||||
}))<MenuItemLabelType>`
|
||||
cursor: pointer;
|
||||
color: ${props => (props.active ? props.theme.colors.primary.main : props.theme.menu.textColor)};
|
||||
color: ${props => (props.active ? props.theme.menu.activeTextColor : props.theme.menu.textColor)};
|
||||
margin: 0;
|
||||
padding: 12.5px ${props => props.theme.spacing.unit * 4}px;
|
||||
${({ depth, type, theme }) =>
|
||||
|
|
|
@ -33,7 +33,7 @@ const StyledStickySidebar = styled.div<{ open?: boolean }>`
|
|||
flex-direction: column;
|
||||
|
||||
backface-visibility: hidden;
|
||||
contain: strict;
|
||||
/* contain: strict; TODO: breaks layout since Chrome 80*/
|
||||
|
||||
height: 100vh;
|
||||
position: sticky;
|
||||
|
@ -44,7 +44,7 @@ const StyledStickySidebar = styled.div<{ open?: boolean }>`
|
|||
position: fixed;
|
||||
z-index: 20;
|
||||
width: 100%;
|
||||
background: #ffffff;
|
||||
background: ${({ theme }) => theme.menu.backgroundColor};
|
||||
display: ${props => (props.open ? 'flex' : 'none')};
|
||||
`};
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import memoize from 'memoize-one';
|
||||
import * as memoize from 'memoize-one/dist/memoize-one.cjs'; // fixme: https://github.com/alexreardon/memoize-one/issues/37
|
||||
import { Component, createContext } from 'react';
|
||||
|
||||
import { AppStore } from '../services/';
|
||||
|
|
|
@ -24,14 +24,14 @@ describe('Components', () => {
|
|||
});
|
||||
|
||||
test('should collapse/uncollapse', () => {
|
||||
expect(component.html()).not.toContain('class="hoverable"'); // all are collapesed by default
|
||||
expect(component.html()).not.toContain('class="hoverable"'); // all are collapsed by default
|
||||
const expandAll = component.find('div > span[children=" Expand all "]');
|
||||
expandAll.simulate('click');
|
||||
expect(component.html()).toContain('class="hoverable"'); // all are collapesed
|
||||
expect(component.html()).toContain('class="hoverable"'); // all are collapsed
|
||||
|
||||
const collapseAll = component.find('div > span[children=" Collapse all "]');
|
||||
collapseAll.simulate('click');
|
||||
expect(component.html()).not.toContain('class="hoverable"'); // all are collapesed
|
||||
expect(component.html()).not.toContain('class="hoverable"'); // all are collapsed
|
||||
});
|
||||
|
||||
test('should collapse/uncollapse', () => {
|
||||
|
|
|
@ -101,6 +101,9 @@ export class AppStore {
|
|||
dispose() {
|
||||
this.scroll.dispose();
|
||||
this.menu.dispose();
|
||||
if (this.search) {
|
||||
this.search.dispose();
|
||||
}
|
||||
if (this.disposer != null) {
|
||||
this.disposer();
|
||||
}
|
||||
|
|
|
@ -45,6 +45,14 @@ export class MarkdownRenderer {
|
|||
return compRegexp.test(rawText);
|
||||
}
|
||||
|
||||
static getTextBeforeHading(md: string, heading: string): string {
|
||||
const headingLinePos = md.search(new RegExp(`^##?\\s+${heading}`, 'm'));
|
||||
if (headingLinePos > -1) {
|
||||
return md.substring(0, headingLinePos);
|
||||
}
|
||||
return md;
|
||||
}
|
||||
|
||||
headings: MarkdownHeading[] = [];
|
||||
currentTopHeading: MarkdownHeading;
|
||||
|
||||
|
@ -119,7 +127,12 @@ export class MarkdownRenderer {
|
|||
.trim();
|
||||
}
|
||||
|
||||
headingRule = (text: string, level: number, raw: string, slugger: marked.Slugger) => {
|
||||
headingRule = (
|
||||
text: string,
|
||||
level: 1 | 2 | 3 | 4 | 5 | 6,
|
||||
raw: string,
|
||||
slugger: marked.Slugger,
|
||||
) => {
|
||||
if (level === 1) {
|
||||
this.currentTopHeading = this.saveHeading(text, level);
|
||||
} else if (level === 2) {
|
||||
|
|
|
@ -66,6 +66,13 @@ export class MenuBuilder {
|
|||
const renderer = new MarkdownRenderer(options);
|
||||
const headings = renderer.extractHeadings(description || '');
|
||||
|
||||
if (headings.length && parent && parent.description) {
|
||||
parent.description = MarkdownRenderer.getTextBeforeHading(
|
||||
parent.description,
|
||||
headings[0].name,
|
||||
);
|
||||
}
|
||||
|
||||
const mapHeadingsDeep = (_parent, items, depth = 1) =>
|
||||
items.map(heading => {
|
||||
const group = new GroupModel('section', heading, _parent);
|
||||
|
@ -88,7 +95,7 @@ export class MenuBuilder {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns array of OperationsGroup items for the tag groups (x-tagGroups vendor extenstion)
|
||||
* Returns array of OperationsGroup items for the tag groups (x-tagGroups vendor extension)
|
||||
* @param tags value of `x-tagGroups` vendor extension
|
||||
*/
|
||||
static getTagGroupsItems(
|
||||
|
|
|
@ -190,7 +190,7 @@ export class MenuStore {
|
|||
* activate menu item
|
||||
* @param item item to activate
|
||||
* @param updateLocation [true] whether to update location
|
||||
* @param rewriteHistory [false] whether to rewrite browser history (do not create new enrty)
|
||||
* @param rewriteHistory [false] whether to rewrite browser history (do not create new entry)
|
||||
*/
|
||||
@action
|
||||
activate(
|
||||
|
|
|
@ -112,7 +112,7 @@ export class OpenAPIParser {
|
|||
};
|
||||
|
||||
/**
|
||||
* checks if the objectt is OpenAPI reference (containts $ref property)
|
||||
* checks if the object is OpenAPI reference (contains $ref property)
|
||||
*/
|
||||
isRef(obj: any): obj is OpenAPIRef {
|
||||
if (!obj) {
|
||||
|
@ -122,7 +122,7 @@ export class OpenAPIParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* resets visited enpoints. should be run after
|
||||
* resets visited endpoints. should be run after
|
||||
*/
|
||||
resetVisited() {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
|
@ -146,7 +146,7 @@ export class OpenAPIParser {
|
|||
/**
|
||||
* Resolve given reference object or return as is if it is not a reference
|
||||
* @param obj object to dereference
|
||||
* @param forceCircular whether to dereference even if it is cirular ref
|
||||
* @param forceCircular whether to dereference even if it is circular ref
|
||||
*/
|
||||
deref<T extends object>(obj: OpenAPIRef | T, forceCircular: boolean = false): T {
|
||||
if (this.isRef(obj)) {
|
||||
|
@ -177,10 +177,10 @@ export class OpenAPIParser {
|
|||
}
|
||||
|
||||
/**
|
||||
* Merge allOf contsraints.
|
||||
* Merge allOf constraints.
|
||||
* @param schema schema with allOF
|
||||
* @param $ref pointer of the schema
|
||||
* @param forceCircular whether to dereference children even if it is a cirular ref
|
||||
* @param forceCircular whether to dereference children even if it is a circular ref
|
||||
*/
|
||||
mergeAllOf(
|
||||
schema: OpenAPISchema,
|
||||
|
@ -275,13 +275,13 @@ export class OpenAPIParser {
|
|||
}
|
||||
|
||||
// merge rest of constraints
|
||||
// TODO: do more intelegent merge
|
||||
// TODO: do more intelligent merge
|
||||
receiver = { ...subSchema, ...receiver };
|
||||
|
||||
if (subSchemaRef) {
|
||||
receiver.parentRefs!.push(subSchemaRef);
|
||||
if (receiver.title === undefined && isNamedDefinition(subSchemaRef)) {
|
||||
// this is not so correct behaviour. comented out for now
|
||||
// this is not so correct behaviour. commented out for now
|
||||
// ref: https://github.com/Redocly/redoc/issues/601
|
||||
// receiver.title = JsonPointer.baseName(subSchemaRef);
|
||||
}
|
||||
|
@ -296,8 +296,8 @@ export class OpenAPIParser {
|
|||
* returns map of definition pointer to definition name
|
||||
* @param $refs array of references to find derived from
|
||||
*/
|
||||
findDerived($refs: string[]): Dict<string> {
|
||||
const res: Dict<string> = {};
|
||||
findDerived($refs: string[]): Dict<string[] | string> {
|
||||
const res: Dict<string[]> = {};
|
||||
const schemas = (this.spec.components && this.spec.components.schemas) || {};
|
||||
for (const defName in schemas) {
|
||||
const def = this.deref(schemas[defName]);
|
||||
|
@ -305,7 +305,7 @@ export class OpenAPIParser {
|
|||
def.allOf !== undefined &&
|
||||
def.allOf.find(obj => obj.$ref !== undefined && $refs.indexOf(obj.$ref) > -1)
|
||||
) {
|
||||
res['#/components/schemas/' + defName] = def['x-discriminator-value'] || defName;
|
||||
res['#/components/schemas/' + defName] = [def['x-discriminator-value'] || defName];
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
|
|
@ -26,6 +26,8 @@ export interface RedocRawOptions {
|
|||
hideSingleRequestSampleTab?: boolean | string;
|
||||
menuToggle?: boolean | string;
|
||||
jsonSampleExpandLevel?: number | string | 'all';
|
||||
hideSchemaTitles?: boolean | string;
|
||||
payloadSampleIdx?: number;
|
||||
|
||||
providedByName?: string;
|
||||
providedByUri?: string;
|
||||
|
@ -43,12 +45,12 @@ export interface RedocRawOptions {
|
|||
expandDefaultServerVariables?: boolean;
|
||||
}
|
||||
|
||||
function argValueToBoolean(val?: string | boolean): boolean {
|
||||
function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean {
|
||||
if (val === undefined) {
|
||||
return false;
|
||||
return defaultValue || false;
|
||||
}
|
||||
if (typeof val === 'string') {
|
||||
return true;
|
||||
return val === 'false' ? false : true;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
@ -123,6 +125,18 @@ export class RedocNormalizedOptions {
|
|||
return value;
|
||||
}
|
||||
|
||||
static normalizePayloadSampleIdx(value: RedocRawOptions['payloadSampleIdx']): number {
|
||||
if (typeof value === 'number') {
|
||||
return Math.max(0, value); // always greater or equal than 0
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
return isFinite(value) ? parseInt(value, 10) : 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static normalizeJsonSampleExpandLevel(level?: number | string | 'all'): number {
|
||||
if (level === 'all') {
|
||||
return +Infinity;
|
||||
|
@ -151,6 +165,8 @@ export class RedocNormalizedOptions {
|
|||
menuToggle: boolean;
|
||||
jsonSampleExpandLevel: number;
|
||||
enumSkipQuotes: boolean;
|
||||
hideSchemaTitles: boolean;
|
||||
payloadSampleIdx: number;
|
||||
enableConsole: boolean;
|
||||
additionalHeaders: object;
|
||||
providedByName: string;
|
||||
|
@ -190,11 +206,13 @@ export class RedocNormalizedOptions {
|
|||
this.onlyRequiredInSamples = argValueToBoolean(raw.onlyRequiredInSamples);
|
||||
this.showExtensions = RedocNormalizedOptions.normalizeShowExtensions(raw.showExtensions);
|
||||
this.hideSingleRequestSampleTab = argValueToBoolean(raw.hideSingleRequestSampleTab);
|
||||
this.menuToggle = argValueToBoolean(raw.menuToggle);
|
||||
this.menuToggle = argValueToBoolean(raw.menuToggle, true);
|
||||
this.jsonSampleExpandLevel = RedocNormalizedOptions.normalizeJsonSampleExpandLevel(
|
||||
raw.jsonSampleExpandLevel,
|
||||
);
|
||||
this.enumSkipQuotes = argValueToBoolean(raw.enumSkipQuotes);
|
||||
this.hideSchemaTitles = argValueToBoolean(raw.hideSchemaTitles);
|
||||
this.payloadSampleIdx = RedocNormalizedOptions.normalizePayloadSampleIdx(raw.payloadSampleIdx);
|
||||
this.enableConsole = argValueToBoolean(raw.enableConsole);
|
||||
this.additionalHeaders = raw.additionalHeaders || {};
|
||||
this.providedByName = raw.providedByName || 'Documentation Powered by ReDoc';
|
||||
|
|
|
@ -38,6 +38,10 @@ export class SearchStore<T> {
|
|||
this.searchWorker.add(title, body, meta);
|
||||
}
|
||||
|
||||
dispose() {
|
||||
(this.searchWorker as any).terminate();
|
||||
}
|
||||
|
||||
search(q: string) {
|
||||
return this.searchWorker.search<T>(q);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import { SecuritySchemesModel } from './models/SecuritySchemes';
|
|||
import { OpenAPIParser } from './OpenAPIParser';
|
||||
import { RedocNormalizedOptions } from './RedocNormalizedOptions';
|
||||
/**
|
||||
* Store that containts all the specification related information in the form of tree
|
||||
* Store that contains all the specification related information in the form of tree
|
||||
*/
|
||||
export class SpecStore {
|
||||
parser: OpenAPIParser;
|
||||
|
|
|
@ -13,7 +13,7 @@ describe('History service', () => {
|
|||
expect(fn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('History subscribe should return unsubsribe function', () => {
|
||||
test('History subscribe should return unsubscribe function', () => {
|
||||
const fn = jest.fn();
|
||||
const unsubscribe = history.subscribe(fn);
|
||||
history.emit();
|
||||
|
|
|
@ -22,7 +22,7 @@ describe('Models', () => {
|
|||
expect(resp.type).toEqual('error');
|
||||
});
|
||||
|
||||
test('default should be sucessful by default', () => {
|
||||
test('default should be successful by default', () => {
|
||||
const resp = new ResponseModel(parser, 'default', false, {}, opts);
|
||||
expect(resp.type).toEqual('success');
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ export class ApiInfoModel implements OpenAPIInfo {
|
|||
constructor(private parser: OpenAPIParser) {
|
||||
Object.assign(this, parser.spec.info);
|
||||
this.description = parser.spec.info.description || '';
|
||||
|
||||
const firstHeadingLinePos = this.description.search(/^##?\s+/m);
|
||||
if (firstHeadingLinePos > -1) {
|
||||
this.description = this.description.substring(0, firstHeadingLinePos);
|
||||
|
|
|
@ -2,7 +2,7 @@ import { action, observable } from 'mobx';
|
|||
|
||||
import { OpenAPIExternalDocumentation, OpenAPITag } from '../../types';
|
||||
import { safeSlugify } from '../../utils';
|
||||
import { MarkdownHeading } from '../MarkdownRenderer';
|
||||
import { MarkdownHeading, MarkdownRenderer } from '../MarkdownRenderer';
|
||||
import { ContentItemModel } from '../MenuBuilder';
|
||||
import { IMenuItem, MenuItemGroupType } from '../MenuStore';
|
||||
|
||||
|
@ -43,9 +43,10 @@ export class GroupModel implements IMenuItem {
|
|||
|
||||
// remove sections from markdown, same as in ApiInfo
|
||||
this.description = tagOrGroup.description || '';
|
||||
const firstHeadingLinePos = this.description.search(/^##?\s+/m);
|
||||
if (firstHeadingLinePos > -1) {
|
||||
this.description = this.description.substring(0, firstHeadingLinePos);
|
||||
|
||||
const items = (tagOrGroup as MarkdownHeading).items;
|
||||
if (items && items.length) {
|
||||
this.description = MarkdownRenderer.getTextBeforeHading(this.description, items[0].name);
|
||||
}
|
||||
|
||||
this.parent = parent;
|
||||
|
|
|
@ -21,7 +21,7 @@ export class MediaContentModel {
|
|||
* @param isRequestType needed to know if skipe RO/RW fields in objects
|
||||
*/
|
||||
constructor(
|
||||
public parser: OpenAPIParser,
|
||||
parser: OpenAPIParser,
|
||||
info: Dict<OpenAPIMediaType>,
|
||||
public isRequestType: boolean,
|
||||
options: RedocNormalizedOptions,
|
||||
|
|
|
@ -27,9 +27,23 @@ import { ContentItemModel, ExtendedOpenAPIOperation } from '../MenuBuilder';
|
|||
import { OpenAPIParser } from '../OpenAPIParser';
|
||||
import { RedocNormalizedOptions } from '../RedocNormalizedOptions';
|
||||
import { FieldModel } from './Field';
|
||||
import { MediaContentModel } from './MediaContent';
|
||||
import { RequestBodyModel } from './RequestBody';
|
||||
import { ResponseModel } from './Response';
|
||||
|
||||
interface XPayloadSample {
|
||||
lang: 'payload';
|
||||
label: string;
|
||||
requestBodyContent: MediaContentModel;
|
||||
source: string;
|
||||
}
|
||||
|
||||
export function isPayloadSample(
|
||||
sample: XPayloadSample | OpenAPIXCodeSample,
|
||||
): sample is XPayloadSample {
|
||||
return sample.lang === 'payload' && (sample as any).requestBodyContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation model ready to be used by components
|
||||
*/
|
||||
|
@ -62,7 +76,6 @@ export class OperationModel implements IMenuItem {
|
|||
path: string;
|
||||
servers: OpenAPIServer[];
|
||||
security: SecurityRequirementModel[];
|
||||
codeSamples: OpenAPIXCodeSample[];
|
||||
extensions: Dict<any>;
|
||||
|
||||
constructor(
|
||||
|
@ -89,7 +102,6 @@ export class OperationModel implements IMenuItem {
|
|||
this.httpVerb = operationSpec.httpVerb;
|
||||
this.deprecated = !!operationSpec.deprecated;
|
||||
this.operationId = operationSpec.operationId;
|
||||
this.codeSamples = operationSpec['x-code-samples'] || [];
|
||||
this.path = operationSpec.pathName;
|
||||
|
||||
const pathInfo = parser.byRef<OpenAPIPath>(
|
||||
|
@ -144,6 +156,30 @@ export class OperationModel implements IMenuItem {
|
|||
);
|
||||
}
|
||||
|
||||
@memoize
|
||||
get codeSamples() {
|
||||
let samples: Array<OpenAPIXCodeSample | XPayloadSample> =
|
||||
this.operationSpec['x-code-samples'] || [];
|
||||
|
||||
const requestBodyContent = this.requestBody && this.requestBody.content;
|
||||
if (requestBodyContent && requestBodyContent.hasSample) {
|
||||
const insertInx = Math.min(samples.length, this.options.payloadSampleIdx);
|
||||
|
||||
samples = [
|
||||
...samples.slice(0, insertInx),
|
||||
{
|
||||
lang: 'payload',
|
||||
label: 'Payload',
|
||||
source: '',
|
||||
requestBodyContent,
|
||||
},
|
||||
...samples.slice(insertInx),
|
||||
];
|
||||
}
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
@memoize
|
||||
get parameters() {
|
||||
const _parameters = mergeParams(
|
||||
|
@ -154,11 +190,12 @@ export class OperationModel implements IMenuItem {
|
|||
).map(paramOrRef => new FieldModel(this.parser, paramOrRef, this.pointer, this.options));
|
||||
|
||||
if (this.options.sortPropsAlphabetically) {
|
||||
sortByField(_parameters, 'name');
|
||||
return sortByField(_parameters, 'name');
|
||||
}
|
||||
if (this.options.requiredPropsFirst) {
|
||||
sortByRequired(_parameters);
|
||||
return sortByRequired(_parameters);
|
||||
}
|
||||
|
||||
return _parameters;
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ export class SchemaModel {
|
|||
this.pointer = schemaOrRef.$ref || pointer || '';
|
||||
this.rawSchema = parser.deref(schemaOrRef);
|
||||
this.schema = parser.mergeAllOf(this.rawSchema, this.pointer, isChild);
|
||||
|
||||
this.init(parser, isChild);
|
||||
|
||||
parser.exitRef(schemaOrRef);
|
||||
|
@ -125,6 +126,13 @@ export class SchemaModel {
|
|||
if (!isChild && getDiscriminator(schema) !== undefined) {
|
||||
this.initDiscriminator(schema, parser);
|
||||
return;
|
||||
} else if (
|
||||
isChild &&
|
||||
Array.isArray(schema.oneOf) &&
|
||||
schema.oneOf.find(s => s.$ref === this.pointer)
|
||||
) {
|
||||
// we hit allOf of the schema with the parent discriminator
|
||||
delete schema.oneOf;
|
||||
}
|
||||
|
||||
if (schema.oneOf !== undefined) {
|
||||
|
@ -216,7 +224,10 @@ export class SchemaModel {
|
|||
) {
|
||||
const discriminator = getDiscriminator(schema)!;
|
||||
this.discriminatorProp = discriminator.propertyName;
|
||||
const derived = parser.findDerived([...(schema.parentRefs || []), this.pointer]);
|
||||
const implicitInversedMapping = parser.findDerived([
|
||||
...(schema.parentRefs || []),
|
||||
this.pointer,
|
||||
]);
|
||||
|
||||
if (schema.oneOf) {
|
||||
for (const variant of schema.oneOf) {
|
||||
|
@ -224,19 +235,41 @@ export class SchemaModel {
|
|||
continue;
|
||||
}
|
||||
const name = JsonPointer.baseName(variant.$ref);
|
||||
derived[variant.$ref] = name;
|
||||
implicitInversedMapping[variant.$ref] = name;
|
||||
}
|
||||
}
|
||||
|
||||
const mapping = discriminator.mapping || {};
|
||||
const explicitInversedMapping = {};
|
||||
for (const name in mapping) {
|
||||
derived[mapping[name]] = name;
|
||||
const $ref = mapping[name];
|
||||
|
||||
if (Array.isArray(explicitInversedMapping[$ref])) {
|
||||
explicitInversedMapping[$ref].push(name);
|
||||
} else {
|
||||
// overrides implicit mapping here
|
||||
explicitInversedMapping[$ref] = [name];
|
||||
}
|
||||
}
|
||||
|
||||
const refs = Object.keys(derived);
|
||||
this.oneOf = refs.map(ref => {
|
||||
const innerSchema = new SchemaModel(parser, parser.byRef(ref)!, ref, this.options, true);
|
||||
innerSchema.title = derived[ref];
|
||||
const inversedMapping = { ...implicitInversedMapping, ...explicitInversedMapping };
|
||||
|
||||
const refs: Array<{ $ref; name }> = [];
|
||||
|
||||
for (const $ref of Object.keys(inversedMapping)) {
|
||||
const names = inversedMapping[$ref];
|
||||
if (Array.isArray(names)) {
|
||||
for (const name of names) {
|
||||
refs.push({ $ref, name });
|
||||
}
|
||||
} else {
|
||||
refs.push({ $ref, name: names });
|
||||
}
|
||||
}
|
||||
|
||||
this.oneOf = refs.map(({ $ref, name }) => {
|
||||
const innerSchema = new SchemaModel(parser, parser.byRef($ref)!, $ref, this.options, true);
|
||||
innerSchema.title = name;
|
||||
return innerSchema;
|
||||
});
|
||||
}
|
||||
|
@ -251,7 +284,7 @@ function buildFields(
|
|||
const props = schema.properties || {};
|
||||
const additionalProps = schema.additionalProperties;
|
||||
const defaults = schema.default || {};
|
||||
const fields = Object.keys(props || []).map(fieldName => {
|
||||
let fields = Object.keys(props || []).map(fieldName => {
|
||||
let field = props[fieldName];
|
||||
|
||||
if (!field) {
|
||||
|
@ -280,11 +313,11 @@ function buildFields(
|
|||
});
|
||||
|
||||
if (options.sortPropsAlphabetically) {
|
||||
sortByField(fields, 'name');
|
||||
fields = sortByField(fields, 'name');
|
||||
}
|
||||
if (options.requiredPropsFirst) {
|
||||
// if not sort alphabetically sort in the order from required keyword
|
||||
sortByRequired(fields, !options.sortPropsAlphabetically ? schema.required : undefined);
|
||||
fields = sortByRequired(fields, !options.sortPropsAlphabetically ? schema.required : undefined);
|
||||
}
|
||||
|
||||
if (typeof additionalProps === 'object' || additionalProps === true) {
|
||||
|
|
|
@ -126,6 +126,10 @@ const defaultTheme: ThemeInterface = {
|
|||
width: '260px',
|
||||
backgroundColor: '#fafafa',
|
||||
textColor: '#333333',
|
||||
activeTextColor: theme =>
|
||||
theme.menu.textColor !== defaultTheme.menu!.textColor
|
||||
? theme.menu.textColor
|
||||
: theme.colors.primary.main,
|
||||
groupItems: {
|
||||
textTransform: 'uppercase',
|
||||
},
|
||||
|
@ -302,6 +306,7 @@ export interface ResolvedThemeInterface {
|
|||
width: string;
|
||||
backgroundColor: string;
|
||||
textColor: string;
|
||||
activeTextColor: string;
|
||||
groupItems: {
|
||||
textTransform: string;
|
||||
};
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
normalizeServers,
|
||||
pluralizeType,
|
||||
serializeParameterValue,
|
||||
sortByRequired,
|
||||
} from '../';
|
||||
|
||||
import { FieldModel, OpenAPIParser, RedocNormalizedOptions } from '../../services';
|
||||
|
@ -249,7 +250,7 @@ describe('Utils', () => {
|
|||
expect(res).toEqual([{ url: 'http://base.com/sandbox/test', description: '' }]);
|
||||
});
|
||||
|
||||
it('should correcly resolve url with server relative path', () => {
|
||||
it('should correctly resolve url with server relative path', () => {
|
||||
const res = normalizeServers('http://base.com/subpath/spec.yaml', [
|
||||
{
|
||||
url: '/sandbox/test',
|
||||
|
@ -258,7 +259,7 @@ describe('Utils', () => {
|
|||
expect(res).toEqual([{ url: 'http://base.com/sandbox/test', description: '' }]);
|
||||
});
|
||||
|
||||
it('should correcly resolve url with relative path', () => {
|
||||
it('should correctly resolve url with relative path', () => {
|
||||
const res = normalizeServers('http://base.com/subpath/spec.yaml', [
|
||||
{
|
||||
url: 'sandbox/test',
|
||||
|
@ -333,7 +334,8 @@ describe('Utils', () => {
|
|||
const itemConstraintSchema = (
|
||||
min: number | undefined = undefined,
|
||||
max: number | undefined = undefined,
|
||||
) => ({ type: 'array', minItems: min, maxItems: max });
|
||||
multipleOf: number | undefined = undefined,
|
||||
) => ({ type: 'array', minItems: min, maxItems: max, multipleOf });
|
||||
|
||||
it('should not have a humanized constraint without schema constraints', () => {
|
||||
expect(humanizeConstraints(itemConstraintSchema())).toHaveLength(0);
|
||||
|
@ -355,9 +357,21 @@ describe('Utils', () => {
|
|||
expect(humanizeConstraints(itemConstraintSchema(7, 7))).toContain('7 items');
|
||||
});
|
||||
|
||||
it('should have a humazined constraint when justMinItems is set, and it is equal to 1', () => {
|
||||
it('should have a humanized constraint when justMinItems is set, and it is equal to 1', () => {
|
||||
expect(humanizeConstraints(itemConstraintSchema(1))).toContain('non-empty');
|
||||
});
|
||||
|
||||
it('should have a humanized constraint when multipleOf is set, and it is in format of /^0\\.0*1$/', () => {
|
||||
expect(humanizeConstraints(itemConstraintSchema(undefined, undefined, 0.01))).toContain(
|
||||
'decimal places <= 2',
|
||||
);
|
||||
});
|
||||
|
||||
it('should have a humanized constraint when multipleOf is set, and it is in format other than /^0\\.0*1$/', () => {
|
||||
expect(humanizeConstraints(itemConstraintSchema(undefined, undefined, 0.5))).toContain(
|
||||
'multiple of 0.5',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('OpenAPI pluralizeType', () => {
|
||||
|
@ -370,17 +384,27 @@ describe('Utils', () => {
|
|||
expect(pluralizeType('array')).toEqual('arrays');
|
||||
});
|
||||
|
||||
it('should pluralize complex dislay types', () => {
|
||||
it('should pluralize complex display types', () => {
|
||||
expect(pluralizeType('object (Pet)')).toEqual('objects (Pet)');
|
||||
expect(pluralizeType('string <email>')).toEqual('strings <email>');
|
||||
});
|
||||
|
||||
it('should pluralize oneOf-ed dislay types', () => {
|
||||
it('should pluralize oneOf-ed display types', () => {
|
||||
expect(pluralizeType('object or string')).toEqual('objects or strings');
|
||||
expect(pluralizeType('object (Pet) or number <int64>')).toEqual(
|
||||
'objects (Pet) or numbers <int64>',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not pluralize display types that are already pluralized', () => {
|
||||
expect(pluralizeType('strings')).toEqual('strings');
|
||||
expect(pluralizeType('objects (Pet)')).toEqual('objects (Pet)');
|
||||
expect(pluralizeType('strings <email>')).toEqual('strings <email>');
|
||||
expect(pluralizeType('objects or strings')).toEqual('objects or strings');
|
||||
expect(pluralizeType('objects (Pet) or numbers <int64>')).toEqual(
|
||||
'objects (Pet) or numbers <int64>',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('openapi serializeParameter', () => {
|
||||
|
@ -613,4 +637,370 @@ describe('Utils', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('OpenAPI sortByRequired', () => {
|
||||
it('should equal to the old data when all items have no required props', () => {
|
||||
let fields = [
|
||||
{
|
||||
name: 'loginName',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'displayName',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'space',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depIds',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depNames',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'pwdControl',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'csfLevel',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'siteId',
|
||||
required: false,
|
||||
},
|
||||
];
|
||||
expect(sortByRequired(fields as FieldModel[])).toEqual(fields);
|
||||
});
|
||||
|
||||
it('other item should be the same order when some of items are required', () => {
|
||||
let fields = [
|
||||
{
|
||||
name: 'loginName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'displayName',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'space',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depIds',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depNames',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'pwdControl',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'csfLevel',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'siteId',
|
||||
required: false,
|
||||
},
|
||||
];
|
||||
let sortedFields = [
|
||||
{
|
||||
name: 'loginName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'displayName',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'space',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depIds',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depNames',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'pwdControl',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'csfLevel',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'siteId',
|
||||
required: false,
|
||||
},
|
||||
];
|
||||
expect(sortByRequired(fields as FieldModel[])).toEqual(sortedFields);
|
||||
});
|
||||
|
||||
it('should the order of required items is as same as the order parameter ', () => {
|
||||
let fields = [
|
||||
{
|
||||
name: 'loginName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'displayName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'space',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depIds',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depNames',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'pwdControl',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'csfLevel',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'siteId',
|
||||
required: false,
|
||||
},
|
||||
];
|
||||
expect(
|
||||
sortByRequired(fields as FieldModel[], ['siteId', 'displayName', 'loginName', 'email']),
|
||||
).toEqual([
|
||||
{
|
||||
name: 'displayName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'loginName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'space',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depIds',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depNames',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'pwdControl',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'csfLevel',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'siteId',
|
||||
required: false,
|
||||
},
|
||||
]);
|
||||
expect(sortByRequired(fields as FieldModel[], ['email', 'displayName'])).toEqual([
|
||||
{
|
||||
name: 'email',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'displayName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'loginName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'space',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depIds',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depNames',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'pwdControl',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'csfLevel',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'siteId',
|
||||
required: false,
|
||||
},
|
||||
]);
|
||||
|
||||
expect(sortByRequired(fields as FieldModel[], ['displayName'])).toEqual([
|
||||
{
|
||||
name: 'displayName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'loginName',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'email',
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'space',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'type',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depIds',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'depNames',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'password',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'pwdControl',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'csfLevel',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'priority',
|
||||
required: false,
|
||||
},
|
||||
{
|
||||
name: 'siteId',
|
||||
required: false,
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -2,7 +2,7 @@ import slugify from 'slugify';
|
|||
import { format, parse } from 'url';
|
||||
|
||||
/**
|
||||
* Maps over array passing `isLast` bool to iterator as the second arguemnt
|
||||
* Maps over array passing `isLast` bool to iterator as the second argument
|
||||
*/
|
||||
export function mapWithLast<T, P>(array: T[], iteratee: (item: T, isLast: boolean) => P) {
|
||||
const res: P[] = [];
|
||||
|
@ -118,7 +118,7 @@ const isMergebleObject = (item): boolean => {
|
|||
|
||||
/**
|
||||
* slugify() returns empty string when failed to slugify.
|
||||
* so try to return minimun slugified-string with failed one which keeps original value
|
||||
* so try to return minimum slugified-string with failed one which keeps original value
|
||||
* the regex codes are referenced with https://gist.github.com/mathewbyrne/1280286
|
||||
*/
|
||||
export function safeSlugify(value: string): string {
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'prismjs/components/prism-coffeescript.js';
|
|||
import 'prismjs/components/prism-cpp.js';
|
||||
import 'prismjs/components/prism-csharp.js';
|
||||
import 'prismjs/components/prism-go.js';
|
||||
import 'prismjs/components/prism-http.js';
|
||||
import 'prismjs/components/prism-java.js';
|
||||
import 'prismjs/components/prism-lua.js';
|
||||
import 'prismjs/components/prism-markup-templating.js'; // dep of php
|
||||
|
@ -65,7 +66,7 @@ export function mapLang(lang: string): string {
|
|||
* Highlight source code string using Prism.js
|
||||
* @param source source code to highlight
|
||||
* @param lang highlight language
|
||||
* @return highlighted souce code as **html string**
|
||||
* @return highlighted source code as **html string**
|
||||
*/
|
||||
export function highlight(source: string, lang: string = DEFAULT_LANG): string {
|
||||
lang = lang.toLowerCase();
|
||||
|
|
|
@ -4,7 +4,9 @@ export function jsonToHTML(json, maxExpandLevel) {
|
|||
level = 1;
|
||||
let output = '';
|
||||
output += '<div class="redoc-json">';
|
||||
output += '<code>';
|
||||
output += valueToHTML(json, maxExpandLevel);
|
||||
output += '</code>';
|
||||
output += '</div>';
|
||||
return output;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { dirname } from 'path';
|
||||
const URLtemplate = require('url-template');
|
||||
|
||||
import { FieldModel } from '../services/models';
|
||||
import { OpenAPIParser } from '../services/OpenAPIParser';
|
||||
import {
|
||||
OpenAPIEncoding,
|
||||
|
@ -13,7 +14,7 @@ import {
|
|||
Referenced,
|
||||
} from '../types';
|
||||
import { IS_BROWSER } from './dom';
|
||||
import { isNumeric, removeQueryString, resolveUrl, stripTrailingSlash } from './helpers';
|
||||
import { isNumeric, removeQueryString, resolveUrl } from './helpers';
|
||||
|
||||
function isWildcardStatusCode(statusCode: string | number): statusCode is string {
|
||||
return typeof statusCode === 'string' && /\dxx/i.test(statusCode);
|
||||
|
@ -137,13 +138,13 @@ export function isFormUrlEncoded(contentType: string): boolean {
|
|||
return contentType === 'application/x-www-form-urlencoded';
|
||||
}
|
||||
|
||||
function delimitedEncodeField(fieldVal: any, fieldName: string, delimeter: string): string {
|
||||
function delimitedEncodeField(fieldVal: any, fieldName: string, delimiter: string): string {
|
||||
if (Array.isArray(fieldVal)) {
|
||||
return fieldVal.map(v => v.toString()).join(delimeter);
|
||||
return fieldVal.map(v => v.toString()).join(delimiter);
|
||||
} else if (typeof fieldVal === 'object') {
|
||||
return Object.keys(fieldVal)
|
||||
.map(k => `${k}${delimeter}${fieldVal[k]}`)
|
||||
.join(delimeter);
|
||||
.map(k => `${k}${delimiter}${fieldVal[k]}`)
|
||||
.join(delimiter);
|
||||
} else {
|
||||
return fieldName + '=' + fieldVal.toString();
|
||||
}
|
||||
|
@ -165,7 +166,7 @@ function deepObjectEncodeField(fieldVal: any, fieldName: string): string {
|
|||
|
||||
function serializeFormValue(name: string, explode: boolean, value: any) {
|
||||
// Use RFC6570 safe name ([a-zA-Z0-9_]) and replace with our name later
|
||||
// e.g. URI.template doesn't parse names with hypen (-) which are valid query param names
|
||||
// e.g. URI.template doesn't parse names with hyphen (-) which are valid query param names
|
||||
const safeName = '__redoc_param_name__';
|
||||
const suffix = explode ? '*' : '';
|
||||
const template = URLtemplate.parse(`{?${safeName}${suffix}}`);
|
||||
|
@ -177,7 +178,7 @@ function serializeFormValue(name: string, explode: boolean, value: any) {
|
|||
|
||||
/*
|
||||
* Should be used only for url-form-encoded body payloads
|
||||
* To be used for parmaters should be extended with other style values
|
||||
* To be used for parameters should be extended with other style values
|
||||
*/
|
||||
export function urlFormEncodePayload(
|
||||
payload: object,
|
||||
|
@ -225,7 +226,7 @@ function serializePathParameter(
|
|||
}
|
||||
|
||||
// Use RFC6570 safe name ([a-zA-Z0-9_]) and replace with our name later
|
||||
// e.g. URI.template doesn't parse names with hypen (-) which are valid query param names
|
||||
// e.g. URI.template doesn't parse names with hyphen (-) which are valid query param names
|
||||
const safeName = '__redoc_param_name__';
|
||||
const template = URLtemplate.parse(`{${prefix}${safeName}${suffix}}`);
|
||||
|
||||
|
@ -368,6 +369,17 @@ export function isNamedDefinition(pointer?: string): boolean {
|
|||
return /^#\/components\/schemas\/[^\/]+$/.test(pointer || '');
|
||||
}
|
||||
|
||||
function humanizeMultipleOfConstraint(multipleOf: number | undefined): string | undefined {
|
||||
if (multipleOf === undefined) {
|
||||
return;
|
||||
}
|
||||
const strigifiedMultipleOf = multipleOf.toString(10);
|
||||
if (!/^0\.0*1$/.test(strigifiedMultipleOf)) {
|
||||
return `multiple of ${strigifiedMultipleOf}`;
|
||||
}
|
||||
return `decimal places <= ${strigifiedMultipleOf.split('.')[1].length}`;
|
||||
}
|
||||
|
||||
function humanizeRangeConstraint(
|
||||
description: string,
|
||||
min: number | undefined,
|
||||
|
@ -406,6 +418,11 @@ export function humanizeConstraints(schema: OpenAPISchema): string[] {
|
|||
res.push(arrayRange);
|
||||
}
|
||||
|
||||
const multipleOfConstraint = humanizeMultipleOfConstraint(schema.multipleOf);
|
||||
if (multipleOfConstraint !== undefined) {
|
||||
res.push(multipleOfConstraint);
|
||||
}
|
||||
|
||||
let numberRange;
|
||||
if (schema.minimum !== undefined && schema.maximum !== undefined) {
|
||||
numberRange = schema.exclusiveMinimum ? '( ' : '[ ';
|
||||
|
@ -428,25 +445,29 @@ export function humanizeConstraints(schema: OpenAPISchema): string[] {
|
|||
return res;
|
||||
}
|
||||
|
||||
export function sortByRequired(
|
||||
fields: Array<{ required: boolean; name: string }>,
|
||||
order: string[] = [],
|
||||
) {
|
||||
fields.sort((a, b) => {
|
||||
if (!a.required && b.required) {
|
||||
return 1;
|
||||
} else if (a.required && !b.required) {
|
||||
return -1;
|
||||
} else if (a.required && b.required) {
|
||||
return order.indexOf(a.name) - order.indexOf(b.name);
|
||||
export function sortByRequired(fields: FieldModel[], order: string[] = []) {
|
||||
const unrequiredFields: FieldModel[] = [];
|
||||
const orderedFields: FieldModel[] = [];
|
||||
const unorderedFields: FieldModel[] = [];
|
||||
|
||||
fields.forEach(field => {
|
||||
if (field.required) {
|
||||
order.includes(field.name) ? orderedFields.push(field) : unorderedFields.push(field);
|
||||
} else {
|
||||
return 0;
|
||||
unrequiredFields.push(field);
|
||||
}
|
||||
});
|
||||
|
||||
orderedFields.sort((a, b) => order.indexOf(a.name) - order.indexOf(b.name));
|
||||
|
||||
return [...orderedFields, ...unorderedFields, ...unrequiredFields];
|
||||
}
|
||||
|
||||
export function sortByField<T extends string>(fields: Array<{ [P in T]: string }>, param: T) {
|
||||
fields.sort((a, b) => {
|
||||
export function sortByField(
|
||||
fields: FieldModel[],
|
||||
param: keyof Pick<FieldModel, 'name' | 'description' | 'kind'>,
|
||||
) {
|
||||
return [...fields].sort((a, b) => {
|
||||
return a[param].localeCompare(b[param]);
|
||||
});
|
||||
}
|
||||
|
@ -462,7 +483,7 @@ export function mergeParams(
|
|||
operationParamNames[param.name + '_' + param.in] = true;
|
||||
});
|
||||
|
||||
// filter out path params overriden by operation ones with the same name
|
||||
// filter out path params overridden by operation ones with the same name
|
||||
pathParams = pathParams.filter(param => {
|
||||
param = parser.shalowDeref(param);
|
||||
return !operationParamNames[param.name + '_' + param.in];
|
||||
|
@ -509,9 +530,10 @@ export function normalizeServers(
|
|||
const baseUrl = specUrl === undefined ? removeQueryString(getHref()) : dirname(specUrl);
|
||||
|
||||
if (servers.length === 0) {
|
||||
return [
|
||||
// Behaviour defined in OpenAPI spec: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#openapi-object
|
||||
servers = [
|
||||
{
|
||||
url: stripTrailingSlash(baseUrl),
|
||||
url: '/',
|
||||
},
|
||||
];
|
||||
}
|
||||
|
@ -579,6 +601,6 @@ export function extractExtensions(obj: object, showExtensions: string[] | true):
|
|||
export function pluralizeType(displayType: string): string {
|
||||
return displayType
|
||||
.split(' or ')
|
||||
.map(type => type.replace(/^(string|object|number|integer|array|boolean)( ?.*)/, '$1s$2'))
|
||||
.map(type => type.replace(/^(string|object|number|integer|array|boolean)s?( ?.*)/, '$1s$2'))
|
||||
.join(' or ');
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
"e2e/**"
|
||||
],
|
||||
"include": [
|
||||
"cli/index.ts",
|
||||
"./custom.d.ts",
|
||||
"./demo/playground/hmr-playground.tsx",
|
||||
"./src/**/*.ts?",
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
"quotemark": [true, "single", "avoid-template", "jsx-double"],
|
||||
"variable-name": [true, "ban-keywords", "check-format", "allow-leading-underscore", "allow-pascal-case"],
|
||||
"arrow-parens": [true, "ban-single-arg-parens"],
|
||||
"no-submodule-imports": [true, "prismjs", "perfect-scrollbar", "react-dom", "core-js", "brace"],
|
||||
"no-submodule-imports": [true, "prismjs", "perfect-scrollbar", "react-dom", "core-js", "brace", "memoize-one"],
|
||||
"object-literal-key-quotes": [true, "as-needed"],
|
||||
"no-unused-expression": [true, "allow-tagged-template"],
|
||||
"semicolon": [true, "always", "ignore-bound-class-methods"],
|
||||
|
|
|
@ -5,7 +5,7 @@ import * as webpack from 'webpack';
|
|||
import * as path from 'path';
|
||||
|
||||
const nodeExternals = require('webpack-node-externals')({
|
||||
// bundle in moudules that need transpiling + non-js (e.g. css)
|
||||
// bundle in modules that need transpiling + non-js (e.g. css)
|
||||
whitelist: [
|
||||
'swagger2openapi',
|
||||
/reftools/,
|
||||
|
|
Loading…
Reference in New Issue
Block a user