@@ -1984,7 +2008,7 @@ details.
- All JSight repositories: https://github.com/jsightapi.
- GitHub discussions: https://github.com/jsightapi/online-editor-frontend/discussions.
-- JSight video lessons:
+- JSight Youtube:
https://www.youtube.com/watch?v=AegCETY9Cdk&list=PLy9sOecVhlybvRoDhGlzyMwKVxR-gFkdX
diff --git a/docker-compose.yml b/docker-compose.yml
index 2507bef..3bb4b31 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -11,7 +11,7 @@ services:
- '${FE_HOST_PORT}:80'
jsight-server:
- image: jsight/jsight-server:4
+ image: jsight/jsight-server:6.0
environment:
- JSIGHT_SERVER_CORS=true
- JSIGHT_SERVER_STATISTICS
diff --git a/img/openapi.gif b/img/openapi.gif
new file mode 100644
index 0000000..409a093
Binary files /dev/null and b/img/openapi.gif differ
diff --git a/jsight-server-docker-compose.yml b/jsight-server-docker-compose.yml
index c65fe98..a17ba38 100644
--- a/jsight-server-docker-compose.yml
+++ b/jsight-server-docker-compose.yml
@@ -1,7 +1,7 @@
version: '3.8'
services:
jsight-server:
- image: jsight/jsight-server:4
+ image: jsight/jsight-server:6.0
environment:
- JSIGHT_SERVER_CORS=true
- JSIGHT_SERVER_STATISTICS
diff --git a/package-lock.json b/package-lock.json
index 52b6ff3..b3e3146 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -16,17 +16,17 @@
"monaco-editor": "0.31.1",
"re-resizable": "6.9.1",
"react": "^18.1.0",
- "react-collapse": "5.1.1",
- "react-collapsed": "3.3.0",
+ "react-animate-height": "2.1.2",
"react-dom": "^18.1.0",
"react-gtm-module": "2.0.11",
+ "react-helmet": "6.1.0",
"react-intersection-observer": "8.32.5",
"react-modal": "3.14.4",
"react-popper": "2.2.5",
"react-router-dom": "5.3.0",
"react-scripts": "5.0.0",
"react-scroll": "1.8.4",
- "react-toastify": "8.1.0",
+ "react-toastify": "9.0.1",
"react-transition-group": "4.4.2",
"react-virtuoso": "2.7.1",
"sanitize-html": "2.7.0",
@@ -46,6 +46,7 @@
"@types/react-collapse": "5.0.1",
"@types/react-dom": "17.0.14",
"@types/react-gtm-module": "2.0.1",
+ "@types/react-helmet": "^6.1.5",
"@types/react-modal": "3.13.1",
"@types/react-router-dom": "5.3.1",
"@types/react-transition-group": "4.4.4",
@@ -3469,6 +3470,15 @@
"integrity": "sha512-T/DN9gAbCYk5wJ1nxf4pSwmXz4d1iVjM++OoG+mwMfz9STMAotGjSb65gJHOS5bPvl6vLSsJnuC+y/43OQrltg==",
"dev": true
},
+ "node_modules/@types/react-helmet": {
+ "version": "6.1.11",
+ "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.11.tgz",
+ "integrity": "sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/react-modal": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.13.1.tgz",
@@ -5085,6 +5095,11 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
},
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
+ },
"node_modules/clean-css": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz",
@@ -12898,6 +12913,22 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-animate-height": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/react-animate-height/-/react-animate-height-2.1.2.tgz",
+ "integrity": "sha512-A9jfz/4CTdsIsE7WCQtO9UkOpMBcBRh8LxyHl2eoZz1ki02jpyUL5xt58gabd0CyeLQ8fRyQ+s2lyV2Ufu8Owg==",
+ "dependencies": {
+ "classnames": "^2.2.5",
+ "prop-types": "^15.6.1"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=15.6.2",
+ "react-dom": ">=15.6.2"
+ }
+ },
"node_modules/react-app-polyfill": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz",
@@ -12938,30 +12969,6 @@
"semver": "bin/semver"
}
},
- "node_modules/react-collapse": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/react-collapse/-/react-collapse-5.1.1.tgz",
- "integrity": "sha512-k6cd7csF1o9LBhQ4AGBIdxB60SUEUMQDAnL2z1YvYNr9KoKr+nDkhN6FK7uGaBd/rYrYfrMpzpmJEIeHRYogBw==",
- "peerDependencies": {
- "react": ">=16.3.0"
- }
- },
- "node_modules/react-collapsed": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/react-collapsed/-/react-collapsed-3.3.0.tgz",
- "integrity": "sha512-2oXo9xsleo3ZwmNP7GymWbkZp2SwDZImLduy1LKgQMsqZTDldyzP2GnfvYb9vyGFDYHRYFhnWlwDmG2yWkt8eQ==",
- "dependencies": {
- "raf": "^3.4.1",
- "tiny-warning": "^1.0.3"
- },
- "engines": {
- "node": ">=12"
- },
- "peerDependencies": {
- "react": ">=16.8",
- "react-dom": ">=16.8"
- }
- },
"node_modules/react-dev-utils": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
@@ -13096,6 +13103,20 @@
"resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz",
"integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw=="
},
+ "node_modules/react-helmet": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
+ "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.7.2",
+ "react-fast-compare": "^3.1.1",
+ "react-side-effect": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.3.0"
+ }
+ },
"node_modules/react-intersection-observer": {
"version": "8.32.5",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.32.5.tgz",
@@ -13593,10 +13614,18 @@
"react-dom": "^15.5.4 || ^16.0.0 || ^17.0.0"
}
},
+ "node_modules/react-side-effect": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
+ "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==",
+ "peerDependencies": {
+ "react": "^16.3.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/react-toastify": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-8.1.0.tgz",
- "integrity": "sha512-M+Q3rTmEw/53Csr7NsV/YnldJe4c7uERcY7Tma9mvLU98QT2VhIkKwjBzzxZkJRk/oBKyUAtkyMjMgO00hx6gQ==",
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.0.1.tgz",
+ "integrity": "sha512-c2zeZHkCX+WXuItS/JRqQ/8CH8Qm/je+M0rt09xe9fnu5YPJigtNOdD8zX4fwLA093V2am3abkGfOowwpkrwOQ==",
"dependencies": {
"clsx": "^1.1.1"
},
@@ -18831,6 +18860,15 @@
"integrity": "sha512-T/DN9gAbCYk5wJ1nxf4pSwmXz4d1iVjM++OoG+mwMfz9STMAotGjSb65gJHOS5bPvl6vLSsJnuC+y/43OQrltg==",
"dev": true
},
+ "@types/react-helmet": {
+ "version": "6.1.11",
+ "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.11.tgz",
+ "integrity": "sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/react-modal": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/@types/react-modal/-/react-modal-3.13.1.tgz",
@@ -20033,6 +20071,11 @@
"resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz",
"integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA=="
},
+ "classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
+ },
"clean-css": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.0.tgz",
@@ -25606,6 +25649,15 @@
"loose-envify": "^1.1.0"
}
},
+ "react-animate-height": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/react-animate-height/-/react-animate-height-2.1.2.tgz",
+ "integrity": "sha512-A9jfz/4CTdsIsE7WCQtO9UkOpMBcBRh8LxyHl2eoZz1ki02jpyUL5xt58gabd0CyeLQ8fRyQ+s2lyV2Ufu8Owg==",
+ "requires": {
+ "classnames": "^2.2.5",
+ "prop-types": "^15.6.1"
+ }
+ },
"react-app-polyfill": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-3.0.0.tgz",
@@ -25636,20 +25688,6 @@
}
}
},
- "react-collapse": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/react-collapse/-/react-collapse-5.1.1.tgz",
- "integrity": "sha512-k6cd7csF1o9LBhQ4AGBIdxB60SUEUMQDAnL2z1YvYNr9KoKr+nDkhN6FK7uGaBd/rYrYfrMpzpmJEIeHRYogBw=="
- },
- "react-collapsed": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/react-collapsed/-/react-collapsed-3.3.0.tgz",
- "integrity": "sha512-2oXo9xsleo3ZwmNP7GymWbkZp2SwDZImLduy1LKgQMsqZTDldyzP2GnfvYb9vyGFDYHRYFhnWlwDmG2yWkt8eQ==",
- "requires": {
- "raf": "^3.4.1",
- "tiny-warning": "^1.0.3"
- }
- },
"react-dev-utils": {
"version": "12.0.0",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.0.tgz",
@@ -25750,6 +25788,17 @@
"resolved": "https://registry.npmjs.org/react-gtm-module/-/react-gtm-module-2.0.11.tgz",
"integrity": "sha512-8gyj4TTxeP7eEyc2QKawEuQoAZdjKvMY4pgWfycGmqGByhs17fR+zEBs0JUDq4US/l+vbTl+6zvUIx27iDo/Vw=="
},
+ "react-helmet": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
+ "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
+ "requires": {
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.7.2",
+ "react-fast-compare": "^3.1.1",
+ "react-side-effect": "^2.1.0"
+ }
+ },
"react-intersection-observer": {
"version": "8.32.5",
"resolved": "https://registry.npmjs.org/react-intersection-observer/-/react-intersection-observer-8.32.5.tgz",
@@ -26116,10 +26165,15 @@
"prop-types": "^15.7.2"
}
},
+ "react-side-effect": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
+ "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw=="
+ },
"react-toastify": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-8.1.0.tgz",
- "integrity": "sha512-M+Q3rTmEw/53Csr7NsV/YnldJe4c7uERcY7Tma9mvLU98QT2VhIkKwjBzzxZkJRk/oBKyUAtkyMjMgO00hx6gQ==",
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.0.1.tgz",
+ "integrity": "sha512-c2zeZHkCX+WXuItS/JRqQ/8CH8Qm/je+M0rt09xe9fnu5YPJigtNOdD8zX4fwLA093V2am3abkGfOowwpkrwOQ==",
"requires": {
"clsx": "^1.1.1"
}
diff --git a/package.json b/package.json
index 73269ac..eb1f821 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
"web-vitals": "1.0.1",
"yaml": "1.10.2"
},
+ "proxy": "https://dev.editor.jsight.io",
"scripts": {
"start": "react-app-rewired start",
"one": "./scripts/save-export-js.sh",
diff --git a/src/api/baseUrl.ts b/src/api/baseUrl.ts
new file mode 100644
index 0000000..380ca74
--- /dev/null
+++ b/src/api/baseUrl.ts
@@ -0,0 +1,3 @@
+export const baseUrl = process.env.REACT_APP_API_URL || `${window.location.origin}`;
+
+export const convertJsightUrl = `${baseUrl}/convert-jsight`;
diff --git a/src/api/codeSharing.ts b/src/api/codeSharing.ts
index 4d3e71f..7f17a9f 100644
--- a/src/api/codeSharing.ts
+++ b/src/api/codeSharing.ts
@@ -31,7 +31,11 @@ export const createNewState = (content: string) => {
},
};
- return runRequest
(`${cloudUrl}/item`, {body: JSON.stringify(item)}, 5000);
+ return runRequest(
+ `${cloudUrl}/item`,
+ {body: JSON.stringify(item)},
+ {timeout: 5000}
+ );
};
export const updateState = (code: string, content: string) => {
@@ -46,7 +50,7 @@ export const updateState = (code: string, content: string) => {
return runRequest(
`${cloudUrl}/item/${code}`,
{body: JSON.stringify(item)},
- 5000
+ {timeout: 5000}
);
};
diff --git a/src/api/getJDocExchange.ts b/src/api/convert.ts
similarity index 54%
rename from src/api/getJDocExchange.ts
rename to src/api/convert.ts
index c52cf93..fbffafa 100644
--- a/src/api/getJDocExchange.ts
+++ b/src/api/convert.ts
@@ -1,10 +1,8 @@
import {runRequest} from 'utils/runRequest';
-import {JDocType} from 'types/exchange';
import {v4 as uuidv4} from 'uuid';
+import {convertJsightUrl} from './baseUrl';
-export const baseUrlApi = process.env.REACT_APP_API_URL || `${window.location.origin}/api`;
-
-export const getJDocExchange = (body: string) => {
+export const convert = (body = '', format: string) => {
const uuid = localStorage.getItem('uuid') || '';
if (!uuid) {
@@ -16,5 +14,9 @@ export const getJDocExchange = (body: string) => {
'Content-Type': 'text/plain',
};
- return runRequest(baseUrlApi, {body, headers});
+ return runRequest(
+ `${convertJsightUrl}?to=openapi-3.0.3&format=${format}`,
+ {body, headers},
+ {responseAsText: true}
+ );
};
diff --git a/src/api/convertJsight.ts b/src/api/convertJsight.ts
new file mode 100644
index 0000000..f4bab22
--- /dev/null
+++ b/src/api/convertJsight.ts
@@ -0,0 +1,29 @@
+import {ConvertDestinationType, OpenApiFormatType} from 'types/converter';
+import {runRequest} from 'utils/runRequest';
+import {v4 as uuidv4} from 'uuid';
+import {convertJsightUrl} from './baseUrl';
+
+export const convertJsight = (
+ body = '',
+ to: ConvertDestinationType,
+ format?: OpenApiFormatType
+) => {
+ const uuid = localStorage.getItem('uuid') || '';
+
+ if (!uuid) {
+ localStorage.setItem('uuid', uuidv4());
+ }
+
+ const isOpenApi = to === 'openapi-3.0.3';
+
+ const headers = {
+ 'X-Browser-UUID': uuid,
+ 'Content-Type': 'text/plain',
+ };
+
+ let url = `${convertJsightUrl}?to=${to}`;
+
+ if (format) url += `&format=${format}`;
+
+ return runRequest(url, {body, headers}, {responseAsText: isOpenApi});
+};
diff --git a/src/assets/images/icons/contents.svg b/src/assets/images/icons/contents.svg
new file mode 100644
index 0000000..ae60378
--- /dev/null
+++ b/src/assets/images/icons/contents.svg
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/src/assets/images/icons/copy.svg b/src/assets/images/icons/copy.svg
new file mode 100644
index 0000000..4fec64d
--- /dev/null
+++ b/src/assets/images/icons/copy.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/images/icons/htmldoc.svg b/src/assets/images/icons/htmldoc.svg
new file mode 100644
index 0000000..861479b
--- /dev/null
+++ b/src/assets/images/icons/htmldoc.svg
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/src/assets/images/icons/openapi.svg b/src/assets/images/icons/openapi.svg
new file mode 100644
index 0000000..fd63847
--- /dev/null
+++ b/src/assets/images/icons/openapi.svg
@@ -0,0 +1,5 @@
+
+
+
\ No newline at end of file
diff --git a/src/assets/images/icons/vector.svg b/src/assets/images/icons/vector.svg
index b55ade5..b4f452c 100644
--- a/src/assets/images/icons/vector.svg
+++ b/src/assets/images/icons/vector.svg
@@ -1,3 +1,5 @@
-
-
+
+
\ No newline at end of file
diff --git a/src/components/ApiInfo/ApiInfo.styles.scss b/src/components/ApiInfo/ApiInfo.styles.scss
index 104944b..27c7240 100644
--- a/src/components/ApiInfo/ApiInfo.styles.scss
+++ b/src/components/ApiInfo/ApiInfo.styles.scss
@@ -17,4 +17,8 @@
.description {
color: $secondary-text;
}
+
+ &.hidden {
+ display: none;
+ }
}
diff --git a/src/components/ApiInfo/index.tsx b/src/components/ApiInfo/index.tsx
index 497f78d..fb2a5af 100644
--- a/src/components/ApiInfo/index.tsx
+++ b/src/components/ApiInfo/index.tsx
@@ -1,4 +1,5 @@
import React, {useEffect} from 'react';
+import clsx from 'clsx';
import {ApiInfoType} from 'types/exchange';
import {Description} from '../Description';
import './ApiInfo.styles.scss';
@@ -7,9 +8,10 @@ const DEFAULT_TITLE = 'JSight Online Editor';
interface ApiInfoProps {
apiInfo?: ApiInfoType;
+ hidden?: boolean;
}
-export const ApiInfo = ({apiInfo}: ApiInfoProps) => {
+export const ApiInfo = ({apiInfo, hidden}: ApiInfoProps) => {
useEffect(() => {
document.title = apiInfo?.title || DEFAULT_TITLE;
return () => {
@@ -18,7 +20,7 @@ export const ApiInfo = ({apiInfo}: ApiInfoProps) => {
}, [apiInfo?.title]);
return apiInfo ? (
-
+
{apiInfo.title}
{apiInfo.version && (
diff --git a/src/components/Button/Button.styles.scss b/src/components/Button/Button.styles.scss
index 098e5b9..83f2747 100644
--- a/src/components/Button/Button.styles.scss
+++ b/src/components/Button/Button.styles.scss
@@ -13,14 +13,17 @@
border-bottom-right-radius: 0;
}
- .btn+.btn {
+ .btn + .btn {
margin-left: -1px;
}
}
.btn {
- padding-left: 2.4rem;
- padding-right: 2.4rem;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding-left: 1.4rem;
+ padding-right: 1.4rem;
border-radius: 4px;
font-weight: 500;
font-size: 1.4rem;
diff --git a/src/components/CodeView/Code.tsx b/src/components/CodeView/Code.tsx
index 399e861..e28caaa 100644
--- a/src/components/CodeView/Code.tsx
+++ b/src/components/CodeView/Code.tsx
@@ -68,7 +68,12 @@ export const Code = ({schema, tab, codeViewRef, keyBlock}: CodeProps) => {
const [height, setHeight] = useState
(0);
const {selectedLine, setSchemasData, schemasData} = useContext(MainContext);
const {expandedTypes} = useContext(SchemaViewContext);
- const {currentDocSidebar, setCurrentDocSidebar} = useContext(SidebarContext);
+ const {
+ currentDocSidebar,
+ setCurrentDocSidebar,
+ currentHtmlDocPanel,
+ setCurrentHtmlDocPanel,
+ } = useContext(SidebarContext);
const [isFirst, setIsFirst] = useState(true);
const schemaData = useMemo(() => {
@@ -197,8 +202,8 @@ export const Code = ({schema, tab, codeViewRef, keyBlock}: CodeProps) => {
// when active live with rules is changed
useEffect(() => {
- if (selectedLine && currentDocSidebar !== 'content') {
- setCurrentDocSidebar('rules');
+ if (selectedLine && currentHtmlDocPanel !== 'content') {
+ setCurrentHtmlDocPanel('rules');
} else {
setHeight((codeViewRef.current?.getBoundingClientRect().height || 0) + 65);
}
diff --git a/src/components/CodeView/DetailCard/index.tsx b/src/components/CodeView/DetailCard/index.tsx
index 4ed5acb..3abe632 100644
--- a/src/components/CodeView/DetailCard/index.tsx
+++ b/src/components/CodeView/DetailCard/index.tsx
@@ -33,7 +33,7 @@ export const DetailCard = ({
keyBlock,
}: DetailCardProps) => {
const divRef = useRef(null);
- const {setCurrentDocSidebar} = useContext(SidebarContext);
+ const {setCurrentHtmlDocPanel} = useContext(SidebarContext);
const {setSelectedLine} = useContext(MainContext);
const renderRule = (rule: RuleType, key: string, rulesLength: number, index: number) => {
@@ -80,7 +80,7 @@ export const DetailCard = ({
};
const closeDetailCard = () => {
- setCurrentDocSidebar(null);
+ setCurrentHtmlDocPanel('none');
setSelectedLine(null);
};
diff --git a/src/components/CodeView/Line/ShortcutLines.tsx b/src/components/CodeView/Line/ShortcutLines.tsx
index c036d58..5bc6fcb 100644
--- a/src/components/CodeView/Line/ShortcutLines.tsx
+++ b/src/components/CodeView/Line/ShortcutLines.tsx
@@ -21,7 +21,7 @@ export const ShortcutLines = ({
tab,
disableOpenBracket,
}: ShortcutLinesProps) => {
- const jdocData = useContext(JDocContext);
+ const {jdocExchange: jdocData} = useContext(JDocContext);
const userType = useMemo(() => {
const schemaName = schemasNames.slice(-1).pop();
diff --git a/src/components/CodeView/RightRules.tsx b/src/components/CodeView/RightRules.tsx
index 6af6775..8b3ff3c 100644
--- a/src/components/CodeView/RightRules.tsx
+++ b/src/components/CodeView/RightRules.tsx
@@ -24,7 +24,7 @@ export const RightRules: FC = ({
isFirst,
}) => {
const divRulesRef = useRef(null);
- const {currentDocSidebar} = useContext(SidebarContext);
+ const {currentHtmlDocPanel} = useContext(SidebarContext);
const {selectedLine} = useContext(MainContext);
const [topOffset, setTopOffset] = useState(0);
const [rightOffset, setRightOffset] = useState(0);
@@ -43,7 +43,7 @@ export const RightRules: FC = ({
const rightOffset = wrapper ? parseInt(getComputedStyle(wrapper).paddingRight) : 0;
setRightOffset(rightOffset);
- if (selectedLine?.keyBlock === keyBlock && currentDocSidebar === 'rules') {
+ if (selectedLine?.keyBlock === keyBlock && currentHtmlDocPanel === 'rules') {
const detailActiveElements = divRulesRef.current?.querySelectorAll(
`[data-name="line-${selectedLine.numberLine}"]`
);
@@ -82,10 +82,10 @@ export const RightRules: FC = ({
updateHeight(detailActiveElement, codeLineDocumentOffset);
}
}
- }, [selectedLine, currentDocSidebar, keyBlock]);
+ }, [selectedLine, currentHtmlDocPanel, keyBlock]);
const updateDetailWrapperHeight = () => {
- if (selectedLine?.keyBlock === keyBlock && currentDocSidebar === 'rules') {
+ if (selectedLine?.keyBlock === keyBlock && currentHtmlDocPanel === 'rules') {
const detailActiveElements = divRulesRef.current?.querySelectorAll(
`[data-name="line-${selectedLine.numberLine}"]`
);
@@ -138,7 +138,7 @@ export const RightRules: FC = ({
{
if (prev?.numberLine === numberLine && prev?.keyBlock === keyBlock) {
- setCurrentDocSidebar(null);
+ setCurrentDocSidebar('htmldoc');
return null;
}
- setCurrentDocSidebar('rules');
+ setCurrentHtmlDocPanel('rules');
return {
numberLine,
keyBlock,
@@ -67,7 +67,7 @@ export function useSelectionLine({
});
} else {
setSelectedLine(null);
- setCurrentDocSidebar(null);
+ setCurrentDocSidebar('htmldoc');
}
};
diff --git a/src/components/CodeView/index.tsx b/src/components/CodeView/index.tsx
index c359ba9..831348c 100644
--- a/src/components/CodeView/index.tsx
+++ b/src/components/CodeView/index.tsx
@@ -14,7 +14,7 @@ interface UsedUserElementProps {
}
const UsedUserType = ({value, keyBlock}: UsedUserElementProps) => {
- const jdocData = useContext(JDocContext);
+ const {jdocExchange: jdocData} = useContext(JDocContext);
const userType = useMemo(
() => (jdocData?.userTypes ? getUserType(value, jdocData.userTypes) : null),
@@ -36,7 +36,7 @@ const UsedUserType = ({value, keyBlock}: UsedUserElementProps) => {
};
const UsedUserEnum = ({value, keyBlock}: UsedUserElementProps) => {
- const jdocData = useContext(JDocContext);
+ const {jdocExchange: jdocData} = useContext(JDocContext);
const userEnum = useMemo(
() => (jdocData?.userEnums ? getUserEnum(value, jdocData.userEnums) : null),
diff --git a/src/components/Dropdown/DropdownMenu/index.tsx b/src/components/Dropdown/DropdownMenu/index.tsx
index 0348952..9e1204a 100644
--- a/src/components/Dropdown/DropdownMenu/index.tsx
+++ b/src/components/Dropdown/DropdownMenu/index.tsx
@@ -1,5 +1,6 @@
import React, {useContext} from 'react';
import {Popper} from 'react-popper';
+import {Placement} from '@popperjs/core/lib';
import clsx from 'clsx';
import {DropdownContext} from '../index';
import {DropdownMenuComponent} from '../DropdownMenuComponent';
@@ -9,15 +10,21 @@ interface DropdownMenuProps {
offsetY?: number;
offsetX?: number;
children?: React.ReactNode;
+ placement?: Placement;
}
-export const DropdownMenu = ({children, offsetY, offsetX}: DropdownMenuProps) => {
+export const DropdownMenu = ({
+ children,
+ offsetY,
+ offsetX,
+ placement = 'bottom-start',
+}: DropdownMenuProps) => {
const {isOpen} = useContext(DropdownContext);
return (
{}}
modifiers={[
{
diff --git a/src/components/Header/Header.styles.scss b/src/components/Header/Header.styles.scss
index 57d3356..88f534d 100644
--- a/src/components/Header/Header.styles.scss
+++ b/src/components/Header/Header.styles.scss
@@ -120,34 +120,34 @@
bottom: 2px;
}
}
+ }
+
+ .dropdown {
+ display: flex;
+ align-items: center;
+ }
- .dropdown {
+ .dropdown-items {
+ li {
display: flex;
align-items: center;
- }
+ padding: 1rem;
+ cursor: pointer;
- .dropdown-items {
- li {
- display: flex;
- align-items: center;
- padding: 1rem;
- cursor: pointer;
-
- &:hover {
- background: $main-stroke;
- }
- img {
- margin-left: 10px;
- }
+ &:hover {
+ background: $main-stroke;
+ }
+ img {
+ margin-left: 10px;
}
}
+ }
- .dropdown-menu {
- border: 0;
- border-radius: 0;
- background: $background;
- top: 0.5rem !important;
- }
+ .dropdown-menu {
+ border: 0;
+ border-radius: 0;
+ background: $background;
+ top: 0.5rem !important;
}
.logo {
diff --git a/src/components/Header/HeaderDoc.export.tsx b/src/components/Header/HeaderDoc.export.tsx
index 17cd3cf..7354a60 100644
--- a/src/components/Header/HeaderDoc.export.tsx
+++ b/src/components/Header/HeaderDoc.export.tsx
@@ -10,8 +10,8 @@ interface HeaderDocProps {
}
export const HeaderDoc = ({setViewMode}: HeaderDocProps) => {
- const jdocData = useContext(JDocContext);
- const [saveHtml] = useExport();
+ const {jdocExchange: jdocData} = useContext(JDocContext);
+ const {saveHtml} = useExport();
return (
diff --git a/src/components/Header/HeaderDoc.tsx b/src/components/Header/HeaderDoc.tsx
index 99b76c9..69da81f 100644
--- a/src/components/Header/HeaderDoc.tsx
+++ b/src/components/Header/HeaderDoc.tsx
@@ -10,8 +10,8 @@ interface HeaderDocProps {
}
export const HeaderDoc = ({setViewMode}: HeaderDocProps) => {
- const jdocData = useContext(JDocContext);
- const [saveHtml] = useExport();
+ const {jdocExchange: jdocData} = useContext(JDocContext);
+ const {saveHtml} = useExport();
const title = jdocData?.info?.title;
return (
diff --git a/src/components/Header/MenuItems/DownloadMenu/DownloadMenu.styles.scss b/src/components/Header/MenuItems/DownloadMenu/DownloadMenu.styles.scss
new file mode 100644
index 0000000..1a3caf7
--- /dev/null
+++ b/src/components/Header/MenuItems/DownloadMenu/DownloadMenu.styles.scss
@@ -0,0 +1,33 @@
+@import 'src/styles/variables';
+
+.app-header .dropdown {
+ button {
+ font-weight: 500;
+ }
+
+ i {
+ margin-left: 8px;
+ }
+
+ .icon {
+ margin-right: 8px;
+ }
+
+ .dropdown-items li.item {
+ display: flex;
+ flex-direction: row;
+ align-items: flex-start;
+ }
+
+ .name {
+ font-size: 14px;
+ font-weight: 500;
+ color: $main-text;
+ }
+
+ .desc {
+ font-size: 12px;
+ font-weight: 400;
+ color: $secondary-text;
+ }
+}
diff --git a/src/components/Header/MenuItems/DownloadMenu/index.tsx b/src/components/Header/MenuItems/DownloadMenu/index.tsx
new file mode 100644
index 0000000..e17ffe2
--- /dev/null
+++ b/src/components/Header/MenuItems/DownloadMenu/index.tsx
@@ -0,0 +1,85 @@
+import React from 'react';
+import {Dropdown} from 'components/Dropdown';
+import {DropdownToggle} from 'components/Dropdown/DropdownToggle';
+import {DropdownMenu} from 'components/Dropdown/DropdownMenu';
+
+import IconOpenAPI from 'assets/images/icons/openapi.svg';
+import IconHTMLDoc from 'assets/images/icons/htmldoc.svg';
+
+import './DownloadMenu.styles.scss';
+import {useExport} from 'hooks/useExport';
+
+interface MenuType {
+ icon: string;
+ name: string;
+ desc: string;
+ action: () => Promise
;
+}
+
+interface DocsMenuProps {
+ isMenuOpened: boolean;
+ setIsMenuOpened: React.Dispatch>;
+}
+
+interface DocsMenuItemsProps {
+ setIsMenuOpened: React.Dispatch>;
+}
+
+export const DownloadMenu = ({isMenuOpened, setIsMenuOpened}: DocsMenuProps) => {
+ const {saveHtml, saveJson, saveYaml} = useExport();
+
+ const menu: MenuType[] = [
+ {
+ icon: IconHTMLDoc,
+ name: 'HTML page',
+ desc: 'Download the prettified documentation page',
+ action: saveHtml,
+ },
+ {
+ icon: IconOpenAPI,
+ name: 'OpenAPI JSON',
+ desc: 'Download the converted OpenAPI JSON code',
+ action: saveJson,
+ },
+ {
+ icon: IconOpenAPI,
+ name: 'OpenAPI YAML',
+ desc: 'Download the converted OpenAPI YAML code',
+ action: saveYaml,
+ },
+ ];
+
+ const DownloadMenuItems = ({setIsMenuOpened}: DocsMenuItemsProps) => (
+
+ );
+
+ return (
+
+
+ Download
+
+
+
+
+
+
+ );
+};
diff --git a/src/components/Header/index.tsx b/src/components/Header/index.tsx
index f9398fc..c867310 100644
--- a/src/components/Header/index.tsx
+++ b/src/components/Header/index.tsx
@@ -1,15 +1,18 @@
-import React, {useState} from 'react';
+import React, {useContext, useState} from 'react';
import clsx from 'clsx';
import {Button} from '../Button';
import {HeaderLogo} from './HeaderLogo';
import {DocsMenu} from './MenuItems/DocsMenu';
import {FileMenu} from './MenuItems/FileMenu';
-import {useExport} from 'hooks/useExport';
import {editorModeType, ExamplesType} from 'types';
import {ShareButton} from 'components/ShareButton';
-import './Header.styles.scss';
import {Example} from '../Modals/Example';
import Modal from 'react-modal';
+import {Toggle} from 'components/Toggle';
+import {DownloadMenu} from './MenuItems/DownloadMenu';
+import {SidebarContext} from 'store';
+
+import './Header.styles.scss';
interface HeaderProps {
setInitialContent(content: ExamplesType): void;
@@ -28,10 +31,19 @@ export const Header = ({
}: HeaderProps) => {
const [docsMenuVisible, setDocsMenuVisible] = useState(false);
const [fileMenuVisible, setFileMenuVisible] = useState(false);
+ const [downloadMenuVisible, setDownloadMenuVisible] = useState(false);
const [examplePopup, setExampleMenuPopup] = useState(null);
+
+ const {
+ currentDocSidebar,
+ setCurrentDocSidebar,
+ currentOpenApiFormat,
+ setCurrentOpenApiFormat,
+ } = useContext(SidebarContext);
+
const switchDocsMenu = () => setDocsMenuVisible(!docsMenuVisible);
const switchFileMenu = () => setFileMenuVisible(!fileMenuVisible);
- const [saveHtml] = useExport();
+ const switchDownloadMenu = () => setDownloadMenuVisible(!downloadMenuVisible);
if (examplePopup) {
Modal.setAppElement('#root');
@@ -60,25 +72,35 @@ export const Header = ({
-
-
- Message validator
-
-
+ setCurrentDocSidebar('openapi')}>OpenAPI
setContactModalVisible(true)}>Ask a question
+ {currentDocSidebar === 'openapi' && (
+
+ setCurrentOpenApiFormat && setCurrentOpenApiFormat(value ? 'yaml' : 'json')
+ }
+ />
+ )}
setContactModalVisible(true)} />
-
- setViewMode('doc')} />
+ setViewMode('doc')}>
+ HTML Preview
+
+
+
+
diff --git a/src/components/HeaderMetaTags/index.tsx b/src/components/HeaderMetaTags/index.tsx
index 44adf34..3b072fa 100644
--- a/src/components/HeaderMetaTags/index.tsx
+++ b/src/components/HeaderMetaTags/index.tsx
@@ -4,7 +4,7 @@ import {JDocContext} from 'store';
import {shorten} from 'utils/shorten';
export const HeaderMetaTags = () => {
- const jdocData = useContext(JDocContext);
+ const {jdocExchange: jdocData} = useContext(JDocContext);
const getTitle = (limit: number) => {
if (jdocData?.info?.title) {
diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx
index 1a07530..9d31356 100644
--- a/src/components/Layout/index.tsx
+++ b/src/components/Layout/index.tsx
@@ -9,8 +9,10 @@ interface LayoutProps {
}
export const Layout = ({children, isEditor}: LayoutProps) => {
- const {currentDocSidebar} = useContext(SidebarContext);
- const isShowSidebar = isEditor ? currentDocSidebar === 'content' : true;
+ const {currentDocSidebar, currentHtmlDocPanel} = useContext(SidebarContext);
+ const isShowSidebar = isEditor
+ ? currentHtmlDocPanel === 'content' && currentDocSidebar === 'htmldoc'
+ : true;
const side = isEditor ? 'right' : 'left';
return (
diff --git a/src/components/MainContent/MainContent.styles.scss b/src/components/MainContent/MainContent.styles.scss
index a85e5bd..e00bb5a 100644
--- a/src/components/MainContent/MainContent.styles.scss
+++ b/src/components/MainContent/MainContent.styles.scss
@@ -23,7 +23,12 @@
}
}
- .reusable-header, .resource-header {
+ .wrapper {
+ position: relative;
+ }
+
+ .reusable-header,
+ .resource-header {
font-size: 2.8rem;
line-height: 3.6rem;
font-weight: 600;
@@ -36,7 +41,7 @@
.resource-header {
padding: 0 3rem 1.2rem;
- +.resource-wrapper {
+ + .resource-wrapper {
padding-bottom: 3.2rem;
}
}
@@ -68,3 +73,43 @@
.main-resources {
height: 100%;
}
+
+.openapi-wrapper {
+ display: flex;
+}
+
+.openapi-lines {
+ padding: 20px 0;
+ width: 54px;
+ font-family: 'JetBrainsMono', serif;
+ font-size: 14px;
+ text-align: center;
+ background-color: $secondary-grey;
+ color: $main-grey;
+ flex-shrink: 0;
+}
+
+.openapi-content {
+ margin: 0;
+ padding: 20px 24px;
+ font-family: 'JetBrainsMono', serif;
+ font-size: 14px;
+ flex: 1;
+}
+
+.openapi-copy.btn {
+ position: absolute;
+ bottom: 20px;
+ right: 50px;
+ width: auto;
+ padding: 11px 23px;
+ border-radius: 4px;
+ border: 1px solid $secondary-stroke;
+ background: $main-stroke;
+ color: $main-text;
+ opacity: 0.8;
+}
+
+.openapi-copy img {
+ margin-left: 8px;
+}
diff --git a/src/components/MainContent/index.tsx b/src/components/MainContent/index.tsx
index 4792388..30ce256 100644
--- a/src/components/MainContent/index.tsx
+++ b/src/components/MainContent/index.tsx
@@ -1,6 +1,6 @@
-import React, {useRef, useState, useEffect, useContext, useMemo} from 'react';
+import React, {useRef, useState, useEffect, useContext, useMemo, Fragment} from 'react';
import {Virtuoso, VirtuosoHandle} from 'react-virtuoso';
-import {compact, each, groupBy, isEqual, map, mapValues} from 'lodash';
+import {compact, each, groupBy, map, mapValues} from 'lodash';
import {useParams} from 'react-router-dom';
import {MainRouterParams} from 'types/router';
import {ApiInfo} from 'components/ApiInfo';
@@ -15,6 +15,15 @@ import {HttpResource} from 'components/Resource/Http';
import './MainContent.styles.scss';
import {JsonRpcHeader} from 'components/Resource/JsonRpc/JsonRpcHeader';
import {JsonRpcResource} from 'components/Resource/JsonRpc';
+import clsx from 'clsx';
+import {editorModeType, ErrorType} from 'types';
+import {Button} from 'components/Button';
+
+import IconCopy from 'assets/images/icons/copy.svg';
+import {toast} from 'react-toastify';
+import {notificationIds} from 'utils/notificationIds';
+import {convertJsight} from 'api/convertJsight';
+import {showEditorError} from 'utils/showEditorError';
type SchemaPropertyType =
| 'collapsedRules'
@@ -25,298 +34,408 @@ type SchemaPropertyType =
interface MainContentProps {
jdocExchange?: JDocType;
+ jdocExchangeError?: boolean;
+ isJdocLoading?: boolean;
+ jsightCode?: string;
+ viewMode?: editorModeType;
+ setScrollToRow?: React.Dispatch>;
+ setErrorRow?: React.Dispatch>;
}
-export const MainContent = React.memo(
- ({jdocExchange}: MainContentProps) => {
- const divRef = useRef(null);
- const virtuosoRef = useRef(null);
- const virtuosoScrollerRef = useRef(null);
- const [selectedLine, setSelectedLine] = useState(null);
- const [jdocList, setJdocList] = useState([]);
- const [jdocPositions, setJdocPositions] = useState([]);
- const {path} = useParams();
- const {headersBodiesTypesCode, pathQueriesCode, typesExpand, rulesExpand} = useContext(
- GlobalSettingsContext
- );
- const {currentUrl, setCurrentUrl} = useContext(CurrentUrlContext);
- const {currentDocSidebar, setCurrentDocSidebar} = useContext(SidebarContext);
- const [overscan, setOverscan] = useState(480);
- const [schemasView, setSchemasView] = useState([]);
- const [schemasData, setSchemasData] = useState<{[key: string]: SchemaData[]}>({});
- const [resourceState, setResourceState] = useState([]);
- // @ts-ignore
- window['mainContent'] = virtuosoRef;
-
- const showRightSidebar = useMemo(() => !!currentDocSidebar, [currentDocSidebar]);
-
- useEffect(() => {
- if (!currentUrl && path) {
- const currentPath = path[0] !== '@' ? '/' + path : path;
- const index = jdocPositions.indexOf(`${currentPath.replace(/({|})/gi, '-')}`);
-
- if (~index && virtuosoRef?.current) {
- virtuosoRef.current.scrollToIndex({
- index: index + 1,
- align: 'start',
- behavior: 'auto',
- });
- setCurrentUrl(path);
- }
- }
- }, [path, jdocPositions]);
-
- useEffect(() => {
- setSchemasView((prev) => {
- return prev.map((item) => {
- if (item.typeBlock === 'header-body') {
- item['viewType'] = headersBodiesTypesCode ? 'code' : 'table';
- }
- return item;
- });
+export const MainContent = React.memo((props: MainContentProps) => {
+ const {
+ jdocExchange,
+ jdocExchangeError,
+ isJdocLoading,
+ jsightCode,
+ viewMode,
+ setScrollToRow,
+ setErrorRow,
+ } = props;
+ const virtuosoRef = useRef(null);
+ const virtuosoScrollerRef = useRef(null);
+ const [selectedLine, setSelectedLine] = useState(null);
+ const [jdocList, setJdocList] = useState([]);
+ const [jdocPositions, setJdocPositions] = useState([]);
+ const {path} = useParams();
+ const {headersBodiesTypesCode, pathQueriesCode, typesExpand, rulesExpand} = useContext(
+ GlobalSettingsContext
+ );
+ const {currentUrl, setCurrentUrl} = useContext(CurrentUrlContext);
+ const {
+ currentDocSidebar,
+ currentOpenApiFormat,
+ currentHtmlDocPanel,
+ setCurrentHtmlDocPanel,
+ } = useContext(SidebarContext);
+ const [overscan, setOverscan] = useState(480);
+ const [schemasView, setSchemasView] = useState([]);
+ const [schemasData, setSchemasData] = useState<{[key: string]: SchemaData[]}>({});
+ const [resourceState, setResourceState] = useState([]);
+
+ const [openApiContent, setOpenApiContent] = useState('');
+ const [openApiLinesCount, setOpenApiLinesCount] = useState();
+ const [isOpenApiContentLoading, setIsOpenApiContentLoading] = useState(false);
+
+ // @ts-ignore
+ window['mainContent'] = virtuosoRef;
+
+ const showRightSidebar = useMemo(() => !!currentDocSidebar, [currentDocSidebar]);
+
+ const copyToClipboard = () => {
+ if (navigator && navigator.clipboard && navigator.clipboard.writeText && openApiContent) {
+ navigator.clipboard.writeText(openApiContent);
+
+ toast.success('OpenAPI copied', {
+ toastId: notificationIds.SUCCESS_MESSAGE_DEFAULT_ID,
+ position: 'bottom-center',
+ className: 'notification-success success',
+ autoClose: 3000,
+ hideProgressBar: true,
+ closeButton: false,
+ closeOnClick: false,
+ pauseOnHover: false,
+ draggable: false,
+ progress: undefined,
+ icon: ,
});
- }, [headersBodiesTypesCode]);
- useEffect(() => {
- setSchemasView((prev) => {
- return prev.map((item) => {
- if (item.typeBlock === 'path-query') {
- item['viewType'] = pathQueriesCode ? 'code' : 'table';
- }
- return item;
- });
- });
- }, [pathQueriesCode]);
+ return Promise.resolve();
+ }
- useEffect(() => {
- setSchemasView((prev) => {
- return prev.map((item) => {
- return {
- ...item,
- expandedTypes: typesExpand,
- };
- });
- });
+ return Promise.reject('The Clipboard API is not available.');
+ };
- if (!typesExpand) {
- setSchemasData((prev) => {
- return mapValues(prev, () => {
- return [emptySchemaData];
- });
- });
- }
- }, [typesExpand]);
+ useEffect(() => {
+ if (!currentUrl && path) {
+ const currentPath = path[0] !== '@' ? '/' + path : path;
+ const index = jdocPositions.indexOf(`${currentPath.replace(/({|})/gi, '-')}`);
- useEffect(() => {
- setSchemasView((prev) => {
- return prev.map((item) => {
- return {
- ...item,
- collapsedRules: !rulesExpand,
- };
+ if (~index && virtuosoRef?.current) {
+ virtuosoRef.current.scrollToIndex({
+ index: index + 1,
+ align: 'start',
+ behavior: 'auto',
});
- });
- }, [rulesExpand]);
-
- useEffect(() => {
- setOverscan(window.innerHeight / 2);
- }, []);
-
- useEffect(() => {
- if (currentDocSidebar === 'content') {
- setSelectedLine(null);
+ setCurrentUrl(path);
}
- }, [currentDocSidebar]);
-
- const updateSchemaView = (keyBlock: string, value: any, property: SchemaPropertyType) => {
- setSchemasView((prev) => {
- if (prev.find((item) => item.key === keyBlock)) {
- return prev.map((item) => {
- if (item.key === keyBlock) {
- item[property] = value;
- return item;
- }
- return item;
- });
- } else {
- const schemaView: SchemaViewType = {key: keyBlock};
- schemaView[property] = value;
- return [...prev, schemaView];
+ }
+ }, [path, jdocPositions]);
+
+ useEffect(() => {
+ setSchemasView((prev) => {
+ return prev.map((item) => {
+ if (item.typeBlock === 'header-body') {
+ item['viewType'] = headersBodiesTypesCode ? 'code' : 'table';
}
+ return item;
});
- };
-
- const setCollapsedRules = (keyBlock: string, value: boolean) => {
- updateSchemaView(keyBlock, value, 'collapsedRules');
- };
-
- const setExpandedTypes = (keyBlock: string, value: boolean) => {
- updateSchemaView(keyBlock, value, 'expandedTypes');
- };
-
- const setViewType = (keyBlock: string, value: string) => {
- updateSchemaView(keyBlock, value, 'viewType');
- };
-
- const setExpandDetailCard = (keyBlock: string, value: boolean) => {
- updateSchemaView(keyBlock, value, 'expandDetailCard');
- };
-
- const setTypeBlock = (keyBlock: string, value: string | undefined) => {
- updateSchemaView(keyBlock, value, 'typeBlock');
- };
-
- useEffect(() => {
- if (jdocExchange) {
- const {info, servers, tags, interactions, userTypes, userEnums} = jdocExchange;
- const jdocList: JSX.Element[] = [];
- const jdocPositions: string[] = [];
- jdocList.push(
);
-
- if (info) {
- jdocList.push( );
- jdocPositions.push('info');
- }
-
- if (servers) {
- jdocList.push( );
- jdocPositions.push('servers');
+ });
+ }, [headersBodiesTypesCode]);
+
+ useEffect(() => {
+ setSchemasView((prev) => {
+ return prev.map((item) => {
+ if (item.typeBlock === 'path-query') {
+ item['viewType'] = pathQueriesCode ? 'code' : 'table';
}
+ return item;
+ });
+ });
+ }, [pathQueriesCode]);
+
+ useEffect(() => {
+ setSchemasView((prev) => {
+ return prev.map((item) => {
+ return {
+ ...item,
+ expandedTypes: typesExpand,
+ };
+ });
+ });
- if (Object.values(tags).length > 0) {
- let index = 0;
- each(tags, (tag, tagKey) => {
- if (tag.interactionGroups.find((item) => item.protocol === 'json-rpc-2.0')) {
- jdocList.push( );
- } else {
- jdocList.push(
-
- );
+ if (!typesExpand) {
+ setSchemasData((prev) => {
+ return mapValues(prev, () => {
+ return [emptySchemaData];
+ });
+ });
+ }
+ }, [typesExpand]);
+
+ useEffect(() => {
+ setSchemasView((prev) => {
+ return prev.map((item) => {
+ return {
+ ...item,
+ collapsedRules: !rulesExpand,
+ };
+ });
+ });
+ }, [rulesExpand]);
+
+ useEffect(() => {
+ setOverscan(window.innerHeight / 2);
+ }, []);
+
+ useEffect(() => {
+ if (currentDocSidebar === 'openapi') {
+ toast.dismiss(notificationIds.ERROR_MESSAGE_HTMLDOC_ID);
+ } else if (currentDocSidebar === 'htmldoc') {
+ toast.dismiss(notificationIds.ERROR_MESSAGE_OPENAPI_ID);
+ }
+ }, [currentDocSidebar]);
+
+ useEffect(() => {
+ if (currentDocSidebar === 'openapi' && currentOpenApiFormat) {
+ const convert = async () => {
+ try {
+ setIsOpenApiContentLoading(true);
+ const result = await convertJsight(jsightCode, 'openapi-3.0.3', currentOpenApiFormat);
+ setOpenApiContent(result as string);
+ setIsOpenApiContentLoading(false);
+ toast.dismiss();
+ setErrorRow && setErrorRow(null);
+ } catch (error) {
+ showEditorError(error as ErrorType, notificationIds.ERROR_MESSAGE_OPENAPI_ID, () => {
+ if (!(error as ErrorType).Line) {
+ return;
}
- jdocPositions.push(`resource-${tagKey}`);
-
- tag.interactionGroups.forEach((interactionGroup) => {
- if (interactionGroup.protocol === 'http') {
- each(
- groupBy(
- compact(
- interactionGroup.interactions.map((interaction) =>
- interactions.hasOwnProperty(interaction) ? interactions[interaction] : null
- )
- ),
- 'path'
- ),
- (interactionsByPath, interactionPath) => {
- const resourceKey = `${interactionPath.replace(/({|})/gi, '-')}`;
- jdocList.push(
-
- );
- jdocPositions.push(resourceKey);
- setResourceState((prev) => [...prev, {method: ''}]);
- index++;
- }
- );
- } else if (interactionGroup.protocol === 'json-rpc-2.0') {
- interactionGroup.interactions.forEach((interaction) => {
- if (interactions.hasOwnProperty(interaction)) {
- const resource = interactions[interaction] as JsonRpcInteractionType;
- const resourceKey = `${resource.path.replace(/({|})/gi, '-')}-${
- resource.method
- }`;
-
- jdocList.push(
-
- );
- jdocPositions.push(resourceKey);
- }
- });
- }
- });
+
+ setScrollToRow && setScrollToRow(true);
+ setTimeout(() => setScrollToRow && setScrollToRow(false), 500);
});
+ (error as ErrorType).Line && setErrorRow && setErrorRow((error as ErrorType).Line);
}
+ };
- if (userTypes) {
- jdocList.push(Types );
- jdocPositions.push('types');
+ convert();
+ }
+ }, [currentDocSidebar, currentOpenApiFormat, jsightCode, setErrorRow, setScrollToRow]);
- map(jdocExchange.userTypes, (userType, key) => {
- jdocList.push(
-
- );
- jdocPositions.push(key);
- });
- }
+ const updateSchemaView = (keyBlock: string, value: any, property: SchemaPropertyType) => {
+ setSchemasView((prev) => {
+ if (prev.find((item) => item.key === keyBlock)) {
+ return prev.map((item) => {
+ if (item.key === keyBlock) {
+ item[property] = value;
+ return item;
+ }
+ return item;
+ });
+ } else {
+ const schemaView: SchemaViewType = {key: keyBlock};
+ schemaView[property] = value;
+ return [...prev, schemaView];
+ }
+ });
+ };
+
+ const setCollapsedRules = (keyBlock: string, value: boolean) => {
+ updateSchemaView(keyBlock, value, 'collapsedRules');
+ };
+
+ const setExpandedTypes = (keyBlock: string, value: boolean) => {
+ updateSchemaView(keyBlock, value, 'expandedTypes');
+ };
+
+ const setViewType = (keyBlock: string, value: string) => {
+ updateSchemaView(keyBlock, value, 'viewType');
+ };
+
+ const setExpandDetailCard = (keyBlock: string, value: boolean) => {
+ updateSchemaView(keyBlock, value, 'expandDetailCard');
+ };
+
+ const setTypeBlock = (keyBlock: string, value: string | undefined) => {
+ updateSchemaView(keyBlock, value, 'typeBlock');
+ };
+
+ useEffect(() => {
+ if (jdocExchange) {
+ const {info, servers, tags, interactions, userTypes, userEnums} = jdocExchange;
+ const jdocList: JSX.Element[] = [];
+ const jdocPositions: string[] = [];
+ jdocList.push(
);
+
+ if (info) {
+ jdocList.push( );
+ jdocPositions.push('info');
+ }
- if (userEnums) {
- jdocList.push(Enums );
+ if (servers) {
+ jdocList.push( );
+ jdocPositions.push('servers');
+ }
- map(jdocExchange.userEnums, (userEnum, key) => {
+ if (Object.values(tags).length > 0) {
+ let index = 0;
+ each(tags, (tag, tagKey) => {
+ if (tag.interactionGroups.find((item) => item.protocol === 'json-rpc-2.0')) {
+ jdocList.push( );
+ } else {
jdocList.push(
-
+
);
- jdocPositions.push(key);
+ }
+ jdocPositions.push(`resource-${tagKey}`);
+
+ tag.interactionGroups.forEach((interactionGroup) => {
+ if (interactionGroup.protocol === 'http') {
+ each(
+ groupBy(
+ compact(
+ interactionGroup.interactions.map((interaction) =>
+ interactions.hasOwnProperty(interaction) ? interactions[interaction] : null
+ )
+ ),
+ 'path'
+ ),
+ (interactionsByPath, interactionPath) => {
+ const resourceKey = `${interactionPath.replace(/({|})/gi, '-')}`;
+ jdocList.push(
+
+ );
+ jdocPositions.push(resourceKey);
+ setResourceState((prev) => [...prev, {method: ''}]);
+ index++;
+ }
+ );
+ } else if (interactionGroup.protocol === 'json-rpc-2.0') {
+ interactionGroup.interactions.forEach((interaction) => {
+ if (interactions.hasOwnProperty(interaction)) {
+ const resource = interactions[interaction] as JsonRpcInteractionType;
+ const resourceKey = `${resource.path.replace(/({|})/gi, '-')}-${resource.method}`;
+
+ jdocList.push(
+
+ );
+ jdocPositions.push(resourceKey);
+ }
+ });
+ }
});
- }
- setJdocList(jdocList);
- setJdocPositions(jdocPositions);
+ });
+ }
- // @ts-ignore
- window['jdocPositions'] = jdocPositions;
+ if (userTypes) {
+ jdocList.push(Types );
+ jdocPositions.push('types');
+
+ map(jdocExchange.userTypes, (userType, key) => {
+ jdocList.push(
+
+ );
+ jdocPositions.push(key);
+ });
}
- return () => {
- setResourceState([]);
- };
- }, [jdocExchange]);
-
- const value = useMemo(
- () => ({
- showRightSidebar,
- selectedLine,
- schemasView,
- schemasData,
- resourceState,
- setSelectedLine,
- setExpandDetailCard,
- setCollapsedRules,
- setExpandedTypes,
- setViewType,
- setResourceState,
- setTypeBlock,
- setSchemasData,
- }),
- [selectedLine, schemasView, schemasData, resourceState]
- );
-
- return (
-
-
+
+ if (userEnums) {
+ jdocList.push(
Enums );
+
+ map(jdocExchange.userEnums, (userEnum, key) => {
+ jdocList.push(
+
+ );
+ jdocPositions.push(key);
+ });
+ }
+ setJdocList(jdocList);
+ setJdocPositions(jdocPositions);
+
+ // @ts-ignore
+ window['jdocPositions'] = jdocPositions;
+ }
+ return () => {
+ setResourceState([]);
+ };
+ }, [jdocExchange]);
+
+ useEffect(() => {
+ const count = openApiContent.match(new RegExp('\n', 'g'))?.length || 0;
+ setOpenApiLinesCount(count + 1);
+ }, [openApiContent]);
+
+ const value = useMemo(
+ () => ({
+ showRightSidebar,
+ selectedLine,
+ schemasView,
+ schemasData,
+ resourceState,
+ setSelectedLine,
+ setExpandDetailCard,
+ setCollapsedRules,
+ setExpandedTypes,
+ setViewType,
+ setResourceState,
+ setTypeBlock,
+ setSchemasData,
+ }),
+ [selectedLine, schemasView, schemasData, resourceState]
+ );
+
+ const mainContentClasses = clsx('main-content', {
+ scrollable: currentDocSidebar === 'openapi',
+ disabled:
+ (currentDocSidebar === 'openapi' && isOpenApiContentLoading) ||
+ (currentDocSidebar === 'htmldoc' && jdocExchangeError) ||
+ (currentDocSidebar === 'htmldoc' && isJdocLoading),
+ });
+
+ return (
+
+
+ {currentDocSidebar === 'openapi' && viewMode !== 'doc' && (
+
+
+
+ {Array.from(Array(openApiLinesCount).keys()).map((num) => (
+
+ {num + 1}
+
+
+ ))}
+
+
{openApiContent}
+
+ Copy all
+
+
+
+ )}
+ {(currentDocSidebar !== 'openapi' || viewMode === 'doc') && (
- {currentDocSidebar === 'rules' && (
+ {currentHtmlDocPanel === 'rules' && (
{
- setCurrentDocSidebar(null);
+ setCurrentHtmlDocPanel('none');
setSelectedLine(null);
}}
>
@@ -342,9 +461,8 @@ export const MainContent = React.memo(
increaseViewportBy={overscan}
/>
-
+ )}
- );
- },
- (prev, next) => isEqual(prev.jdocExchange, next.jdocExchange)
-);
+
+ );
+});
diff --git a/src/components/Notifications/EditorErrorNotification.tsx b/src/components/Notifications/EditorErrorNotification.tsx
index 1ee9010..e469453 100644
--- a/src/components/Notifications/EditorErrorNotification.tsx
+++ b/src/components/Notifications/EditorErrorNotification.tsx
@@ -2,7 +2,7 @@ import React, {useCallback, useEffect, useRef} from 'react';
import './Notifications.styles.scss';
export interface CustomNotificationsProps {
- message: string | JSX.Element;
+ message: string;
title?: string;
setScrollToRow?: () => void;
}
@@ -37,7 +37,7 @@ export const EditorErrorNotification = ({
return (
{title &&
{title}
}
-
{message}
+
);
};
diff --git a/src/components/Notifications/Notifications.styles.scss b/src/components/Notifications/Notifications.styles.scss
index 66baf8b..f1080a0 100644
--- a/src/components/Notifications/Notifications.styles.scss
+++ b/src/components/Notifications/Notifications.styles.scss
@@ -7,7 +7,8 @@
.notification-success {
&.success {
background: rgba(255, 255, 255, 0.95);
- box-shadow: 0 0 36px rgba(27, 17, 40, 0.08), 0 0 12px rgba(27, 17, 40, 0.04), 0 0 4px rgba(27, 17, 40, 0.02);
+ box-shadow: 0 0 36px rgba(27, 17, 40, 0.08), 0 0 12px rgba(27, 17, 40, 0.04),
+ 0 0 4px rgba(27, 17, 40, 0.02);
border-radius: 21px;
min-height: 0;
color: $main-text;
@@ -66,6 +67,15 @@
line-height: 2.1rem;
}
+ .message a {
+ text-decoration: underline;
+ color: $secondary-yellow;
+ }
+
+ .message a:hover {
+ text-decoration: none;
+ }
+
.btn-close {
padding: 0.75rem 1.6rem;
width: 6.4rem;
diff --git a/src/components/SidebarContent/index.tsx b/src/components/SidebarContent/index.tsx
index 2ed2335..8e38acc 100644
--- a/src/components/SidebarContent/index.tsx
+++ b/src/components/SidebarContent/index.tsx
@@ -19,8 +19,8 @@ interface SidebarContentProps {
export const SidebarContent = ({side, isShowSettings, isShow}: SidebarContentProps) => {
const {setIsOpen, isOpen} = useContext(GlobalSettingsContext);
- const {setCurrentDocSidebar} = useContext(SidebarContext);
- const jdocData = useContext(JDocContext);
+ const {setCurrentHtmlDocPanel} = useContext(SidebarContext);
+ const {jdocExchange: jdocData} = useContext(JDocContext);
const tags = useMemo(() => jdocData?.tags || {}, [jdocData]);
@@ -48,7 +48,7 @@ export const SidebarContent = ({side, isShowSettings, isShow}: SidebarContentPro
Contents
{!(side === 'left' || isExport) && (
- setCurrentDocSidebar(null)}>
+ setCurrentHtmlDocPanel('none')}>
)}
diff --git a/src/components/TableView/RowsCollection.tsx b/src/components/TableView/RowsCollection.tsx
index b0c4805..7ef93e7 100644
--- a/src/components/TableView/RowsCollection.tsx
+++ b/src/components/TableView/RowsCollection.tsx
@@ -34,16 +34,22 @@ export const RowsCollection = ({
);
} else if (content.tokenType === 'object' || content.tokenType === 'array') {
const isArray = content.tokenType === 'array';
- rows.push(
- ' : String(key)}
- level={level + 1}
- property={content}
- isNestedChild={isNestedChild}
- isArrayLastItem={isArrayLastItem}
- />
- );
+
+ if (block === 'path' && level === 0) {
+ level--;
+ } else {
+ rows.push(
+ ' : String(key)}
+ level={level + 1}
+ property={content}
+ isNestedChild={isNestedChild}
+ isArrayLastItem={isArrayLastItem}
+ />
+ );
+ }
+
content.children?.forEach((item, index) => {
const childrenRows = RowsCollection({
block,
@@ -58,8 +64,8 @@ export const RowsCollection = ({
} else if (['number', 'string', 'boolean', 'null'].includes(content.tokenType)) {
rows.push(
' : String(key)}
+ key={`${level}-${level === 0 && block !== 'path' ? 'root' : key}`}
+ keyValue={level === 0 && block !== 'path' ? '' : String(key)}
level={level + 1}
property={content}
isNestedChild={isNestedChild}
diff --git a/src/components/TableView/index.tsx b/src/components/TableView/index.tsx
index 0675cda..78cd6fc 100644
--- a/src/components/TableView/index.tsx
+++ b/src/components/TableView/index.tsx
@@ -20,7 +20,7 @@ export const TableView = ({keyBlock, schema, format, block}: TableViewProps) =>
block,
level: 0,
});
- } else if ('regex') {
+ } else {
return (
'}
@@ -34,8 +34,6 @@ export const TableView = ({keyBlock, schema, format, block}: TableViewProps) =>
}}
/>
);
- } else {
- return null;
}
};
diff --git a/src/components/Toggle/Toggle.styles.scss b/src/components/Toggle/Toggle.styles.scss
new file mode 100644
index 0000000..71665a8
--- /dev/null
+++ b/src/components/Toggle/Toggle.styles.scss
@@ -0,0 +1,76 @@
+@import '/src/styles/variables';
+
+.toggle {
+ display: flex;
+ align-items: center;
+ color: $main-text;
+ font-size: 14px;
+ font-weight: 500;
+}
+
+.toggle-switch {
+ position: relative;
+ display: inline-block;
+ width: 36px;
+ height: 20px;
+ margin: 0 12px;
+}
+
+/* Hide default HTML checkbox */
+.toggle-switch input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+}
+
+/* The slider */
+.toggle-slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: #ccc;
+ -webkit-transition: 0.4s;
+ transition: 0.4s;
+}
+
+.toggle-slider.equivalent {
+ background-color: $secondary-blue;
+}
+
+.toggle-slider:before {
+ position: absolute;
+ content: '';
+ height: 12px;
+ width: 12px;
+ left: 4px;
+ bottom: 4px;
+ background-color: white;
+ -webkit-transition: 0.4s;
+ transition: 0.4s;
+}
+
+input:checked + .toggle-slider {
+ background-color: $secondary-blue;
+}
+
+input:focus + .toggle-slider {
+ box-shadow: 0 0 1px $secondary-blue;
+}
+
+input:checked + .toggle-slider:before {
+ -webkit-transform: translateX(16px);
+ -ms-transform: translateX(16px);
+ transform: translateX(16px);
+}
+
+/* Rounded sliders */
+.toggle-slider.round {
+ border-radius: 34px;
+}
+
+.toggle-slider.round:before {
+ border-radius: 50%;
+}
diff --git a/src/components/Toggle/index.tsx b/src/components/Toggle/index.tsx
new file mode 100644
index 0000000..c5d71b3
--- /dev/null
+++ b/src/components/Toggle/index.tsx
@@ -0,0 +1,36 @@
+import React, {useEffect, useState} from 'react';
+import clsx from 'clsx';
+import './Toggle.styles.scss';
+
+interface ToggleProps {
+ leftOption?: string;
+ rightOption?: string;
+ defaultOption?: string | boolean;
+ isEquivalent?: boolean;
+ onChange?: (value: boolean) => void;
+}
+
+export const Toggle = ({
+ leftOption = 'OFF',
+ rightOption = 'ON',
+ defaultOption = false,
+ isEquivalent,
+ onChange,
+}: ToggleProps) => {
+ const [checked, setChecked] = useState(defaultOption === true || defaultOption === rightOption);
+
+ useEffect(() => {
+ onChange && onChange(checked);
+ }, [checked, onChange]);
+
+ return (
+
+ {leftOption}
+
+ setChecked((prev) => !prev)} />
+
+
+ {rightOption}
+
+ );
+};
diff --git a/src/hooks/useExport.ts b/src/hooks/useExport.ts
index 3e02541..baf2d50 100644
--- a/src/hooks/useExport.ts
+++ b/src/hooks/useExport.ts
@@ -1,9 +1,10 @@
import {useContext} from 'react';
import {find} from 'lodash';
import {JDocContext} from 'store';
+import {convertJsight} from 'api/convertJsight';
export function useExport() {
- const jdocData = useContext(JDocContext);
+ const {jdocExchange: jdocData, jsightCode} = useContext(JDocContext);
const renderHtml: () => Promise = async () => {
const styles = document.querySelectorAll('style');
@@ -16,6 +17,7 @@ export function useExport() {
let scriptLink = '';
let styleLink = '';
+
if (process.env.NODE_ENV !== 'production') {
const scripts = document.querySelectorAll('script');
scriptLink = find(scripts, (script) => script.src.indexOf('static/js') !== -1)?.src || '';
@@ -63,7 +65,7 @@ export function useExport() {
-
+
@@ -74,7 +76,7 @@ export function useExport() {
-
+
@@ -98,19 +100,37 @@ export function useExport() {
return null;
};
+ const save = (text: string, title: string, type: string) => {
+ const content = [text];
+ const bl = new Blob(content, {type});
+ const a = document.createElement('a');
+ a.href = URL.createObjectURL(bl);
+ a.download = title;
+ a.hidden = true;
+ document.body.appendChild(a);
+ a.click();
+ };
+
const saveHtml = async () => {
- const documentHtml = await renderHtml();
- if (documentHtml) {
- const htmlContent = [documentHtml];
- const bl = new Blob(htmlContent, {type: 'text/html'});
- const a = document.createElement('a');
- a.href = URL.createObjectURL(bl);
- a.download = 'jsight-document.html';
- a.hidden = true;
- document.body.appendChild(a);
- a.click();
+ const html = await renderHtml();
+ if (html) {
+ save(html, 'jsight-document.html', 'text/html');
+ }
+ };
+
+ const saveJson = async () => {
+ const json = await convertJsight(jsightCode, 'openapi-3.0.3', 'json');
+ if (json) {
+ save(json as string, 'jsight-document.json', 'text/json');
+ }
+ };
+
+ const saveYaml = async () => {
+ const yaml = await convertJsight(jsightCode, 'openapi-3.0.3', 'yaml');
+ if (yaml) {
+ save(yaml as string, 'jsight-document.yaml', 'application/yaml');
}
};
- return [saveHtml];
+ return {saveHtml, saveJson, saveYaml};
}
diff --git a/src/screens/Editor/Editor.styles.scss b/src/screens/Editor/Editor.styles.scss
index afc4e51..b4239fb 100644
--- a/src/screens/Editor/Editor.styles.scss
+++ b/src/screens/Editor/Editor.styles.scss
@@ -58,7 +58,17 @@
margin-left: 0;
margin-right: 0;
flex: 1;
- /* overflow-y: scroll; */
+
+ &.scrollable {
+ overflow-y: scroll;
+ }
+
+ &.disabled {
+ overflow: hidden;
+ opacity: 0.5;
+ pointer-events: none;
+ user-select: none;
+ }
.main-body {
padding: 0;
@@ -119,6 +129,11 @@
margin-bottom: 1rem;
font-size: 1rem;
}
+
+ &.disabled {
+ opacity: 0.5;
+ cursor: not-allowed;
+ }
}
}
}
diff --git a/src/screens/Editor/EditorScreen.export.tsx b/src/screens/Editor/EditorScreen.export.tsx
index bebf117..0e41290 100644
--- a/src/screens/Editor/EditorScreen.export.tsx
+++ b/src/screens/Editor/EditorScreen.export.tsx
@@ -8,12 +8,13 @@ import './Editor.styles.scss';
import 'react-toastify/dist/ReactToastify.css';
import {Contacts} from 'components/Modals/Contacts';
import {screenWidthMultiplier} from 'utils/screenWidthMultiplier';
-import {editorModeType, ErrorType, SidebarDocType} from 'types';
+import {editorModeType, ErrorType, HtmlDocPanelType, SidebarDocType} from 'types';
import {JDocContext, SidebarContext, EditorContext, CurrentUrlProvider} from 'store';
-import {getJDocExchange} from 'api/getJDocExchange';
import {showEditorError} from 'utils/showEditorError';
import {useDebounce} from 'hooks/useDebounce';
import {initCats} from 'screens/Editor/initCats';
+import {convertJsight} from 'api/convertJsight';
+import {notificationIds} from 'utils/notificationIds';
const {isExport} = window as any;
@@ -25,7 +26,8 @@ export const EditorScreen = () => {
const codeContentsSidebar = false;
//documentation sidebar on the right
- const [currentDocSidebar, setCurrentDocSidebar] = useState(null);
+ const [currentDocSidebar, setCurrentDocSidebar] = useState('htmldoc');
+ const [currentHtmlDocPanel, setCurrentHtmlDocPanel] = useState('none');
const [jdocExchange, setJdocExchange] = useState();
const jsightCodeDebounced = useDebounce(jsightCode, 600);
const [contactModalVisible, setContactModalVisible] = useState(false);
@@ -54,11 +56,11 @@ export const EditorScreen = () => {
(async () => {
if (!isExport) {
try {
- const jdocExchange = await getJDocExchange(jsightCodeDebounced);
- startTransition(() => setJdocExchange(jdocExchange));
+ const jdocExchange = await convertJsight(jsightCodeDebounced, 'jdoc-2.0');
+ startTransition(() => setJdocExchange(jdocExchange as JDocType));
toast.dismiss();
} catch (error) {
- showEditorError(error as ErrorType, () => {
+ showEditorError(error as ErrorType, notificationIds.ERROR_MESSAGE_DEFAULT_ID, () => {
if (!(error as ErrorType).Line) {
return;
}
@@ -78,23 +80,33 @@ export const EditorScreen = () => {
() =>
clsx({
'editor-wrapper-inner': true,
- 'rules-sidebar': currentDocSidebar === 'rules',
- 'content-sidebar': currentDocSidebar === 'content',
+ 'rules-sidebar': currentHtmlDocPanel === 'rules',
+ 'content-sidebar': currentHtmlDocPanel === 'content',
'code-sidebar': codeContentsSidebar,
}),
- [codeContentsSidebar, currentDocSidebar]
+ [codeContentsSidebar, currentHtmlDocPanel]
);
- const handleCurrentDocSidebar = useCallback((sidebar: SidebarDocType) => {
- setCurrentDocSidebar((prev) => (prev === sidebar ? null : sidebar));
+ const handleCurrentHtmlDocPanel = useCallback((htmldocpanel: HtmlDocPanelType) => {
+ setCurrentHtmlDocPanel((prev) => (prev === htmldocpanel ? 'none' : htmldocpanel));
}, []);
+ const jdocValue = useMemo(
+ () => ({
+ jdocExchange,
+ jsightCode: jsightCodeDebounced,
+ }),
+ [jdocExchange, jsightCodeDebounced]
+ );
+
const sidebarValue = useMemo(
() => ({
currentDocSidebar,
setCurrentDocSidebar,
+ currentHtmlDocPanel,
+ setCurrentHtmlDocPanel,
}),
- [currentDocSidebar]
+ [currentDocSidebar, currentHtmlDocPanel]
);
const editorValue = useMemo(
@@ -106,7 +118,7 @@ export const EditorScreen = () => {
);
return (
-
+
{
{isEditor && (
handleCurrentDocSidebar('content')}
+ onClick={() => handleCurrentHtmlDocPanel('content')}
className={clsx('side-panel-element', {
- active: currentDocSidebar === 'content',
+ active: currentHtmlDocPanel === 'content',
})}
>
Contents
diff --git a/src/screens/Editor/index.tsx b/src/screens/Editor/index.tsx
index ee306ef..a91e122 100644
--- a/src/screens/Editor/index.tsx
+++ b/src/screens/Editor/index.tsx
@@ -4,7 +4,6 @@ import {toast, ToastContainer} from 'react-toastify';
import {Resizable} from 're-resizable';
import {Editor} from 'components/Editor';
import {useDebounce} from 'hooks/useDebounce';
-import {getJDocExchange} from 'api/getJDocExchange';
import {JDocType} from 'types/exchange';
import {MainContent} from 'components/MainContent';
import {Layout} from 'components/Layout';
@@ -15,14 +14,27 @@ import {initCats, initDogs, initPigs, initJsonRpc} from './init';
import {Contacts} from 'components/Modals/Contacts';
import {HeaderDoc} from 'components/Header/HeaderDoc';
import {screenWidthMultiplier} from 'utils/screenWidthMultiplier';
-import {editorModeType, ExamplesType, SidebarDocType} from 'types';
+import {
+ editorModeType,
+ ExamplesType,
+ OpenApiFormatType,
+ SidebarDocType,
+ HtmlDocPanelType,
+} from 'types';
import {EditorContext, JDocContext, SidebarContext, SharingContext} from 'store';
import {CurrentUrlProvider} from 'store/CurrentUrlStore';
import {onOrientationChange} from 'utils/onOrientationChange';
+import {notificationIds} from 'utils/notificationIds';
import {ErrorScreen} from 'screens/Error';
import {SharingForm} from 'components/Modals/SharingForm';
import 'react-toastify/dist/ReactToastify.css';
import {AnnouncementBar} from 'components/AnnouncementBar';
+import {convertJsight} from 'api/convertJsight';
+
+import IconOpenAPI from 'assets/images/icons/openapi.svg';
+import IconHTMLDoc from 'assets/images/icons/htmldoc.svg';
+import IconContents from 'assets/images/icons/contents.svg';
+
import './Editor.styles.scss';
const {isExport} = window as any;
@@ -35,10 +47,13 @@ export const EditorScreen = () => {
const [jsightCode, setJsightCode] = useState
(
key ? '' : localStorage.getItem('jsightCode') || initCats
);
+ const [jdocExchangeError, setJdocExchangeError] = useState(false);
// left sidebar
const [codeContentsSidebar] = useState(false);
//documentation sidebar on the right
- const [currentDocSidebar, setCurrentDocSidebar] = useState(null);
+ const [currentDocSidebar, setCurrentDocSidebar] = useState('htmldoc');
+ const [currentOpenApiFormat, setCurrentOpenApiFormat] = useState('yaml');
+ const [currentHtmlDocPanel, setCurrentHtmlDocPanel] = useState('none');
const [jdocExchange, setJdocExchange] = useState();
const [errorRow, setErrorRow] = useState(null);
const [scrollToRow, setScrollToRow] = useState(false);
@@ -49,6 +64,7 @@ export const EditorScreen = () => {
const [error, setError] = useState(null);
const [disableSharing, setDisableSharing] = useState(true);
const isEditor = useMemo(() => viewMode === 'editor', [viewMode]);
+ const [isJdocLoading, setIsJdocLoading] = useState(false);
const [isShowAnnouncementBar, setIsShowAnnouncementBar] = useState(
!localStorage.getItem('announcement.bar.hidden')
);
@@ -87,6 +103,15 @@ export const EditorScreen = () => {
setEditorWidth(finalNewWidth);
};
+ useEffect(() => {
+ const isMobile = /Mobi|Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(
+ navigator.userAgent
+ );
+ if (isMobile) {
+ setCurrentDocSidebar('openapi');
+ }
+ }, []);
+
useEffect(() => {
const changeWidth = () => {
const width = getEditorWidth(screenWidth);
@@ -98,16 +123,19 @@ export const EditorScreen = () => {
});
useEffect(() => {
- if (jsightCodeDebounced !== undefined) {
+ if (currentDocSidebar === 'htmldoc' && jsightCodeDebounced !== undefined) {
(async () => {
if (!isExport) {
try {
- const jdocExchange = await getJDocExchange(jsightCodeDebounced);
- startTransition(() => setJdocExchange(jdocExchange));
+ setIsJdocLoading(true);
+ const jdocExchange = await convertJsight(jsightCodeDebounced, 'jdoc-2.0');
+ startTransition(() => setJdocExchange(jdocExchange as JDocType));
toast.dismiss();
setErrorRow(null);
+ setJdocExchangeError(false);
+ setIsJdocLoading(false);
} catch (error) {
- showEditorError(error as ErrorType, () => {
+ showEditorError(error as ErrorType, notificationIds.ERROR_MESSAGE_HTMLDOC_ID, () => {
if (!(error as ErrorType).Line) {
return;
}
@@ -116,6 +144,7 @@ export const EditorScreen = () => {
setTimeout(() => setScrollToRow(false), 500);
});
(error as ErrorType).Line && setErrorRow((error as ErrorType).Line);
+ setJdocExchangeError(true);
} finally {
localStorage.setItem('jsightCode', jsightCodeDebounced);
}
@@ -125,18 +154,17 @@ export const EditorScreen = () => {
}
})();
}
- // eslint-disable-next-line
- }, [jsightCodeDebounced]);
+ }, [currentDocSidebar, jsightCodeDebounced]);
const classes = useMemo(
() =>
clsx({
'editor-wrapper-inner': true,
- 'rules-sidebar': currentDocSidebar === 'rules',
- 'content-sidebar': currentDocSidebar === 'content',
+ 'rules-sidebar': currentHtmlDocPanel === 'rules',
+ 'content-sidebar': currentHtmlDocPanel === 'content',
'code-sidebar': codeContentsSidebar,
}),
- [codeContentsSidebar, currentDocSidebar]
+ [codeContentsSidebar, currentHtmlDocPanel]
);
const setInitJsightCode = (code: string) => {
@@ -175,7 +203,11 @@ export const EditorScreen = () => {
};
const handleCurrentDocSidebar = useCallback((sidebar: SidebarDocType) => {
- setCurrentDocSidebar((prev) => (prev === sidebar ? null : sidebar));
+ setCurrentDocSidebar((prev) => (prev === sidebar ? 'htmldoc' : sidebar));
+ }, []);
+
+ const handleCurrentHtmlDocPanel = useCallback((htmldocpanel: HtmlDocPanelType) => {
+ setCurrentHtmlDocPanel((prev) => (prev === htmldocpanel ? 'none' : htmldocpanel));
}, []);
const handleJsightCode = useCallback((code: string) => setJsightCode(code), []);
@@ -183,12 +215,24 @@ export const EditorScreen = () => {
const handleError = useCallback((error) => setError(error), []);
const handleReloadedEditor = useCallback(() => reloadedEditor(), []);
+ const jdocValue = useMemo(
+ () => ({
+ jdocExchange,
+ jsightCode: jsightCodeDebounced,
+ }),
+ [jdocExchange, jsightCodeDebounced]
+ );
+
const sidebarValue = useMemo(
() => ({
currentDocSidebar,
setCurrentDocSidebar,
+ currentOpenApiFormat,
+ setCurrentOpenApiFormat,
+ currentHtmlDocPanel,
+ setCurrentHtmlDocPanel,
}),
- [currentDocSidebar]
+ [currentDocSidebar, currentOpenApiFormat, currentHtmlDocPanel]
);
const editorValue = useMemo(
@@ -206,7 +250,7 @@ export const EditorScreen = () => {
}
return (
-
+
{
{!isExport ? (
{isEditor ? (
-
+
+
+
) : (
)}
@@ -271,19 +317,53 @@ export const EditorScreen = () => {
-
+
{isEditor && (
handleCurrentDocSidebar('content')}
+ onClick={() =>
+ currentDocSidebar !== 'openapi' && handleCurrentDocSidebar('openapi')
+ }
+ className={clsx('side-panel-element', {
+ active: currentDocSidebar === 'openapi',
+ })}
+ >
+
OpenAPI
+
+
handleCurrentDocSidebar('htmldoc')}
+ className={clsx('side-panel-element', {
+ active:
+ currentDocSidebar === 'htmldoc' &&
+ (currentHtmlDocPanel === 'rules' || currentHtmlDocPanel === 'content'),
+ })}
+ >
+
HTML Doc
+
+
+ currentDocSidebar !== 'openapi' && handleCurrentHtmlDocPanel('content')
+ }
className={clsx('side-panel-element', {
- active: currentDocSidebar === 'content',
+ active: currentHtmlDocPanel === 'content',
+ disabled: currentDocSidebar === 'openapi',
})}
+ title={
+ currentDocSidebar === 'openapi' ? 'Not available while in OpenAPI view' : ''
+ }
>
-
Contents
+
Contents
)}
diff --git a/src/store/JDocStore.ts b/src/store/JDocStore.ts
index 79f50fb..abe0912 100644
--- a/src/store/JDocStore.ts
+++ b/src/store/JDocStore.ts
@@ -1,4 +1,9 @@
import {createContext} from 'react';
import {JDocType} from 'types/exchange';
-export const JDocContext = createContext({} as JDocType | undefined);
+export interface JDocContextType {
+ jdocExchange: JDocType | undefined;
+ jsightCode: string;
+}
+
+export const JDocContext = createContext({} as JDocContextType);
diff --git a/src/store/SidebarStore.ts b/src/store/SidebarStore.ts
index 64304f1..211aec9 100644
--- a/src/store/SidebarStore.ts
+++ b/src/store/SidebarStore.ts
@@ -1,9 +1,14 @@
import React, {createContext} from 'react';
-import {SidebarDocType} from 'types';
+import {OpenApiFormatType, SidebarDocType} from 'types';
+import {HtmlDocPanelType} from 'types/htmldocpanel';
interface SidebarContextInterface {
currentDocSidebar: SidebarDocType;
setCurrentDocSidebar: React.Dispatch
>;
+ currentHtmlDocPanel: HtmlDocPanelType;
+ setCurrentHtmlDocPanel: React.Dispatch>;
+ currentOpenApiFormat?: OpenApiFormatType;
+ setCurrentOpenApiFormat?: React.Dispatch>;
}
export const SidebarContext = createContext({} as SidebarContextInterface);
diff --git a/src/styles/_variables.scss b/src/styles/_variables.scss
index 7d7acf9..51354b3 100644
--- a/src/styles/_variables.scss
+++ b/src/styles/_variables.scss
@@ -18,6 +18,7 @@ $secondary-azure: #6acccb;
$secondary-red: #c83b27;
$secondary-oxley: #729682;
$secondary-stroke: #dbdbe1;
+$secondary-grey: #f5f5f7;
/** CODE HIGHLIGHT **/
$code-rule: #54a4d3;
diff --git a/src/types/converter.ts b/src/types/converter.ts
new file mode 100644
index 0000000..d316c9b
--- /dev/null
+++ b/src/types/converter.ts
@@ -0,0 +1,2 @@
+export type ConvertDestinationType = 'jdoc-2.0' | 'openapi-3.0.3';
+export type OpenApiFormatType = 'json' | 'yaml';
diff --git a/src/types/htmldocpanel.ts b/src/types/htmldocpanel.ts
new file mode 100644
index 0000000..f61cd56
--- /dev/null
+++ b/src/types/htmldocpanel.ts
@@ -0,0 +1 @@
+export type HtmlDocPanelType = 'none' | 'content' | 'rules';
diff --git a/src/types/index.ts b/src/types/index.ts
index f78b14b..1cc8d08 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -2,5 +2,7 @@ export * from './editor';
export * from './error';
export * from './router';
export * from './sidebar';
+export * from './htmldocpanel';
export * from './exchange';
export * from './header';
+export * from './converter';
diff --git a/src/types/sidebar.ts b/src/types/sidebar.ts
index 6b3269a..72dc8d1 100644
--- a/src/types/sidebar.ts
+++ b/src/types/sidebar.ts
@@ -1 +1 @@
-export type SidebarDocType = 'content' | 'rules' | null;
+export type SidebarDocType = 'openapi' | 'htmldoc';
diff --git a/src/utils/getError.ts b/src/utils/getError.ts
index 4ae3d60..3416cb8 100644
--- a/src/utils/getError.ts
+++ b/src/utils/getError.ts
@@ -6,12 +6,10 @@ export const getErrorTitle = (error: ErrorType | undefined) => {
};
export const getError = (error: ErrorType) => {
- if (!error?.Line) {
- return 'Server error, try again later';
- }
-
const errorMessage = error.Message;
- return errorMessage.charAt(0).toUpperCase() + errorMessage.slice(1);
+ return errorMessage
+ ? errorMessage.charAt(0).toUpperCase() + errorMessage.slice(1)
+ : 'No connection';
};
export const getDefaultErrorMessages = (status: number) => {
diff --git a/src/utils/notificationIds.ts b/src/utils/notificationIds.ts
index 64d1071..c727452 100644
--- a/src/utils/notificationIds.ts
+++ b/src/utils/notificationIds.ts
@@ -2,4 +2,6 @@ export const notificationIds = {
ERROR_MESSAGE_DEFAULT_ID: 1,
ERROR_MESSAGE_SHARING_ID: 2,
SUCCESS_MESSAGE_DEFAULT_ID: 3,
+ ERROR_MESSAGE_HTMLDOC_ID: 4,
+ ERROR_MESSAGE_OPENAPI_ID: 5,
};
diff --git a/src/utils/runRequest.ts b/src/utils/runRequest.ts
index dd0e169..4f9a1c1 100644
--- a/src/utils/runRequest.ts
+++ b/src/utils/runRequest.ts
@@ -8,13 +8,19 @@ const defaultError: ErrorType = {
Status: 'Error',
};
+interface RequestAddParams {
+ responseAsText?: boolean;
+ timeout?: number;
+ times?: number;
+}
+
export const runRequest = async (
action: string,
{body, headers, method}: RequestInit = {},
- timeout = 0,
- times = 0
+ addParams?: RequestAddParams
): Promise => {
const fetchParams: RequestInit = {headers, body, method: method || 'POST'};
+ const {responseAsText = false, timeout = 0, times = 0} = addParams || {};
let id: any;
if (timeout > 0) {
@@ -31,7 +37,7 @@ export const runRequest = async (
if (!window.navigator.onLine && timeout > 0) {
return new Promise((resolve) => {
setTimeout(() => {
- resolve(runRequest(action, fetchParams, timeout, times + 1));
+ resolve(runRequest(action, fetchParams, {responseAsText, timeout, times: times + 1}));
}, 1000);
});
}
@@ -40,8 +46,12 @@ export const runRequest = async (
if (response.ok) {
const text = await response.text();
try {
- const json = JSON.parse(text);
- return json;
+ if (responseAsText) {
+ return text;
+ } else {
+ const json = JSON.parse(text);
+ return json;
+ }
} catch (err) {
return text;
}
diff --git a/src/utils/showEditorError.tsx b/src/utils/showEditorError.tsx
index 766c254..547c423 100644
--- a/src/utils/showEditorError.tsx
+++ b/src/utils/showEditorError.tsx
@@ -5,6 +5,7 @@ import {getError, getErrorTitle} from 'utils/getError';
import {notificationIds} from 'utils/notificationIds';
import {EditorErrorNotification} from 'components/Notifications/EditorErrorNotification';
import {IconError} from 'components/Notifications/IconError';
+import {updateMessageWithUrl} from './updateMessageWithUrl';
const {ERROR_MESSAGE_DEFAULT_ID} = notificationIds;
@@ -19,19 +20,28 @@ const showErrorOptions: ToastOptions = {
icon: IconError,
};
-export const showEditorError = (error: ErrorType, setScrollToRow: () => void) => {
+export const showEditorError = (error: ErrorType, toastId: number, setScrollToRow: () => void) => {
const title = getErrorTitle(error);
- const message = getError(error);
+ const errorMessage = getError(error);
+ const messageWithLink = updateMessageWithUrl(errorMessage);
- if (!toast.isActive(ERROR_MESSAGE_DEFAULT_ID)) {
+ if (!toast.isActive(toastId)) {
toast.warning(
- ,
- showErrorOptions
+ ,
+ {...showErrorOptions, toastId}
);
} else {
- toast.update(ERROR_MESSAGE_DEFAULT_ID, {
+ toast.update(toastId, {
render: (
-
+
),
});
}
diff --git a/src/utils/updateMessageWithUrl.ts b/src/utils/updateMessageWithUrl.ts
new file mode 100644
index 0000000..26d3c1d
--- /dev/null
+++ b/src/utils/updateMessageWithUrl.ts
@@ -0,0 +1,5 @@
+export const updateMessageWithUrl = (message: string) => {
+ const pattern = /(https?:\/\/[^\s]+)/gi;
+
+ return message.replace(pattern, '$1 ');
+};
diff --git a/tests/manual-tests/!BEFORE-TESTING.md b/tests/manual-tests/!BEFORE-TESTING.md
new file mode 100644
index 0000000..3942e84
--- /dev/null
+++ b/tests/manual-tests/!BEFORE-TESTING.md
@@ -0,0 +1,3 @@
+# Before manual testing
+
+1. Update all your browsers to the latest stable versions.
\ No newline at end of file
diff --git a/tests/manual-tests/all-features-test.jst b/tests/manual-tests/all-features-test.jst
index ebe96e8..7680ccd 100644
--- a/tests/manual-tests/all-features-test.jst
+++ b/tests/manual-tests/all-features-test.jst
@@ -1,442 +1,442 @@
-JSIGHT 0.3
-
-INFO
- Title "\"Catsbook\" social network API"
- Description
- (
- **Catsbook** social network API.
-
- # API purpose
-
- This example uses all the features of
- *JSight API 0.3* language.
-
- Among others:
-
- - one,
- - two,
- - three.
-
- And lets look on the table:
-
- ## The table
-
- | Header | Header |
- | ------- | ------- |
- | Cell | Cell |
- | Cell | Cell |
- )
- Version 1.0
-
-SERVER @DEV // Developers server.
- BaseUrl "192.168.0.100"
-
-SERVER @PROD
- BaseUrl "https://{env}.catsbook.com/api/{version}/{locale}/"
-
-#------------------------------------------- CATS ------------------------------------------------------
-
-URL /cats
-
- GET /* Get all
- the cats. */
- Query "page=1&per_page=50&filter[size]=XXL"
- {
- "page": 1,
- "per_page": 50, // {optional: true, max: 100}
- "filter": { // {optional: true}
- "size": "XXL", // {optional: true } - Cat size filter. # TODO: enum: "@catSizeEnum"
- "age" : 12 // {optional: true } - Cat age filter.
- }
- }
-
- 200 // Cat’s list.
- Headers
- { # we shouldn't forget to add "additionalProperties: true" to JDoc Exchange Schema
- "content-type": "application/json" // {const: true}
- }
- Body [@cat]
-
- 500
- { # Body omited
- "ErrorMessage" : "Something is terribly wrong!"
- }
-
- Headers
- {} // {allOf: "@standardHeaders"}
-
- 500
- @serverError # Body omited
-
- POST // Create a new cat.
- Description
- You must be very carefull
- when creating a new cat.
-
- Do not be disturbed!
-
- Request @cat
-
- 200 @cat
-
- PASTE @commonErrors
-
-URL /cats/{id}
-(
- Path
- {
- "id": @catId // Cat’s id.
- }
-
- GET // Get a cat by it’s id.
- Description
- Returns a cat’s definition by it’s id.
-
- 200 @cat // Take your cat!
-
- 500 @serverError
-
- 404 empty
-
- PUT // Update cat completely.
-
- Request jsight
- @cat
-
- 200
- Body @cat
-
- 500 any
-
- PATCH // Change cat’s mood status.
- Request
- { # Request and Body are omited.
- "moodStatus": "happy" // {enum: ["happy", "gloomy"]}
- }
-
- 200
- Body # Body without parameters.
- {
- "moodStatus": "happy" // {enum: ["happy", "gloomy"]}
- }
-
- 500
- Body regex
- /Error/
-
- DELETE // Delete a cat.
- Query "force=1" htmlFormEncoded
- {
- "force": 1 // {optional: true, enum: [0,1]} - Means, should API delete a cat if it has some friends.
- }
-
- # we do not specify responses, which mean that any response is possible.
-)
-
-URL /cats/friends
- GET
- 200 [@cat]
- #TODO: @COMMON_ERRORS_DIR
-
-URL "/cats/enemies"
- GET
- 200
- [ // {type: "array", maxItems: 100}
- @pig,
- @dog | @pig
- ]
-
-
-URL /cats/astronauts
- GET // Get all the cats-astronauts.
- 200
- Body jsight
- {} // {allOf: ["@cat", "@astronaut"]}
-
-#------------------------------------------- PETS ------------------------------------------------------
-
-GET /pets // Get all pets.
- Query htmlFormEncoded
- @standardQuery
-
- 200 [@pet]
-
-GET /pets/{passportNumber} // Get all pets by passport number.
- Path
- @petPathVariables
-
- 200 [@pet]
-
-#------------------------------------------- DOGS ------------------------------------------------------
-
-URL /dogs
-
- GET // Get all dogs (paged list).
- Query
- { // {allOf: "@standardQuery"}
- "page": 1,
- "per_page": 50, // {type: "integer", max: 100, optional: true}
- "filter": { // {optional: true}
- "age" : 12, // {optional: true} - Dog age filter.
- "canHunt": true /* {type: "boolean", optional: true}
- - Hunting ability filter. */
- }
- }
-
- 200
- [ // {minItems: 0, maxItems: 100}
- @dog
- ]
-
- POST // Create a new dog.
- Request
- Headers
- @standardHeaders
- Body @dog
-
- # no responses specified — it means that any response is possible.
-
-GET /dogs/{id} // Get a dog by it’s id.
- 200 @dog
-
-POST /dogs/{id} // Replace a dog completely (exact copy of PUT /dogs/{id} method).
- Request
- @dog
-
- 200 @dog
-
-PATCH /dogs/{id}
- Request
- { # Body is omited.
- "moodStatus": "happy"
- }
- Headers
- { // {allOf: "@standardHeaders"}
- "content-type": "application/json"
- }
-
- 200 // Status is successfully changed.
- "OK" // {const: true}
-
-URL /dogs/{id}
- # Path is not specified deliberately.
-
- PUT # Annotation is not specified.
- Request
- Headers
- {
- "content-type": "application/json" // {const: true}
- }
-
- Body
- { // {allOf: "@pet"}
- "id" : "DOG-123", // {type: "string", regex: "DOG-\\d+"}
- "canHunt" : false,
- "maxToothLength" : 0.013
- }
-
- 200 @dog
-
-GET /extremely-wierd-endpoint
- Query "myVeryStrange[way]of%20query=string\\encoding" noFormat
- {
- "myVeryStrange": [
- "way"
- ],
- "of query": "string\\encoding"
- }
-
- 200
- @very_strange_type_123
-
-
-#------------------------------------------- JSON RPC ---------------------------------------------------
-
-URL /json-rpc-api
- Protocol json-rpc-2.0
- Method getCat /* Get a cat by its id. */
- Params
- {
- "id": @catId // Cat's id.
- }
- Result
- @cat
- Method getAllcats // Returns all cats.
- Params
- {
- "limit": 30, // {min: 1, max: 1000}
- "offset": 0 // {min: 0}
- }
- Result
- {
- "itemsCount": 30,
- "offset": 0,
- "items": [@cat]
- }
-
-#------------------------------------------- TYPES ------------------------------------------------------
-
-TYPE @cat // A cat.
-{ // {allOf: "@pet"}
- "id" : "CAT-123", // {type: "@catId"} - Cat’s id.
- "size" : "XXL", // # TODO: {enum: "@catSizeEnum"}
- "tailHeight" : 0.743, // {type: "float"}
- "friends" : @catList, // {optional: true} # here we check recursive types.
- "enemies": {
- "dogs": { // {additionalProperties: true}
- @dogId: @dog // {optional: true}
- }
- },
- "playing": {
- "likesToPlay" : true,
- "prefferedMouseColor": "white" // {enum: ["white", "gray"]}
- }
-}
-
-TYPE @dog /* A dog. */
-{ // {allOf: "@pet"}
- "id" : "DOG-123", // {type: "string", regex: "DOG-\\d+"}
- "canHunt" : false,
- "maxToothLength" : 0.013
-}
-
-TYPE @pig // A pig.
-{ // {allOf: "@animal"}
- "id": "PIG-123",
- "lastWashTime" : "2006-01-02T15:04:05+07:00" // { type: "datetime"}
-}
-
-TYPE @pet
-{ // {allOf: "@animal"}
- "passportNumber": 1234123212, /* {or: [
- {type: "integer"},
- {type: "string" , minLength: 10, maxLength: 10}
- ]} */
- "name" : "Thomas the Great",
- "email" : "thomas@catsbook.com", // {type: "email"}
- "website" : "http://www.thomas-the-great.com", // {type: "uri", nullable: true}
- # One pet can have several owners.
- "owners" : [ // Owners
- { // Owner
- "id" : "550e8400-e29b-41d4-a716-446655440000", // {type: "uuid"} - Owners id. # Some text comment.
- "name" : "John"
- }
- ]
-}
-
-TYPE @animal
-{
- "type" : @animalType,
- "moodStatus" : "happy", // {type: "enum", enum: ["happy", "gloomy"]}
- ###
- `age` is calculated by `birthday`.
- ###
- "age" : 12, // {min: 0, max: 600}
- "weight" : 2.5, /* {min: 0, exclusiveMinimum: true,
- max: 6000, exclusiveMaximum: false} */
- "birthday" : "2006-01-02" // {type: "date"}
-}
-
-TYPE @astronaut jsight // An astronaut.
-{ // {type: "object"}
- "spaceSuitSize": 4, // {min: 1, max: 5}
- "salary" : 422.34, // {precision: 2}
- "taxes" : 12.34 // {type: "decimal", precision: 2}
-}
-
-TYPE @catId regex
- /CAT-\d+/
-
-TYPE @dogId
- "DOG-12341" // {regex: "DOG-\\d+", minLength: 4, maxLength: 255}
-
-TYPE @animalType jsight
- "cat" /* {enum: [
- "cat",
- "dog",
- "pig",
- "frog"
- ]}
- */
-
-###
-TODO:
- "cat" /*
- {enum: [
- // Domestic
- "cat", // Cat
- "dog", // Dog
- "pig", // Pig
- /* Wild */
- "frog" /* Frog */
- ]}
- */
-###
-
-TYPE @very_strange_type_123 jsight
-{
- "nullField" : null,
- "wierdEnum" : 1 , // {enum: [1, 2, "a", "b", true, false, null]}
- "anyField" : {}, // {type: "any"}
- "astronautHtmlForm" : "spaceSuitSize=4&salary=422.34&taxes=12.34" # TODO: /*
- # {serializeFormat: "htmlFormEncoded", serializedType: "@astronaut"} */
-}
-
-TYPE @serverError
-{
- "errorCode" : 123,
- "errorMessage": "All is bad"
-}
-
-TYPE @standardQuery
-{
- "debug": 1 // {const: true, optional: true}
-}
-
-TYPE @standardHeaders
-{
- "Authorization": "bearer asdfasdfasdfasdf" // {optional: true}
-}
-
-###
-Here we check block comments.
-TODO: We need more perfect tests of block comments.
-###
-
-TYPE @petPathVariables
-{
- "passportNumber": 12312312
-}
-
-TYPE @catList
-[
- @cat
-]
-
-#------------------------------------------------- ENUMS -----------------------------------------------
-
-###
-TODO:
-ENUM @catSizeEnum // Cat’s sizes.
-[
- // Small cats.
- "S",
- "M",
- // Normal cats.
- "L",
- /* Huge
- cats */
- "XL",
- "XXL"
-]
-###
-
-
-#--------------------------------------------------- MACROS ------------------------------------
-MACRO @commonErrors
-(
- 404
- Body regex
- /Bad request./
- 500 any
+JSIGHT 0.3
+
+INFO
+ Title "\"Catsbook\" social network API (jtest)"
+ Description
+ (
+ **Catsbook** social network API.
+
+ # API purpose
+
+ This example uses all the features of
+ *JSight API 0.3* language.
+
+ Among others:
+
+ - one,
+ - two,
+ - three.
+
+ And lets look on the table:
+
+ ## The table
+
+ | Header | Header |
+ | ------- | ------- |
+ | Cell | Cell |
+ | Cell | Cell |
+ )
+ Version 1.0
+
+SERVER @DEV // Developers server.
+ BaseUrl "192.168.0.100"
+
+SERVER @PROD
+ BaseUrl "https://{env}.catsbook.com/api/{version}/{locale}/"
+
+#------------------------------------------- CATS ------------------------------------------------------
+
+URL /cats
+
+ GET /* Get all
+ the cats. */
+ Query "page=1&per_page=50&filter[size]=XXL"
+ {
+ "page": 1,
+ "per_page": 50, // {optional: true, max: 100}
+ "filter": { // {optional: true}
+ "size": "XXL", // {optional: true } - Cat size filter. # TODO: enum: "@catSizeEnum"
+ "age" : 12 // {optional: true } - Cat age filter.
+ }
+ }
+
+ 200 // Cat’s list.
+ Headers
+ { # we shouldn't forget to add "additionalProperties: true" to JDoc Exchange Schema
+ "content-type": "application/json" // {const: true}
+ }
+ Body [@cat]
+
+ 500
+ { # Body omited
+ "ErrorMessage" : "Something is terribly wrong!"
+ }
+
+ Headers
+ {} // {allOf: "@standardHeaders"}
+
+ 500
+ @serverError # Body omited
+
+ POST // Create a new cat.
+ Description
+ You must be very carefull
+ when creating a new cat.
+
+ Do not be disturbed!
+
+ Request @cat
+
+ 200 @cat
+
+ PASTE @commonErrors
+
+URL /cats/{id}
+(
+ Path
+ {
+ "id": @catId // Cat’s id.
+ }
+
+ GET // Get a cat by it’s id.
+ Description
+ Returns a cat’s definition by it’s id.
+
+ 200 @cat // Take your cat!
+
+ 500 @serverError
+
+ 404 empty
+
+ PUT // Update cat completely.
+
+ Request jsight
+ @cat
+
+ 200
+ Body @cat
+
+ 500 any
+
+ PATCH // Change cat’s mood status.
+ Request
+ { # Request and Body are omited.
+ "moodStatus": "happy" // {enum: ["happy", "gloomy"]}
+ }
+
+ 200
+ Body # Body without parameters.
+ {
+ "moodStatus": "happy" // {enum: ["happy", "gloomy"]}
+ }
+
+ 500
+ Body regex
+ /Error/
+
+ DELETE // Delete a cat.
+ Query "force=1" htmlFormEncoded
+ {
+ "force": 1 // {optional: true, enum: [0,1]} - Means, should API delete a cat if it has some friends.
+ }
+
+ # we do not specify responses, which mean that any response is possible.
+)
+
+URL /cats/friends
+ GET
+ 200 [@cat]
+ #TODO: @COMMON_ERRORS_DIR
+
+URL "/cats/enemies"
+ GET
+ 200
+ [ // {type: "array", maxItems: 100}
+ @pig,
+ @dog | @pig
+ ]
+
+
+URL /cats/astronauts
+ GET // Get all the cats-astronauts.
+ 200
+ Body jsight
+ {} // {allOf: ["@cat", "@astronaut"]}
+
+#------------------------------------------- PETS ------------------------------------------------------
+
+GET /pets // Get all pets.
+ Query htmlFormEncoded
+ @standardQuery
+
+ 200 [@pet]
+
+GET /pets/{passportNumber} // Get all pets by passport number.
+ Path
+ @petPathVariables
+
+ 200 [@pet]
+
+#------------------------------------------- DOGS ------------------------------------------------------
+
+URL /dogs
+
+ GET // Get all dogs (paged list).
+ Query
+ { // {allOf: "@standardQuery"}
+ "page": 1,
+ "per_page": 50, // {type: "integer", max: 100, optional: true}
+ "filter": { // {optional: true}
+ "age" : 12, // {optional: true} - Dog age filter.
+ "canHunt": true /* {type: "boolean", optional: true}
+ - Hunting ability filter. */
+ }
+ }
+
+ 200
+ [ // {minItems: 0, maxItems: 100}
+ @dog
+ ]
+
+ POST // Create a new dog.
+ Request
+ Headers
+ @standardHeaders
+ Body @dog
+
+ # no responses specified — it means that any response is possible.
+
+GET /dogs/{id} // Get a dog by it’s id.
+ 200 @dog
+
+POST /dogs/{id} // Replace a dog completely (exact copy of PUT /dogs/{id} method).
+ Request
+ @dog
+
+ 200 @dog
+
+PATCH /dogs/{id}
+ Request
+ { # Body is omited.
+ "moodStatus": "happy"
+ }
+ Headers
+ { // {allOf: "@standardHeaders"}
+ "content-type": "application/json"
+ }
+
+ 200 // Status is successfully changed.
+ "OK" // {const: true}
+
+URL /dogs/{id}
+ # Path is not specified deliberately.
+
+ PUT # Annotation is not specified.
+ Request
+ Headers
+ {
+ "content-type": "application/json" // {const: true}
+ }
+
+ Body
+ { // {allOf: "@pet"}
+ "id" : "DOG-123", // {type: "string", regex: "DOG-\\d+"}
+ "canHunt" : false,
+ "maxToothLength" : 0.013
+ }
+
+ 200 @dog
+
+GET /extremely-wierd-endpoint
+ Query "myVeryStrange[way]of%20query=string\\encoding" noFormat
+ {
+ "myVeryStrange": [
+ "way"
+ ],
+ "of query": "string\\encoding"
+ }
+
+ 200
+ @very_strange_type_123
+
+
+#------------------------------------------- JSON RPC ---------------------------------------------------
+
+URL /json-rpc-api
+ Protocol json-rpc-2.0
+ Method getCat /* Get a cat by its id. */
+ Params
+ {
+ "id": @catId // Cat's id.
+ }
+ Result
+ @cat
+ Method getAllcats // Returns all cats.
+ Params
+ {
+ "limit": 30, // {min: 1, max: 1000}
+ "offset": 0 // {min: 0}
+ }
+ Result
+ {
+ "itemsCount": 30,
+ "offset": 0,
+ "items": [@cat]
+ }
+
+#------------------------------------------- TYPES ------------------------------------------------------
+
+TYPE @cat // A cat.
+{ // {allOf: "@pet"}
+ "id" : "CAT-123", // {type: "@catId"} - Cat’s id.
+ "size" : "XXL", // # TODO: {enum: "@catSizeEnum"}
+ "tailHeight" : 0.743, // {type: "float"}
+ "friends" : @catList, // {optional: true} # here we check recursive types.
+ "enemies": {
+ "dogs": { // {additionalProperties: true}
+ @dogId: @dog // {optional: true}
+ }
+ },
+ "playing": {
+ "likesToPlay" : true,
+ "prefferedMouseColor": "white" // {enum: ["white", "gray"]}
+ }
+}
+
+TYPE @dog /* A dog. */
+{ // {allOf: "@pet"}
+ "id" : "DOG-123", // {type: "string", regex: "DOG-\\d+"}
+ "canHunt" : false,
+ "maxToothLength" : 0.013
+}
+
+TYPE @pig // A pig.
+{ // {allOf: "@animal"}
+ "id": "PIG-123",
+ "lastWashTime" : "2006-01-02T15:04:05+07:00" // { type: "datetime"}
+}
+
+TYPE @pet
+{ // {allOf: "@animal"}
+ "passportNumber": 1234123212, /* {or: [
+ {type: "integer"},
+ {type: "string" , minLength: 10, maxLength: 10}
+ ]} */
+ "name" : "Thomas the Great",
+ "email" : "thomas@catsbook.com", // {type: "email"}
+ "website" : "http://www.thomas-the-great.com", // {type: "uri", nullable: true}
+ # One pet can have several owners.
+ "owners" : [ // Owners
+ { // Owner
+ "id" : "550e8400-e29b-41d4-a716-446655440000", // {type: "uuid"} - Owners id. # Some text comment.
+ "name" : "John"
+ }
+ ]
+}
+
+TYPE @animal
+{
+ "type" : @animalType,
+ "moodStatus" : "happy", // {type: "enum", enum: ["happy", "gloomy"]}
+ ###
+ `age` is calculated by `birthday`.
+ ###
+ "age" : 12, // {min: 0, max: 600}
+ "weight" : 2.5, /* {min: 0, exclusiveMinimum: true,
+ max: 6000, exclusiveMaximum: false} */
+ "birthday" : "2006-01-02" // {type: "date"}
+}
+
+TYPE @astronaut jsight // An astronaut.
+{ // {type: "object"}
+ "spaceSuitSize": 4, // {min: 1, max: 5}
+ "salary" : 422.34, // {precision: 2}
+ "taxes" : 12.34 // {type: "decimal", precision: 2}
+}
+
+TYPE @catId regex
+ /CAT-\d+/
+
+TYPE @dogId
+ "DOG-12341" // {regex: "DOG-\\d+", minLength: 4, maxLength: 255}
+
+TYPE @animalType jsight
+ "cat" /* {enum: [
+ "cat",
+ "dog",
+ "pig",
+ "frog"
+ ]}
+ */
+
+###
+TODO:
+ "cat" /*
+ {enum: [
+ // Domestic
+ "cat", // Cat
+ "dog", // Dog
+ "pig", // Pig
+ /* Wild */
+ "frog" /* Frog */
+ ]}
+ */
+###
+
+TYPE @very_strange_type_123 jsight
+{
+ "nullField" : null,
+ "wierdEnum" : 1 , // {enum: [1, 2, "a", "b", true, false, null]}
+ "anyField" : {}, // {type: "any"}
+ "astronautHtmlForm" : "spaceSuitSize=4&salary=422.34&taxes=12.34" # TODO: /*
+ # {serializeFormat: "htmlFormEncoded", serializedType: "@astronaut"} */
+}
+
+TYPE @serverError
+{
+ "errorCode" : 123,
+ "errorMessage": "All is bad"
+}
+
+TYPE @standardQuery
+{
+ "debug": 1 // {const: true, optional: true}
+}
+
+TYPE @standardHeaders
+{
+ "Authorization": "bearer asdfasdfasdfasdf" // {optional: true}
+}
+
+###
+Here we check block comments.
+TODO: We need more perfect tests of block comments.
+###
+
+TYPE @petPathVariables
+{
+ "passportNumber": 12312312
+}
+
+TYPE @catList
+[
+ @cat
+]
+
+#------------------------------------------------- ENUMS -----------------------------------------------
+
+###
+TODO:
+ENUM @catSizeEnum // Cat’s sizes.
+[
+ // Small cats.
+ "S",
+ "M",
+ // Normal cats.
+ "L",
+ /* Huge
+ cats */
+ "XL",
+ "XXL"
+]
+###
+
+
+#--------------------------------------------------- MACROS ------------------------------------
+MACRO @commonErrors
+(
+ 404
+ Body regex
+ /Bad request./
+ 500 any
)
\ No newline at end of file
diff --git a/tests/manual-tests/code-view-tests/code-view-tests.jst b/tests/manual-tests/code-view-tests/code-view-tests.jst
index 6f74b60..2af577f 100644
--- a/tests/manual-tests/code-view-tests/code-view-tests.jst
+++ b/tests/manual-tests/code-view-tests/code-view-tests.jst
@@ -376,7 +376,7 @@ TYPE @testAllOfInside
}
}
-TYPE @testAllOfRedundandComma /* Check that there is no redundand comma after last @cat property.
+TYPE @testAllOfRedundandComma /* Check that there is no redundand comma after the last property.
TODO: add to auto tests. */
{} // {allOf: "@allOfBase"}
diff --git a/tests/manual-tests/common-exported-html-ui-tests.md b/tests/manual-tests/common-exported-html-ui-tests.md
index f640571..6179eff 100644
--- a/tests/manual-tests/common-exported-html-ui-tests.md
+++ b/tests/manual-tests/common-exported-html-ui-tests.md
@@ -1,59 +1,59 @@
-# Run all the tests for editor view
-
-1. Annotations tests
-2. Code View Tests.
-3. Directive TYPE tests.
-4. Frontend load tests.
-5. HTTP-method tests.
-6. JSON-RPC tests.
-7. INFO and SERVER tests.
-8. Common Syntax tests.
-9. Markdown tests.
-10. Details card tests.
-11. Table View tests.
-12. Settings tests.
-
-# Contents Sidebar tests
-
-1. Check positioning after item click.
-2. Check that after click on some content item you can refresh page by Ctrl+Shift+R. Especially
- check it on paths with parameters, e. g. `/cats/{id}`.
-3. Check that Contents works fine when there are a huge amount of items (vertical scroll must work).
-
-# Logo
-
-1. Check that "Powered by JSight" panel click directs to https://jsight.io/ (must be opened in the
- new tab).
-
-# Upload
-
-1. Review all resources, which are uploaded during opening the HTML file. Only fonts and images must
- be loaded. No code, no css (both code and css must be embedded in the file).
-
-## Virtual Scroll
-
-### Check smooth scroll up and down
-
-### Check scroll up and down using Pg Up, Pg Down, Cursor Down Arrow, Cursor Up Arrow
-
-### Schema section must remember its state
-
-1. Change something in doc field, e. g.:
- - schema section mode (e. g. Expand Types, Table View, Code View);
- - expand some type;
- - switch to some method (e. g. from GET to POST).
-2. Scroll up or down and come back.
-3. Check that schema section is in the same state as it was before scroll.
-
-### Servers section must remember its state
-
-1. Open Servers section.
-2. Scroll down deeply and come back.
-3. Check Servers section is still opened.
-
-### Details card
-
-1. Check that you can close details card using either cross-mark near the top right corner of card
- or with the cross-mark at the top right corner of rendered document panel.
-2. Check that these two cross-marks (see above) do not interfere each other when scrolling document
+# Run all the tests for editor view
+
+1. Annotations tests
+2. Code View Tests.
+3. Directive TYPE tests.
+4. Frontend load tests.
+5. HTTP-method tests.
+6. JSON-RPC tests.
+7. INFO and SERVER tests.
+8. Common Syntax tests.
+9. Markdown tests.
+10. Details card tests.
+11. Table View tests.
+12. Settings tests.
+
+# Contents Sidebar tests
+
+1. Check positioning after item click.
+2. Check that after click on some content item you can refresh page by Ctrl+Shift+R. Especially
+ check it on paths with parameters, e. g. `/cats/{id}`.
+3. Check that Contents works fine when there are a huge amount of items (vertical scroll must work).
+
+# Logo
+
+1. Check that "Powered by JSight" panel click directs to https://jsight.io/ (must be opened in the
+ new tab).
+
+# Upload
+
+1. Review all resources, which are uploaded during opening the HTML file. Only fonts and images must
+ be loaded. No code, no css (both code and css must be embedded in the file).
+
+## Virtual Scroll
+
+### Check smooth scroll up and down
+
+### Check scroll up and down using Pg Up, Pg Down, Cursor Down Arrow, Cursor Up Arrow
+
+### Schema section must remember its state
+
+1. Change something in doc field, e. g.:
+ - schema section mode (e. g. Expand Types, Table View, Code View);
+ - expand some type;
+ - switch to some method (e. g. from GET to POST).
+2. Scroll up or down and come back.
+3. Check that schema section is in the same state as it was before scroll.
+
+### Servers section must remember its state
+
+1. Open Servers section.
+2. Scroll down deeply and come back.
+3. Check Servers section is still opened.
+
+### Details card
+
+1. Check that you can close details card using either cross-mark near the top right corner of card
+ or with the cross-mark at the top right corner of rendered document panel.
+2. Check that these two cross-marks (see above) do not interfere each other when scrolling document
up and down.
\ No newline at end of file
diff --git a/tests/manual-tests/common-syntax-test.jst b/tests/manual-tests/common-syntax-test.jst
index bc36c93..a0301c6 100644
--- a/tests/manual-tests/common-syntax-test.jst
+++ b/tests/manual-tests/common-syntax-test.jst
@@ -2,7 +2,7 @@ JSIGHT 0.3
GET /test-directive/parameters-escaping
Query "check quotation mark escaping \" and backslash escaping \\ "
- null
+ {}
GET /test-directive/explicit-boundaries
Description
diff --git a/tests/manual-tests/common-ui-tests.md b/tests/manual-tests/common-ui-tests.md
index c492ea2..bd0dbf1 100644
--- a/tests/manual-tests/common-ui-tests.md
+++ b/tests/manual-tests/common-ui-tests.md
@@ -73,8 +73,10 @@ Code content should not be changed.
something in the code. Check that documentation stays in the same place after refresh and do not
scroll back to the previous position.
6. Check that Contents works fine when there are a huge amount of items (vertical scroll must work).
+7. Try to change a JSight code, when the Contents tab is opened, and check, that the HTML doc is
+ updated.
-# Give us a star popup panel
+## Give us a star popup panel
1. Check the github link (must be opened in the new tab).
2. Close the popup.
diff --git a/tests/manual-tests/directives-tests/directive-title-test.jst b/tests/manual-tests/directives-tests/directive-title-test.jst
index 87801f4..42d0a7a 100644
--- a/tests/manual-tests/directives-tests/directive-title-test.jst
+++ b/tests/manual-tests/directives-tests/directive-title-test.jst
@@ -8,6 +8,6 @@
JSIGHT 0.3
INFO
- Title "My API"
+ Title "My API (jtest)" # always use `jtest` in test titles for the sake of statistics
GET /cats
\ No newline at end of file
diff --git a/tests/manual-tests/directives-tests/directives-info-and-server-tests.jst b/tests/manual-tests/directives-tests/directives-info-and-server-tests.jst
index 4f3e7a2..60dd829 100644
--- a/tests/manual-tests/directives-tests/directives-info-and-server-tests.jst
+++ b/tests/manual-tests/directives-tests/directives-info-and-server-tests.jst
@@ -1,22 +1,22 @@
-JSIGHT 0.3
-
-INFO
- Title "Check API title here"
- Version "Check API Version here (1.0)."
- Description
- Check API description here.
-
-SERVER @testCommon
- BaseUrl "https://pets.com/api/1.0"
-
-SERVER @testAnnotation // Check server's annotation.
- BaseUrl "https://192.168.0.100/1.0"
-
-SERVER @testMutilineAnnotation /* Check server's
- multiline annotation. */
- BaseUrl "https://192.168.0.100/1.0"
-
-SERVER @testLongAnnotation /* Check server's
- multiline annotation which is so long, so extremely long.
- so perfectly long, so longly long. */
+JSIGHT 0.3
+
+INFO
+ Title "Check API title here (jtest)" # always use `jtest` in test titles for the sake of statistics
+ Version "Check API Version here (1.0)."
+ Description
+ Check API description here.
+
+SERVER @testCommon
+ BaseUrl "https://pets.com/api/1.0"
+
+SERVER @testAnnotation // Check server's annotation.
+ BaseUrl "https://192.168.0.100/1.0"
+
+SERVER @testMutilineAnnotation /* Check server's
+ multiline annotation. */
+ BaseUrl "https://192.168.0.100/1.0"
+
+SERVER @testLongAnnotation /* Check server's
+ multiline annotation which is so long, so extremely long.
+ so perfectly long, so longly long. */
BaseUrl "https://192.168.0.100/1.0"
\ No newline at end of file
diff --git a/tests/manual-tests/documentation-panel-tests/bottom-margin-test-1.jst b/tests/manual-tests/documentation-panel-tests/bottom-margin-test-1.jst
index 9121661..216eef2 100644
--- a/tests/manual-tests/documentation-panel-tests/bottom-margin-test-1.jst
+++ b/tests/manual-tests/documentation-panel-tests/bottom-margin-test-1.jst
@@ -1,7 +1,7 @@
JSIGHT 0.3
INFO
- Title "Bottom margin tests"
+ Title "Bottom margin tests (jtest)" # always use `jtest` in test titles for the sake of statistics
Description
(
Remove directives one by one from the bottom and check their bottom margin.
@@ -46,16 +46,13 @@ INFO
SERVER @checkServerBottomMargin // Check SERVER bottom margin
BaseUrl http://check-BaseUrl-bottom-margin
-GET /check-method-bottom-margin/{var}
+GET /check-method-bottom-margin/
Description
(
Check method description bottom margin.
)
-Path
- {
- "var": "Check path bottom margin" // Check path bottom margin.
- }
+GET /check-path-bottom-margin/{var}
Query
{
"Check query bottom margin": 0
diff --git a/tests/manual-tests/error-tests/error-messages-test.jst b/tests/manual-tests/error-tests/error-messages-test.jst
new file mode 100644
index 0000000..f0da4c8
--- /dev/null
+++ b/tests/manual-tests/error-tests/error-messages-test.jst
@@ -0,0 +1,196 @@
+###
+
+Uncomment pieces of code and see the corresponding error message:
+1. Check the message text.
+2. Check the message link to documentation (if exists).
+
+###
+
+# GET / # DirectiveJSIGHTShouldBeTheFirst
+# JSIGHT 0.4 # UnsupportedVersion
+JSIGHT 0.3
+# JSIGHT 0.3
+
+INFO
+ Title "Error test (jtest)" # always use `jtest` in test titles for the sake of statistics
+ # Title "bbb" # NotUniqueDirective
+
+SERVER @a
+ BaseUrl "url"
+ # BaseUrl "url" # DirectiveBaseURLAlreadyDefined
+
+# GET # Path not found
+
+
+URL /1
+# URL /1 # NotUniquePath
+
+# INFO # DirectiveINFOGottaBeOnlyOneTime
+
+# INCLUDE /par # IncludeRootErr
+# INCLUDE ../ # IncludeUpErr
+# INCLUDE one\two # IncludeSeparatorErr
+
+
+# Body @scalar # incorrect directive context
+
+GET /{id}
+ Path
+ {
+ "id": 1
+ }
+ # Request empty // annotation is not allowed
+ # Tags # RequiredParameterNotSpecified
+ # Tags @tag # Tag not found
+ # 200 @not_found # Type not found
+ # 200 @scalar jsight # CannotUseTheTypeAndSchemaNotationParametersTogether
+ 200 @scalar
+ # Body @scalar # ParametersAreForbiddenForTheDirective
+ # 201 @scalar @scalar # ParametersIsAlreadyDefined
+ ###
+ Headers
+ @scalar # BodyMustBeObject
+ ###
+ # ) # ThereIsNoExplicitContextForClosure
+ # () # ApartFromTheOpeningParenthesis
+ ###
+ Description # DescriptionIsEmpty
+ (
+ )
+ ###
+
+# DELETE /{id}/{id} # PathParameterIsDuplicatedInThePath
+
+# GET /{name}
+
+###
+TYPE @scalar # DuplicateNames
+ ""
+###
+
+POST /{id}/{par2}
+ Path
+ {
+ # "id": 1, # The parameter %q has already been defined earlier
+ "par2": 2
+ }
+
+###
+GET /1
+ Path
+ # @scalar # PathObjectErr
+ # {} # PathEmptyErr
+ # {} // {additionalProperties: true} # PathAdditionalPropertiesErr
+ # {} // {nullable: true} # PathNullableErr
+###
+
+# GET /{} # PathEmptyParameter
+
+
+
+
+# ErrUserTypeFound TODO: test for ErrUserTypeFound
+
+
+TYPE @test
+{ # // {additionalProperties: "unknown_type"} # ErrUnknownJSchemaType
+ # "key": "value" // {type: "unknown_type"} # ErrUnknownValueOfTheTypeRule
+ # "recursion": @test # ErrInfinityRecursionDetected
+ # "or": 0 // {or: [ {type: "integer", min: 1}, {type: "string"} ]} # ErrOrRuleSetValidation
+ # bad_key # ErrInvalidCharacter
+ # "key": bad_value # ErrInvalidCharacter
+ # "enum": 1 // {enum: [invalid_value]} # ErrInvalidCharacter
+ # "regex": "abc" // {regex: invalid_regex} # ErrInvalidCharacter
+ # "key": "value" // {wrong key} # ErrInvalidCharacterInAnnotationObjectKey
+ # "key": "value" // {type: "string", type: "string"} # ErrDuplicateRule
+ # "duplicate-key": 1, "duplicate-key": 2 # ErrDuplicateKeysInSchema
+ # "key": "value" // {"invalid_rule": ""} # ErrUnknownRule
+ # "key": 42 // {min: 43, max: 44} # ErrConstraintValidation
+ # "key": 1.23 // {precision: 1} # ErrConstraintValidation
+ # "key": "value" // {minLength: 10} # ErrConstraintStringLengthValidation
+ # "key": "value" // {minLength: "invalid_value"} # ErrInvalidValueOfConstraint
+ # "key": 1 // {precision: 0} # ErrZeroPrecision
+ # "key": "value" // {enum: ["one"]} # ErrDoesNotMatchAnyOfTheEnumValues
+ # "key": "value" // {regex: "\\d"} # ErrDoesNotMatchRegularExpression
+ # "key": 0 // {min: 0, max: -1} # ErrValueOfOneConstraintGreaterOrEqualToAnother
+ # "key": "" // {rule: @scalar} # ErrIncorrectRuleValueType
+ # "key": {"foo": "bar"} // {const: true} # ErrIncorrectRuleForSeveralNode
+ # "key": 1 // {or: [ {min: []}, {type: "string"} ]} # ErrLiteralValueExpected
+ # "key": "value" // {enum: [[]]} # ErrIncorrectArrayItemTypeInEnumRule
+ # "key": "value" // {enum: ["value", "value"]} # ErrDuplicationInEnumRule
+ # "key": "value" // {or: "value"} # ErrArrayWasExpectedInOrRule
+ # "key": "value" // {or: []} # ErrEmptyArrayInOrRule
+ # "key": "value" // {or: ["string"]} # ErrOneElementInArrayInOrRule
+ # "key": "value" // {or: [1,2]} # ErrIncorrectArrayItemTypeInOrRule
+ # "key": "value" // {or: [{}]} # ErrEmptyRuleSet
+ # "key": "value" // {or: [{"minLength": 1}]} # ErrTypIsRequiredInsideOr
+ # "key": @scalar // {minLength: 2} # ErrCannotSpecifyOtherRulesWithTypeReference
+ # "key": 1 // {or: ["integer", "string"], min: 1} # ErrShouldBeNoOtherRulesInSetWithOr
+ # "key": 1 // {enum: [1], min: 0} # ErrShouldBeNoOtherRulesInSetWithEnum
+ # "key": 1 // {type: "any", min: 0} # ErrShouldBeNoOtherRulesInSetWithAny
+ # "key": {} // {type: "@scalar"} # ErrInvalidChildNodeTogetherWithTypeReference
+ # "key": {} // {or: ["@scalar", "@scalar"]} # ErrInvalidChildNodeTogetherWithOrRule
+ # "key": 1 // {exclusiveMinimum: true} # ErrConstraintMinNotFound
+ # "key": 2 // {exclusiveMaximum: true} # ErrConstraintMaxNotFound
+ # "key": 3 // {type: "integer", enum: [1,2]} # ErrInvalidValueInTheTypeRule
+ # "key": 3 // {type: "decimal"} # ErrNotFoundRulePrecision
+ # "key": 3 // {type: "mixed"} # ErrNotFoundRuleOr
+ # "key": 3 // {type: "enum"} # ErrNotFoundRuleEnum
+ # "key": 3 // {type: "string"} # ErrIncompatibleTypes
+ # "key": 1 // {precision: 1} # ErrUnexpectedConstraint
+ # "key": [] // {minItems: 1} # ErrIncorrectConstraintValueForEmptyArray
+ # "key": 1 // {or: ["@string1", "@string2"]} # ErrIncorrectUserType
+ # "key": @not_found # ErrUserTypeNotFoun
+ # @any1: "" # ErrInvalidKeyShortcutType
+ # "key": 1 // {enum: true}
+ # "key": "550e8400e29b41d4a716446655440000 " // {type: "uuid"} # ErrUUIDLength
+ # "key": "z50e8400-e29b-41d4-a716-446655440000" // {type: "uuid"} # ErrUUIDFormat
+ # "key": "value" "key" // invalide character after the object property
+}
+
+
+TYPE @string1
+ ""
+
+TYPE @string2
+ ""
+
+
+TYPE @any1
+[ # // {type: "any"} # ErrInvalidNestedElementsFoundForTypeAny
+ 1
+]
+
+
+TYPE @allOfWrong
+{ # // {allOf: []} # ErrTypeNameNotFoundInAllOfRule
+}
+
+TYPE @allOf
+{ # // {allOf: "42"} # ErrInvalidSchemaNameInAllOfRule
+}
+
+TYPE @allOfRecursion
+{ // # {allOf: "@allOfRecursion"} # ErrUnacceptableRecursionInAllOfRule
+}
+
+TYPE @allOfScalar
+{ # // {allOf: "@scalar"}
+}
+
+TYPE @scalar
+ "" // # {optional: true} # ErrRuleOptionalAppliesOnlyToObjectProperties
+
+TYPE @minItems
+[ # // {minItems: 3} # ErrConstraintMinItemsValidation
+ 1, 2
+]
+
+TYPE @cat
+# ( # ContextNotClosed
+ {
+ "id": 1
+ }
+
+# TYPE @endOfFile # ErrUnexpectedEOF
+# {
diff --git a/tests/manual-tests/wrong-rules-conjunctions-tests.jst b/tests/manual-tests/error-tests/wrong-rules-conjunctions-tests.jst
similarity index 94%
rename from tests/manual-tests/wrong-rules-conjunctions-tests.jst
rename to tests/manual-tests/error-tests/wrong-rules-conjunctions-tests.jst
index 3f9e05a..cb86690 100644
--- a/tests/manual-tests/wrong-rules-conjunctions-tests.jst
+++ b/tests/manual-tests/error-tests/wrong-rules-conjunctions-tests.jst
@@ -1,1683 +1,1683 @@
-JSIGHT 0.3
-
-INFO
- Description
- Delete types one by one and check that every type raises an
- error in a right line.
-
- Version 1.0
-
-# Object
-
-TYPE @testWrongRules1
-{
- "object": {} /* {type: "object",
- enum: ["white", "black"]
- }*/
-}
-
-TYPE @testWrongRules2
-{
- "object": {} /* {type: "object",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules3
-{
- "object": {} /* {type: "object",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules4
-{
- "object": {} /* {type: "object",
- regex: "^[A-Za-z]+$",
- }*/
-}
-
-TYPE @testWrongRules5
-{
- "object": {} /* {type: "object",
- maxLength: 100
- }*/
-}
-
-TYPE @testWrongRules6
-{
- "object": {} /* {type: "object",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules7
-{
- "object": {} /* {type: "object",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules8
-{
- "object": {} /* {type: "object",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules9
-{
- "object": {} /* {type: "object",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules10
-{
- "object": {} /* {type: "object",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules11
-{
- "object": {} /* {type: "object",
- const: true
- }*/
-}
-
-# array
-TYPE @testWrongRules12
-{
- "array" : [ /* {type: "array",
- const: true,
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules13
-{
- "array" : [ /* {type: "array",
- min: 0,
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules14
-{
- "array" : [ /* {type: "array",
- max: 1,
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules15
-{
- "array" : [ /* {type: "array",
- exclusiveMinimum: true,
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules16
-{
- "array" : [ /* {type: "array",
- exclusiveMaximum: true,
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules17
-{
- "array" : [ /* {type: "array",
- precision: 2,
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules18
-{
- "array" : [ /* {type: "array",
- minLength: 0,
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules19
-{
- "array" : [ /* {type: "array",
- maxLength: 100,
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules20
-{
- "array" : [ /* {type: "array",
- regex: "^[A-Za-z]+$",
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules21
-{
- "array" : [ /* {type: "array",
- or: [{type: "string"}, {type: "integer"}],
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules22
-{
- "array" : [ /* {type: "array",
- additionalProperties: true,
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules23
-{
- "array" : [ /* {type: "array",
- allOf: "@cat",
- }*/
- "item"
- ]
-}
-
-TYPE @testWrongRules24
-{
- "array" : [ /* {type: "array",
- enum: ["white", "black"]
- }*/
- "item"
- ]
-}
-
-# integer
-
-TYPE @testWrongRules25
-{
- "integer": 1 /* {type: "integer",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules26
-{
- "integer": 1 /* {type: "integer",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules27
-{
- "integer": 1 /* {type: "integer",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules28
-{
- "integer": 1 /* {type: "integer",
- regex: "^[A-Za-z]+$",
- }*/
-}
-
-TYPE @testWrongRules29
-{
- "integer": 1 /* {type: "integer",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules30
-{
- "integer": 1 /* {type: "integer",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules31
-{
- "integer": 1 /* {type: "integer",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules32
-{
- "integer": 1 /* {type: "integer",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules33
-{
- "integer": 1 /* {type: "integer",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules34
-{
- "integer": 1 /* {type: "integer",
- enum: ["white", "black"]
- }*/
-}
-
-# float
-
-TYPE @testWrongRules35
-{
- "float": 1.2 /* {type: "float",
- precision: 1
- }*/
-}
-
-TYPE @testWrongRules36
-{
- "float": 1.2 /* {type: "float",
- minLength: 0
- }*/
-}
-
-TYPE @testWrongRules37
-{
- "float": 1.2 /* {type: "float",
- maxLength: 100
- }*/
-}
-
-TYPE @testWrongRules38
-{
- "float": 1.2 /* {type: "float",
- regex: "^[A-Za-z]+$"
- }*/
-}
-
-TYPE @testWrongRules39
-{
- "float": 1.2 /* {type: "float",
- minItems: 0
- }*/
-}
-
-TYPE @testWrongRules40
-{
- "float": 1.2 /* {type: "float",
- maxItems: 10
- }*/
-}
-
-TYPE @testWrongRules41
-{
- "float": 1.2 /* {type: "float",
- or: [{type: "string"}, {type: "float"}]
- }*/
-}
-
-TYPE @testWrongRules42
-{
- "float": 1.2 /* {type: "float",
- additionalProperties: true
- }*/
-}
-
-TYPE @testWrongRules43
-{
- "float": 1.2 /* {type: "float",
- allOf: "@cat"
- }*/
-}
-
-TYPE @testWrongRules44
-{
- "float": 1.2 /* {type: "float",
- enum: [1.2, 1.3]
- }*/
-}
-
-# decimal
-
-TYPE @testWrongRules45
-{
- "decimal": 1.23 /* {type: "decimal", precision: 2,
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules46
-{
- "decimal": 1.23 /* {type: "decimal", precision: 2,
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules47
-{
- "decimal": 1.23 /* {type: "decimal", precision: 2,
- regex: "^[A-Za-z]+$",
- }*/
-}
-
-TYPE @testWrongRules48
-{
- "decimal": 1.23 /* {type: "decimal", precision: 2,
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules49
-{
- "decimal": 1.23 /* {type: "decimal", precision: 2,
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules50
-{
- "decimal": 1.23 /* {type: "decimal", precision: 2,
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules51
-{
- "decimal": 1.23 /* {type: "decimal", precision: 2,
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules52
-{
- "decimal": 1.23 /* {type: "decimal", precision: 2,
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules53
-{
- "decimal": 1.23 /* {type: "decimal", precision: 2,
- enum: ["white", "black"]
- }*/
-}
-
-# boolean
-
-TYPE @testWrongRules54
-{
- "boolean": true /* {type: "boolean",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules55
-{
- "boolean": true /* {type: "boolean",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules56
-{
- "boolean": true /* {type: "boolean",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules57
-{
- "boolean": true /* {type: "boolean",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules58
-{
- "boolean": true /* {type: "boolean",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules59
-{
- "boolean": true /* {type: "boolean",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules60
-{
- "boolean": true /* {type: "boolean",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules61
-{
- "boolean": true /* {type: "boolean",
- regex: "^[A-Za-z]+$",
- }*/
-}
-
-TYPE @testWrongRules62
-{
- "boolean": true /* {type: "boolean",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules63
-{
- "boolean": true /* {type: "boolean",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules64
-{
- "boolean": true /* {type: "boolean",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules65
-{
- "boolean": true /* {type: "boolean",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules66
-{
- "boolean": true /* {type: "boolean",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules67
-{
- "boolean": true /* {type: "boolean",
- enum: ["white", "black"]
- }*/
-}
-
-# string
-
-TYPE @testWrongRules68
-{
- "string": "value" /* {type: "string",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules69
-{
- "string": "value" /* {type: "string",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules70
-{
- "string": "value" /* {type: "string",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules71
-{
- "string": "value" /* {type: "string",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules72
-{
- "string": "value" /* {type: "string",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules73
-{
- "string": "value" /* {type: "string",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules74
-{
- "string": "value" /* {type: "string",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules75
-{
- "string": "value" /* {type: "string",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules76
-{
- "string": "value" /* {type: "string",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules77
-{
- "string": "value" /* {type: "string",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules78
-{
- "string": "value" /* {type: "string",
- enum: ["white", "black"]
- }*/
-}
-
-# email
-
-TYPE @testWrongRules79
-{
- "email": "t@t.com" /* {type: "email",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules80
-{
- "email": "t@t.com" /* {type: "email",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules81
-{
- "email": "t@t.com" /* {type: "email",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules82
-{
- "email": "t@t.com" /* {type: "email",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules83
-{
- "email": "t@t.com" /* {type: "email",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules84
-{
- "email": "t@t.com" /* {type: "email",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules85
-{
- "email": "t@t.com" /* {type: "email",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules86
-{
- "email": "t@t.com" /* {type: "email",
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules87
-{
- "email": "t@t.com" /* {type: "email",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules88
-{
- "email": "t@t.com" /* {type: "email",
- maxItems: 10,
- }*/
-}
-
-# uri
-
-TYPE @testWrongRules89
-{
- "uri": "http://t.com" /* {type: "uri",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules90
-{
- "uri": "http://t.com" /* {type: "uri",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules91
-{
- "uri": "http://t.com" /* {type: "uri",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules92
-{
- "uri": "http://t.com" /* {type: "uri",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules93
-{
- "uri": "http://t.com" /* {type: "uri",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules94
-{
- "uri": "http://t.com" /* {type: "uri",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules95
-{
- "uri": "http://t.com" /* {type: "uri",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules96
-{
- "uri": "http://t.com" /* {type: "uri",
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules97
-{
- "uri": "http://t.com" /* {type: "uri",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules98
-{
- "uri": "http://t.com" /* {type: "uri",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules99
-{
- "uri": "http://t.com" /* {type: "uri",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules100
-{
- "uri": "http://t.com" /* {type: "uri",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules101
-{
- "uri": "http://t.com" /* {type: "uri",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules102
-{
- "uri": "http://t.com" /* {type: "uri",
- enum: ["white", "black"]
- }*/
-}
-
-# date
-
-TYPE @testWrongRules103
-{
- "date": "2021-12-16" /* {type: "date",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules104
-{
- "date": "2021-12-16" /* {type: "date",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules105
-{
- "date": "2021-12-16" /* {type: "date",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules106
-{
- "date": "2021-12-16" /* {type: "date",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules107
-{
- "date": "2021-12-16" /* {type: "date",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules108
-{
- "date": "2021-12-16" /* {type: "date",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules109
-{
- "date": "2021-12-16" /* {type: "date",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules110
-{
- "date": "2021-12-16" /* {type: "date",
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules111
-{
- "date": "2021-12-16" /* {type: "date",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules112
-{
- "date": "2021-12-16" /* {type: "date",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules113
-{
- "date": "2021-12-16" /* {type: "date",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules114
-{
- "date": "2021-12-16" /* {type: "date",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules115
-{
- "date": "2021-12-16" /* {type: "date",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules116
-{
- "date": "2021-12-16" /* {type: "date",
- enum: ["white", "black"]
- }*/
-}
-
-# datetime
-
-TYPE @testWrongRules117
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules118
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules119
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules120
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules121
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules122
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules123
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules124
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules125
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules126
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules127
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules128
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules129
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules130
-{
- "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
- enum: ["white", "black"]
- }*/
-}
-
-# uuid
-
-TYPE @testWrongRules131
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules132
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules133
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules134
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules135
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules136
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules137
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules138
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules139
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules140
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules141
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules142
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules143
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules144
-{
- "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
- enum: ["white", "black"]
- }*/
-}
-
-# enum
-
-TYPE @testWrongRules145
-{
- "enum": "white" /* {enum: ["white", "black"],
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules146
-{
- "enum": "white" /* {enum: ["white", "black"],
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules147
-{
- "enum": "white" /* {enum: ["white", "black"],
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules148
-{
- "enum": "white" /* {enum: ["white", "black"],
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules149
-{
- "enum": "white" /* {enum: ["white", "black"],
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules150
-{
- "enum": "white" /* {enum: ["white", "black"],
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules151
-{
- "enum": "white" /* {enum: ["white", "black"],
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules152
-{
- "enum": "white" /* {enum: ["white", "black"],
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules153
-{
- "enum": "white" /* {enum: ["white", "black"],
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules154
-{
- "enum": "white" /* {enum: ["white", "black"],
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules155
-{
- "enum": "white" /* {enum: ["white", "black"],
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules156
-{
- "enum": "white" /* {enum: ["white", "black"],
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules157
-{
- "enum": "white" /* {enum: ["white", "black"],
- allOf: "@cat",
- }*/
-}
-
-# mixed
-
-TYPE @testWrongRules158
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- const: true,
- }*/
-}
-
-TYPE @testWrongRules159
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules160
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules161
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules162
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules163
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules164
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules165
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules166
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules167
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules168
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules169
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules170
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules171
-{
- "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
- enum: ["white", "black"]
- }*/
-}
-
-# any
-
-TYPE @testWrongRules172
-{
- "any": 456 /* {type: "any",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules173
-{
- "any": 456 /* {type: "any",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules174
-{
- "any": 456 /* {type: "any",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules175
-{
- "any": 456 /* {type: "any",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules176
-{
- "any": 456 /* {type: "any",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules177
-{
- "any": 456 /* {type: "any",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules178
-{
- "any": 456 /* {type: "any",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules179
-{
- "any": 456 /* {type: "any",
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules180
-{
- "any": 456 /* {type: "any",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules181
-{
- "any": 456 /* {type: "any",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules182
-{
- "any": 456 /* {type: "any",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules183
-{
- "any": 456 /* {type: "any",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules184
-{
- "any": 456 /* {type: "any",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules185
-{
- "any": 456 /* {type: "any",
- enum: ["white", "black"]
- }*/
-}
-
-# null
-
-TYPE @testWrongRules186
-{
- "null": null /* {type: "null",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules187
-{
- "null": null /* {type: "null",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules188
-{
- "null": null /* {type: "null",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules189
-{
- "null": null /* {type: "null",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules190
-{
- "null": null /* {type: "null",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules191
-{
- "null": null /* {type: "null",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules192
-{
- "null": null /* {type: "null",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules193
-{
- "null": null /* {type: "null",
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules194
-{
- "null": null /* {type: "null",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules195
-{
- "null": null /* {type: "null",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules196
-{
- "null": null /* {type: "null",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules197
-{
- "null": null /* {type: "null",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules198
-{
- "null": null /* {type: "null",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules199
-{
- "null": null /* {type: "null",
- enum: ["white", "black"]
- }*/
-}
-
-# user type reference
-
-TYPE @testWrongRules200
-{
- "userType1": @cat /* {
- type: "@cat",
- }*/
-}
-
-TYPE @testWrongRules201
-{
- "userType1": @cat /* {
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules202
-{
- "userType1": @cat /* {
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules203
-{
- "userType1": @cat /* {
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules204
-{
- "userType1": @cat /* {
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules205
-{
- "userType1": @cat /* {
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules206
-{
- "userType1": @cat /* {
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules207
-{
- "userType1": @cat /* {
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules208
-{
- "userType1": @cat /* {
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules209
-{
- "userType1": @cat /* {
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules210
-{
- "userType1": @cat /* {
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules211
-{
- "userType1": @cat /* {
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules212
-{
- "userType1": @cat /* {
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules213
-{
- "userType1": @cat /* {
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules214
-{
- "userType1": @cat /* {
- enum: ["white", "black"]
- }*/
-}
-
-# user type
-
-TYPE @testWrongRules215
-{
- "userType2": 12 /* {type: "@catId",
- const: true,
- }*/
-}
-
-TYPE @testWrongRules216
-{
- "userType2": 12 /* {type: "@catId",
- min: 0,
- }*/
-}
-
-TYPE @testWrongRules217
-{
- "userType2": 12 /* {type: "@catId",
- max: 1,
- }*/
-}
-
-TYPE @testWrongRules218
-{
- "userType2": 12 /* {type: "@catId",
- exclusiveMinimum: true,
- }*/
-}
-
-TYPE @testWrongRules219
-{
- "userType2": 12 /* {type: "@catId",
- exclusiveMaximum: true,
- }*/
-}
-
-TYPE @testWrongRules220
-{
- "userType2": 12 /* {type: "@catId",
- precision: 2,
- }*/
-}
-
-TYPE @testWrongRules221
-{
- "userType2": 12 /* {type: "@catId",
- minLength: 0,
- }*/
-}
-
-TYPE @testWrongRules222
-{
- "userType2": 12 /* {type: "@catId",
- maxLength: 100,
- }*/
-}
-
-TYPE @testWrongRules223
-{
- "userType2": 12 /* {type: "@catId",
- regex: ".*",
- }*/
-}
-
-TYPE @testWrongRules224
-{
- "userType2": 12 /* {type: "@catId",
- minItems: 0,
- }*/
-}
-
-TYPE @testWrongRules225
-{
- "userType2": 12 /* {type: "@catId",
- maxItems: 10,
- }*/
-}
-
-TYPE @testWrongRules226
-{
- "userType2": 12 /* {type: "@catId",
- or: [{type: "string"}, {type: "integer"}],
- }*/
-}
-
-TYPE @testWrongRules227
-{
- "userType2": 12 /* {type: "@catId",
- additionalProperties: true,
- }*/
-}
-
-TYPE @testWrongRules228
-{
- "userType2": 12 /* {type: "@catId",
- allOf: "@cat",
- }*/
-}
-
-TYPE @testWrongRules229
-{
- "userType2": 12 /* {type: "@catId",
- enum: ["white", "black"]
- }*/
-}
-
-# Helpfull types
-
-TYPE @cat
-{
- "catId": @catId,
- "catName": "Tom"
-}
-
-TYPE @catId
- 12 // {min: 1}
+JSIGHT 0.3
+
+INFO
+ Description
+ Delete types one by one and check that every type raises an
+ error in a right line.
+
+ Version 1.0
+
+# Object
+
+TYPE @testWrongRules1
+{
+ "object": {} /* {type: "object",
+ enum: ["white", "black"]
+ }*/
+}
+
+TYPE @testWrongRules2
+{
+ "object": {} /* {type: "object",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules3
+{
+ "object": {} /* {type: "object",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules4
+{
+ "object": {} /* {type: "object",
+ regex: "^[A-Za-z]+$",
+ }*/
+}
+
+TYPE @testWrongRules5
+{
+ "object": {} /* {type: "object",
+ maxLength: 100
+ }*/
+}
+
+TYPE @testWrongRules6
+{
+ "object": {} /* {type: "object",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules7
+{
+ "object": {} /* {type: "object",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules8
+{
+ "object": {} /* {type: "object",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules9
+{
+ "object": {} /* {type: "object",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules10
+{
+ "object": {} /* {type: "object",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules11
+{
+ "object": {} /* {type: "object",
+ const: true
+ }*/
+}
+
+# array
+TYPE @testWrongRules12
+{
+ "array" : [ /* {type: "array",
+ const: true,
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules13
+{
+ "array" : [ /* {type: "array",
+ min: 0,
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules14
+{
+ "array" : [ /* {type: "array",
+ max: 1,
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules15
+{
+ "array" : [ /* {type: "array",
+ exclusiveMinimum: true,
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules16
+{
+ "array" : [ /* {type: "array",
+ exclusiveMaximum: true,
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules17
+{
+ "array" : [ /* {type: "array",
+ precision: 2,
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules18
+{
+ "array" : [ /* {type: "array",
+ minLength: 0,
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules19
+{
+ "array" : [ /* {type: "array",
+ maxLength: 100,
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules20
+{
+ "array" : [ /* {type: "array",
+ regex: "^[A-Za-z]+$",
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules21
+{
+ "array" : [ /* {type: "array",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules22
+{
+ "array" : [ /* {type: "array",
+ additionalProperties: true,
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules23
+{
+ "array" : [ /* {type: "array",
+ allOf: "@cat",
+ }*/
+ "item"
+ ]
+}
+
+TYPE @testWrongRules24
+{
+ "array" : [ /* {type: "array",
+ enum: ["white", "black"]
+ }*/
+ "item"
+ ]
+}
+
+# integer
+
+TYPE @testWrongRules25
+{
+ "integer": 1 /* {type: "integer",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules26
+{
+ "integer": 1 /* {type: "integer",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules27
+{
+ "integer": 1 /* {type: "integer",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules28
+{
+ "integer": 1 /* {type: "integer",
+ regex: "^[A-Za-z]+$",
+ }*/
+}
+
+TYPE @testWrongRules29
+{
+ "integer": 1 /* {type: "integer",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules30
+{
+ "integer": 1 /* {type: "integer",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules31
+{
+ "integer": 1 /* {type: "integer",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules32
+{
+ "integer": 1 /* {type: "integer",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules33
+{
+ "integer": 1 /* {type: "integer",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules34
+{
+ "integer": 1 /* {type: "integer",
+ enum: ["white", "black"]
+ }*/
+}
+
+# float
+
+TYPE @testWrongRules35
+{
+ "float": 1.2 /* {type: "float",
+ precision: 1
+ }*/
+}
+
+TYPE @testWrongRules36
+{
+ "float": 1.2 /* {type: "float",
+ minLength: 0
+ }*/
+}
+
+TYPE @testWrongRules37
+{
+ "float": 1.2 /* {type: "float",
+ maxLength: 100
+ }*/
+}
+
+TYPE @testWrongRules38
+{
+ "float": 1.2 /* {type: "float",
+ regex: "^[A-Za-z]+$"
+ }*/
+}
+
+TYPE @testWrongRules39
+{
+ "float": 1.2 /* {type: "float",
+ minItems: 0
+ }*/
+}
+
+TYPE @testWrongRules40
+{
+ "float": 1.2 /* {type: "float",
+ maxItems: 10
+ }*/
+}
+
+TYPE @testWrongRules41
+{
+ "float": 1.2 /* {type: "float",
+ or: [{type: "string"}, {type: "float"}]
+ }*/
+}
+
+TYPE @testWrongRules42
+{
+ "float": 1.2 /* {type: "float",
+ additionalProperties: true
+ }*/
+}
+
+TYPE @testWrongRules43
+{
+ "float": 1.2 /* {type: "float",
+ allOf: "@cat"
+ }*/
+}
+
+TYPE @testWrongRules44
+{
+ "float": 1.2 /* {type: "float",
+ enum: [1.2, 1.3]
+ }*/
+}
+
+# decimal
+
+TYPE @testWrongRules45
+{
+ "decimal": 1.23 /* {type: "decimal", precision: 2,
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules46
+{
+ "decimal": 1.23 /* {type: "decimal", precision: 2,
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules47
+{
+ "decimal": 1.23 /* {type: "decimal", precision: 2,
+ regex: "^[A-Za-z]+$",
+ }*/
+}
+
+TYPE @testWrongRules48
+{
+ "decimal": 1.23 /* {type: "decimal", precision: 2,
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules49
+{
+ "decimal": 1.23 /* {type: "decimal", precision: 2,
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules50
+{
+ "decimal": 1.23 /* {type: "decimal", precision: 2,
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules51
+{
+ "decimal": 1.23 /* {type: "decimal", precision: 2,
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules52
+{
+ "decimal": 1.23 /* {type: "decimal", precision: 2,
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules53
+{
+ "decimal": 1.23 /* {type: "decimal", precision: 2,
+ enum: ["white", "black"]
+ }*/
+}
+
+# boolean
+
+TYPE @testWrongRules54
+{
+ "boolean": true /* {type: "boolean",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules55
+{
+ "boolean": true /* {type: "boolean",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules56
+{
+ "boolean": true /* {type: "boolean",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules57
+{
+ "boolean": true /* {type: "boolean",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules58
+{
+ "boolean": true /* {type: "boolean",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules59
+{
+ "boolean": true /* {type: "boolean",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules60
+{
+ "boolean": true /* {type: "boolean",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules61
+{
+ "boolean": true /* {type: "boolean",
+ regex: "^[A-Za-z]+$",
+ }*/
+}
+
+TYPE @testWrongRules62
+{
+ "boolean": true /* {type: "boolean",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules63
+{
+ "boolean": true /* {type: "boolean",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules64
+{
+ "boolean": true /* {type: "boolean",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules65
+{
+ "boolean": true /* {type: "boolean",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules66
+{
+ "boolean": true /* {type: "boolean",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules67
+{
+ "boolean": true /* {type: "boolean",
+ enum: ["white", "black"]
+ }*/
+}
+
+# string
+
+TYPE @testWrongRules68
+{
+ "string": "value" /* {type: "string",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules69
+{
+ "string": "value" /* {type: "string",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules70
+{
+ "string": "value" /* {type: "string",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules71
+{
+ "string": "value" /* {type: "string",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules72
+{
+ "string": "value" /* {type: "string",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules73
+{
+ "string": "value" /* {type: "string",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules74
+{
+ "string": "value" /* {type: "string",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules75
+{
+ "string": "value" /* {type: "string",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules76
+{
+ "string": "value" /* {type: "string",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules77
+{
+ "string": "value" /* {type: "string",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules78
+{
+ "string": "value" /* {type: "string",
+ enum: ["white", "black"]
+ }*/
+}
+
+# email
+
+TYPE @testWrongRules79
+{
+ "email": "t@t.com" /* {type: "email",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules80
+{
+ "email": "t@t.com" /* {type: "email",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules81
+{
+ "email": "t@t.com" /* {type: "email",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules82
+{
+ "email": "t@t.com" /* {type: "email",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules83
+{
+ "email": "t@t.com" /* {type: "email",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules84
+{
+ "email": "t@t.com" /* {type: "email",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules85
+{
+ "email": "t@t.com" /* {type: "email",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules86
+{
+ "email": "t@t.com" /* {type: "email",
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules87
+{
+ "email": "t@t.com" /* {type: "email",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules88
+{
+ "email": "t@t.com" /* {type: "email",
+ maxItems: 10,
+ }*/
+}
+
+# uri
+
+TYPE @testWrongRules89
+{
+ "uri": "http://t.com" /* {type: "uri",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules90
+{
+ "uri": "http://t.com" /* {type: "uri",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules91
+{
+ "uri": "http://t.com" /* {type: "uri",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules92
+{
+ "uri": "http://t.com" /* {type: "uri",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules93
+{
+ "uri": "http://t.com" /* {type: "uri",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules94
+{
+ "uri": "http://t.com" /* {type: "uri",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules95
+{
+ "uri": "http://t.com" /* {type: "uri",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules96
+{
+ "uri": "http://t.com" /* {type: "uri",
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules97
+{
+ "uri": "http://t.com" /* {type: "uri",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules98
+{
+ "uri": "http://t.com" /* {type: "uri",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules99
+{
+ "uri": "http://t.com" /* {type: "uri",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules100
+{
+ "uri": "http://t.com" /* {type: "uri",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules101
+{
+ "uri": "http://t.com" /* {type: "uri",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules102
+{
+ "uri": "http://t.com" /* {type: "uri",
+ enum: ["white", "black"]
+ }*/
+}
+
+# date
+
+TYPE @testWrongRules103
+{
+ "date": "2021-12-16" /* {type: "date",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules104
+{
+ "date": "2021-12-16" /* {type: "date",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules105
+{
+ "date": "2021-12-16" /* {type: "date",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules106
+{
+ "date": "2021-12-16" /* {type: "date",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules107
+{
+ "date": "2021-12-16" /* {type: "date",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules108
+{
+ "date": "2021-12-16" /* {type: "date",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules109
+{
+ "date": "2021-12-16" /* {type: "date",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules110
+{
+ "date": "2021-12-16" /* {type: "date",
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules111
+{
+ "date": "2021-12-16" /* {type: "date",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules112
+{
+ "date": "2021-12-16" /* {type: "date",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules113
+{
+ "date": "2021-12-16" /* {type: "date",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules114
+{
+ "date": "2021-12-16" /* {type: "date",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules115
+{
+ "date": "2021-12-16" /* {type: "date",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules116
+{
+ "date": "2021-12-16" /* {type: "date",
+ enum: ["white", "black"]
+ }*/
+}
+
+# datetime
+
+TYPE @testWrongRules117
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules118
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules119
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules120
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules121
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules122
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules123
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules124
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules125
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules126
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules127
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules128
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules129
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules130
+{
+ "datetime": "2006-01-02T15:04:05+07:00" /* {type: "datetime",
+ enum: ["white", "black"]
+ }*/
+}
+
+# uuid
+
+TYPE @testWrongRules131
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules132
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules133
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules134
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules135
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules136
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules137
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules138
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules139
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules140
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules141
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules142
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules143
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules144
+{
+ "uuid": "550e8400-e29b-41d4-a716-446655440000" /* {type: "uuid",
+ enum: ["white", "black"]
+ }*/
+}
+
+# enum
+
+TYPE @testWrongRules145
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules146
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules147
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules148
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules149
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules150
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules151
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules152
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules153
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules154
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules155
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules156
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules157
+{
+ "enum": "white" /* {enum: ["white", "black"],
+ allOf: "@cat",
+ }*/
+}
+
+# mixed
+
+TYPE @testWrongRules158
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ const: true,
+ }*/
+}
+
+TYPE @testWrongRules159
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules160
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules161
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules162
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules163
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules164
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules165
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules166
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules167
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules168
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules169
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules170
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules171
+{
+ "mixed": "abc" /* {or: [{type: "string"}, {type: "integer"}],
+ enum: ["white", "black"]
+ }*/
+}
+
+# any
+
+TYPE @testWrongRules172
+{
+ "any": 456 /* {type: "any",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules173
+{
+ "any": 456 /* {type: "any",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules174
+{
+ "any": 456 /* {type: "any",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules175
+{
+ "any": 456 /* {type: "any",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules176
+{
+ "any": 456 /* {type: "any",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules177
+{
+ "any": 456 /* {type: "any",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules178
+{
+ "any": 456 /* {type: "any",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules179
+{
+ "any": 456 /* {type: "any",
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules180
+{
+ "any": 456 /* {type: "any",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules181
+{
+ "any": 456 /* {type: "any",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules182
+{
+ "any": 456 /* {type: "any",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules183
+{
+ "any": 456 /* {type: "any",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules184
+{
+ "any": 456 /* {type: "any",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules185
+{
+ "any": 456 /* {type: "any",
+ enum: ["white", "black"]
+ }*/
+}
+
+# null
+
+TYPE @testWrongRules186
+{
+ "null": null /* {type: "null",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules187
+{
+ "null": null /* {type: "null",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules188
+{
+ "null": null /* {type: "null",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules189
+{
+ "null": null /* {type: "null",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules190
+{
+ "null": null /* {type: "null",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules191
+{
+ "null": null /* {type: "null",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules192
+{
+ "null": null /* {type: "null",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules193
+{
+ "null": null /* {type: "null",
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules194
+{
+ "null": null /* {type: "null",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules195
+{
+ "null": null /* {type: "null",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules196
+{
+ "null": null /* {type: "null",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules197
+{
+ "null": null /* {type: "null",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules198
+{
+ "null": null /* {type: "null",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules199
+{
+ "null": null /* {type: "null",
+ enum: ["white", "black"]
+ }*/
+}
+
+# user type reference
+
+TYPE @testWrongRules200
+{
+ "userType1": @cat /* {
+ type: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules201
+{
+ "userType1": @cat /* {
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules202
+{
+ "userType1": @cat /* {
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules203
+{
+ "userType1": @cat /* {
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules204
+{
+ "userType1": @cat /* {
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules205
+{
+ "userType1": @cat /* {
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules206
+{
+ "userType1": @cat /* {
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules207
+{
+ "userType1": @cat /* {
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules208
+{
+ "userType1": @cat /* {
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules209
+{
+ "userType1": @cat /* {
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules210
+{
+ "userType1": @cat /* {
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules211
+{
+ "userType1": @cat /* {
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules212
+{
+ "userType1": @cat /* {
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules213
+{
+ "userType1": @cat /* {
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules214
+{
+ "userType1": @cat /* {
+ enum: ["white", "black"]
+ }*/
+}
+
+# user type
+
+TYPE @testWrongRules215
+{
+ "userType2": 12 /* {type: "@catId",
+ const: true,
+ }*/
+}
+
+TYPE @testWrongRules216
+{
+ "userType2": 12 /* {type: "@catId",
+ min: 0,
+ }*/
+}
+
+TYPE @testWrongRules217
+{
+ "userType2": 12 /* {type: "@catId",
+ max: 1,
+ }*/
+}
+
+TYPE @testWrongRules218
+{
+ "userType2": 12 /* {type: "@catId",
+ exclusiveMinimum: true,
+ }*/
+}
+
+TYPE @testWrongRules219
+{
+ "userType2": 12 /* {type: "@catId",
+ exclusiveMaximum: true,
+ }*/
+}
+
+TYPE @testWrongRules220
+{
+ "userType2": 12 /* {type: "@catId",
+ precision: 2,
+ }*/
+}
+
+TYPE @testWrongRules221
+{
+ "userType2": 12 /* {type: "@catId",
+ minLength: 0,
+ }*/
+}
+
+TYPE @testWrongRules222
+{
+ "userType2": 12 /* {type: "@catId",
+ maxLength: 100,
+ }*/
+}
+
+TYPE @testWrongRules223
+{
+ "userType2": 12 /* {type: "@catId",
+ regex: ".*",
+ }*/
+}
+
+TYPE @testWrongRules224
+{
+ "userType2": 12 /* {type: "@catId",
+ minItems: 0,
+ }*/
+}
+
+TYPE @testWrongRules225
+{
+ "userType2": 12 /* {type: "@catId",
+ maxItems: 10,
+ }*/
+}
+
+TYPE @testWrongRules226
+{
+ "userType2": 12 /* {type: "@catId",
+ or: [{type: "string"}, {type: "integer"}],
+ }*/
+}
+
+TYPE @testWrongRules227
+{
+ "userType2": 12 /* {type: "@catId",
+ additionalProperties: true,
+ }*/
+}
+
+TYPE @testWrongRules228
+{
+ "userType2": 12 /* {type: "@catId",
+ allOf: "@cat",
+ }*/
+}
+
+TYPE @testWrongRules229
+{
+ "userType2": 12 /* {type: "@catId",
+ enum: ["white", "black"]
+ }*/
+}
+
+# Helpfull types
+
+TYPE @cat
+{
+ "catId": @catId,
+ "catName": "Tom"
+}
+
+TYPE @catId
+ 12 // {min: 1}
diff --git a/tests/manual-tests/http-method-tests/http-method-replace-test-2.jst b/tests/manual-tests/http-method-tests/http-method-replace-test-2.jst
index 5872971..066c2a6 100644
--- a/tests/manual-tests/http-method-tests/http-method-replace-test-2.jst
+++ b/tests/manual-tests/http-method-tests/http-method-replace-test-2.jst
@@ -1,11 +1,11 @@
-JSIGHT 0.3
-
-INFO
- Description
- 1. Select POST tab in rendered documentation.
- 2. Select POST directory in the code and remove it by `Delete` button.
- 3. Check, that in rendered documentation GET tab is automatically selected.
-
-URL /1
- GET
+JSIGHT 0.3
+
+INFO
+ Description
+ 1. Select the POST tab in the rendered documentation.
+ 2. Select the POST directory in the code and remove it by the `Delete` button.
+ 3. Check, that in the rendered documentation the GET tab is automatically selected.
+
+URL /1
+ GET
POST
\ No newline at end of file
diff --git a/tests/manual-tests/http-method-tests/http-method-tests.jst b/tests/manual-tests/http-method-tests/http-method-tests.jst
index 591f048..eb6e7dc 100644
--- a/tests/manual-tests/http-method-tests/http-method-tests.jst
+++ b/tests/manual-tests/http-method-tests/http-method-tests.jst
@@ -59,6 +59,8 @@
PATCH
DELETE
+ GET /test-keywords/any-path-parameters/{par1} // Check the `par1` parameter in the "Path parameters" section.
+
URL /test-keywords/path-parameters/{par1}
Path
{
diff --git a/tests/manual-tests/mobile-ui-tests.md b/tests/manual-tests/mobile-ui-tests.md
index 9edd61d..7367a76 100644
--- a/tests/manual-tests/mobile-ui-tests.md
+++ b/tests/manual-tests/mobile-ui-tests.md
@@ -1,5 +1,9 @@
# Mobile UI tests
+## OpenAPI mode as default
+
+1. Check, that on mobile devices the OpenAPI mode is by default.
+
## Run common UI tests on mobile screen
Note: right now we should not check all the functions, but just simple things, which can satisfy a
diff --git a/tests/manual-tests/openapi-converter-tests/openapi-converter-tests.md b/tests/manual-tests/openapi-converter-tests/openapi-converter-tests.md
new file mode 100644
index 0000000..062d9e5
--- /dev/null
+++ b/tests/manual-tests/openapi-converter-tests/openapi-converter-tests.md
@@ -0,0 +1,10 @@
+# OpenAPI converter tests
+
+- Check the OpenAPI tab in the right tab panel.
+- Check the YAML and JSON OpenAPI formats.
+ - Check the line numbering from the first to the last (!) line.
+ - Check Horizontal and vertical scrolling of the OpenAPI panel.
+- Check the OpenAPI menu item in the main menu.
+- Check the "Copy All" button for the JSON and YAML formats. Check the copied code in the https://editor.swagger.io site.
+- Check copying the OpenAPI code with manual selection and Ctrl+C.
+- Check Download OpenAPI buttons: JSON and YAML.
\ No newline at end of file
diff --git a/tests/manual-tests/openapi-converter-tests/openapi-specific-error-test.jst b/tests/manual-tests/openapi-converter-tests/openapi-specific-error-test.jst
new file mode 100644
index 0000000..11b76f0
--- /dev/null
+++ b/tests/manual-tests/openapi-converter-tests/openapi-specific-error-test.jst
@@ -0,0 +1,13 @@
+###
+
+Test:
+1. Check that this code is successfully rendered in the HTML Doc mode.
+2. Check that this code is rendered with the error in the OpenAPI mode.
+
+###
+
+JSIGHT 0.3
+
+GET /
+ Query
+ ""
diff --git a/tests/manual-tests/share-link-tests.md b/tests/manual-tests/share-link-tests.md
index 8a16994..e46855f 100644
--- a/tests/manual-tests/share-link-tests.md
+++ b/tests/manual-tests/share-link-tests.md
@@ -80,6 +80,8 @@
all steps in the same browser window without refresh.
10. **Update not last version.** Get link with several versions (e.g. 3). Try to reproduce basic
share test cases 2 and 3, but each time use not last version of the link (e.g. 1).
+11. **OpenAPI**. Repeat all the basic tests, but each time before pressing the Share button, switch
+ to the OpenAPI tab.
# Error cases
diff --git a/tests/manual-tests/sidebar-details-tests/sidebar-details-card-all-sections.jst b/tests/manual-tests/sidebar-details-tests/sidebar-details-card-all-sections.jst
index e6ee686..75f7192 100644
--- a/tests/manual-tests/sidebar-details-tests/sidebar-details-card-all-sections.jst
+++ b/tests/manual-tests/sidebar-details-tests/sidebar-details-card-all-sections.jst
@@ -1,7 +1,7 @@
JSIGHT 0.3
INFO
- Title "Check details cards in different sections"
+ Title "Check details cards in different sections (jtest)" # always use `jtest` in test titles for the sake of statistics
Description
(
Check, that you can open details card in all types of sections.
diff --git a/tests/manual-tests/sidebar-details-tests/sidebar-details-card-all_rules.jst b/tests/manual-tests/sidebar-details-tests/sidebar-details-card-all_rules.jst
index eb77bd4..804fe58 100644
--- a/tests/manual-tests/sidebar-details-tests/sidebar-details-card-all_rules.jst
+++ b/tests/manual-tests/sidebar-details-tests/sidebar-details-card-all_rules.jst
@@ -72,7 +72,7 @@ TYPE @or
]} */
"orByValue": 123 /* {or: [
- {min: 100},
+ {type: "integer", min: 100},
{type: "string"}
]} */
diff --git a/tests/manual-tests/table-view-tests/table-view-root-line.jst b/tests/manual-tests/table-view-tests/table-view-root-line.jst
new file mode 100644
index 0000000..8f93c34
--- /dev/null
+++ b/tests/manual-tests/table-view-tests/table-view-root-line.jst
@@ -0,0 +1,32 @@
+JSIGHT 0.3
+
+INFO
+ Title "Test table view root line (jtest)"
+
+GET /{id}
+ Path
+ {
+ "id": 1 // MUST NOT be line above ONLY HERE!
+ }
+ Query "query_par=1"
+ {
+ "query_par": 1 // MUST be line above
+ }
+ 201
+ Headers
+ {
+ "Switch to the Table View →": "" // MUST be line above
+ }
+ Body any
+ 200
+ Headers
+ @headers
+ Body
+ {
+ "Switch to the Table View ": "" // MUST be line above
+ }
+
+TYPE @headers
+ {
+ "Switch to the Table View ": "" // MUST be line above
+ }
\ No newline at end of file
diff --git a/tests/running-automated-tests-ci.md b/tests/running-automated-tests-ci.md
new file mode 100644
index 0000000..2f19267
--- /dev/null
+++ b/tests/running-automated-tests-ci.md
@@ -0,0 +1,23 @@
+## How to run e2e automated tests remotely (CI/CD)
+
+1. Open the **[CircleCI Dashboard](https://app.circleci.com/pipelines/github/jsightapi)**, **"All Pipelines"** section.
+2. In the filter section...
+ 1. Select the **Project** = "**online-editor-e2e**".
+ 2. Select the **Branch** (e.g. "**main**").
+3. Click **"Trigger Pipeline"** button above.
+4. In the "**Add Parameters**" section...
+ - (Required) Add `boolean` parameter `fire` with value `true`.
+ - (Optional) Add another parameter(s), e.g.:
+
+ | Type | Name | Value | Description |
+ |---------|-------------------|---------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------|
+ | string | env | `dev` (or `stage`) | To run tests on the corresponding environment. |
+ | string | maven-test | internal name of the test class/test method | To run a specific test(s), e.g. `CodeViewTest`. |
+ | integer | junit-parallelism | `2` (`3`, `4`, etc) | For a number of threads, to run tests in parallel. |
+ | string | add-params | comma-separated list of `-Dkey=value` | Additional parameters for the Maven run, e.g. `-Dselenide.browser=firefox, -Dselenide.browserVersion=123.0, -Dselenide.timeout=8000`. |
+
+ _Note: the job with only default `fire = true` parameter will run all the tests on the default DEV environment. See `.circleci/config.yml` for more details._
+5. Click **"Trigger Pipeline"** button in the modal window.
+6. Wait for the pipeline to finish, and open the **"run-e2e"** job.
+7. Check the failed tests list (if any) in the "**Tests**" tab.
+8. Check the **Allure Report** in the "**Artifacts**" tab (open the one with `target/site/allure-maven-plugin/index.html` link)
\ No newline at end of file