docusaurus-theme-openapi-docs 1.3.2 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+
8
+ var _react = _interopRequireDefault(require("react"));
9
+
10
+ var _fileSaver = _interopRequireDefault(require("file-saver"));
11
+
12
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
+
14
+ /* ============================================================================
15
+ * Copyright (c) Palo Alto Networks
16
+ *
17
+ * This source code is licensed under the MIT license found in the
18
+ * LICENSE file in the root directory of this source tree.
19
+ * ========================================================================== */
20
+ const saveFile = url => {
21
+ let fileName;
22
+
23
+ if (url.endsWith("json") || url.endsWith("yaml") || url.endsWith("yml")) {
24
+ fileName = url.substring(url.lastIndexOf("/") + 1);
25
+ }
26
+
27
+ _fileSaver.default.saveAs(url, fileName ? fileName : "openapi.txt");
28
+ };
29
+
30
+ function Export({
31
+ url,
32
+ proxy
33
+ }) {
34
+ return <div style={{
35
+ float: "right"
36
+ }} className="dropdown dropdown--hoverable dropdown--right">
37
+ <button className="export-button button button--sm button--secondary">
38
+ Export
39
+ </button>
40
+ <ul className="export-dropdown dropdown__menu">
41
+ <li>
42
+ <a onClick={e => {
43
+ e.preventDefault();
44
+ saveFile(`${url}`);
45
+ }} className="dropdown__link" href={`${url}`}>
46
+ OpenAPI Spec
47
+ </a>
48
+ </li>
49
+ </ul>
50
+ </div>;
51
+ }
52
+
53
+ var _default = Export;
54
+ exports.default = _default;
@@ -35,15 +35,14 @@ function createPersistanceMiddleware(options) {
35
35
  if (state.auth.selected) {
36
36
  storage.setItem((0, _storageUtils.hashArray)(Object.keys(state.auth.options)), state.auth.selected);
37
37
  }
38
- }
39
-
40
- if (action.type === "contentType/setContentType") {
41
- storage.setItem("contentType", action.payload);
42
- }
38
+ } // TODO: determine way to rehydrate without flashing
39
+ // if (action.type === "contentType/setContentType") {
40
+ // storage.setItem("contentType", action.payload);
41
+ // }
42
+ // if (action.type === "accept/setAccept") {
43
+ // storage.setItem("accept", action.payload);
44
+ // }
43
45
 
44
- if (action.type === "accept/setAccept") {
45
- storage.setItem("accept", action.payload);
46
- }
47
46
 
48
47
  if (action.type === "server/setServer") {
49
48
  storage.setItem("server", action.payload);
@@ -3,17 +3,19 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.default = void 0;
6
+ exports.default = ApiItem;
7
7
 
8
8
  var _react = _interopRequireDefault(require("react"));
9
9
 
10
+ var _BrowserOnly = _interopRequireDefault(require("@docusaurus/BrowserOnly"));
11
+
10
12
  var _ExecutionEnvironment = _interopRequireDefault(require("@docusaurus/ExecutionEnvironment"));
11
13
 
12
14
  var _themeCommon = require("@docusaurus/theme-common");
13
15
 
14
16
  var _useDocusaurusContext = _interopRequireDefault(require("@docusaurus/useDocusaurusContext"));
15
17
 
16
- var _clsx = _interopRequireDefault(require("clsx"));
18
+ var _useIsBrowser = _interopRequireDefault(require("@docusaurus/useIsBrowser"));
17
19
 
18
20
  var _reactRedux = require("react-redux");
19
21
 
@@ -39,38 +41,42 @@ const {
39
41
  DocProvider
40
42
  } = require("@docusaurus/theme-common/internal");
41
43
 
42
- let ApiDemoPanel = _ => <div style={{
43
- marginTop: "3.5em"
44
- }} />;
45
-
46
- let DocItem = props => {
47
- return <div style={{
48
- marginTop: "3.5em"
49
- }} />;
50
- };
44
+ let ApiDemoPanel = _ => <div />;
51
45
 
52
46
  if (_ExecutionEnvironment.default.canUseDOM) {
53
47
  ApiDemoPanel = require("@theme/ApiDemoPanel").default;
48
+ }
49
+
50
+ function ApiItem(props) {
51
+ const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
52
+ const MDXComponent = props.content;
53
+ const {
54
+ frontMatter
55
+ } = MDXComponent;
56
+ const {
57
+ info_path: infoPath
58
+ } = frontMatter;
59
+ const {
60
+ api
61
+ } = frontMatter;
62
+ const {
63
+ siteConfig
64
+ } = (0, _useDocusaurusContext.default)();
65
+ const themeConfig = siteConfig.themeConfig;
66
+ const options = themeConfig.api;
67
+ const isBrowser = (0, _useIsBrowser.default)(); // Define store2
68
+
69
+ let store2 = {};
70
+ const persistanceMiddleware = (0, _persistanceMiddleware.createPersistanceMiddleware)(options); // Init store for SSR
71
+
72
+ if (!isBrowser) {
73
+ store2 = (0, _store.createStoreWithoutState)({}, [persistanceMiddleware]);
74
+ } // Init store for CSR to hydrate components
75
+
76
+
77
+ if (isBrowser) {
78
+ var _api$responses, _api$requestBody$cont, _api$requestBody, _api$servers, _api$parameters, _window, _ref;
54
79
 
55
- DocItem = function DocItem(props) {
56
- var _api$responses, _api$requestBody$cont, _api$requestBody, _api$servers, _api$parameters, _window, _window2, _window3, _ref;
57
-
58
- const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
59
- const MDXComponent = props.content;
60
- const {
61
- frontMatter
62
- } = MDXComponent;
63
- const {
64
- info_path: infoPath
65
- } = frontMatter;
66
- const {
67
- api
68
- } = frontMatter;
69
- const {
70
- siteConfig
71
- } = (0, _useDocusaurusContext.default)();
72
- const themeConfig = siteConfig.themeConfig;
73
- const options = themeConfig.api;
74
80
  const acceptArray = Array.from(new Set(Object.values((_api$responses = api === null || api === void 0 ? void 0 : api.responses) !== null && _api$responses !== void 0 ? _api$responses : {}).map(response => {
75
81
  var _response$content;
76
82
 
@@ -94,19 +100,19 @@ if (_ExecutionEnvironment.default.canUseDOM) {
94
100
  security: api === null || api === void 0 ? void 0 : api.security,
95
101
  securitySchemes: api === null || api === void 0 ? void 0 : api.securitySchemes,
96
102
  options
97
- });
98
- const persistanceMiddleware = (0, _persistanceMiddleware.createPersistanceMiddleware)(options);
99
- const acceptValue = (_window = window) === null || _window === void 0 ? void 0 : _window.sessionStorage.getItem("accept");
100
- const contentTypeValue = (_window2 = window) === null || _window2 === void 0 ? void 0 : _window2.sessionStorage.getItem("contentType");
101
- const server = (_window3 = window) === null || _window3 === void 0 ? void 0 : _window3.sessionStorage.getItem("server");
103
+ }); // TODO: determine way to rehydrate without flashing
104
+ // const acceptValue = window?.sessionStorage.getItem("accept");
105
+ // const contentTypeValue = window?.sessionStorage.getItem("contentType");
106
+
107
+ const server = (_window = window) === null || _window === void 0 ? void 0 : _window.sessionStorage.getItem("server");
102
108
  const serverObject = (_ref = JSON.parse(server)) !== null && _ref !== void 0 ? _ref : {};
103
- const store2 = (0, _store.createStoreWithState)({
109
+ store2 = (0, _store.createStoreWithState)({
104
110
  accept: {
105
- value: acceptValue || acceptArray[0],
111
+ value: acceptArray[0],
106
112
  options: acceptArray
107
113
  },
108
114
  contentType: {
109
- value: contentTypeValue || contentTypeArray[0],
115
+ value: contentTypeArray[0],
110
116
  options: contentTypeArray
111
117
  },
112
118
  server: {
@@ -122,30 +128,43 @@ if (_ExecutionEnvironment.default.canUseDOM) {
122
128
  params,
123
129
  auth
124
130
  }, [persistanceMiddleware]);
125
-
126
- const DocContent = () => {
127
- return <div className="row">
128
- <div className={(0, _clsx.default)("col", api ? "col--7" : "col--12")}>
129
- <MDXComponent />
131
+ }
132
+
133
+ if (api) {
134
+ return <DocProvider content={props.content}>
135
+ <_themeCommon.HtmlClassNameProvider className={docHtmlClassName}>
136
+ <_Metadata.default />
137
+ <_Layout.default>
138
+ <_reactRedux.Provider store={store2}>
139
+ <div className="row">
140
+ <div className="col col--7">
141
+ <MDXComponent />
142
+ </div>
143
+ <div className="col col--5">
144
+ <_BrowserOnly.default fallback={<div>Loading...</div>}>
145
+ {() => {
146
+ return <ApiDemoPanel item={api} infoPath={infoPath} />;
147
+ }}
148
+ </_BrowserOnly.default>
149
+ </div>
150
+ </div>
151
+ </_reactRedux.Provider>
152
+ </_Layout.default>
153
+ </_themeCommon.HtmlClassNameProvider>
154
+ </DocProvider>;
155
+ } // Non-API docs
156
+
157
+
158
+ return <DocProvider content={props.content}>
159
+ <_themeCommon.HtmlClassNameProvider className={docHtmlClassName}>
160
+ <_Metadata.default />
161
+ <_Layout.default>
162
+ <div className="row">
163
+ <div className="col col--12">
164
+ <MDXComponent />
165
+ </div>
130
166
  </div>
131
- {api && <div className="col col--5">
132
- <ApiDemoPanel item={api} infoPath={infoPath} />
133
- </div>}
134
- </div>;
135
- };
136
-
137
- return <_reactRedux.Provider store={store2}>
138
- <DocProvider content={props.content}>
139
- <_themeCommon.HtmlClassNameProvider className={docHtmlClassName}>
140
- <_Metadata.default />
141
- <_Layout.default>
142
- <DocContent />
143
- </_Layout.default>
144
- </_themeCommon.HtmlClassNameProvider>
145
- </DocProvider>
146
- </_reactRedux.Provider>;
147
- };
148
- }
149
-
150
- var _default = DocItem;
151
- exports.default = _default;
167
+ </_Layout.default>
168
+ </_themeCommon.HtmlClassNameProvider>
169
+ </DocProvider>;
170
+ }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.createStoreWithState = void 0;
6
+ exports.createStoreWithoutState = exports.createStoreWithState = void 0;
7
7
 
8
8
  var _toolkit = require("@reduxjs/toolkit");
9
9
 
@@ -45,4 +45,12 @@ const createStoreWithState = (preloadedState, middlewares) => (0, _toolkit.confi
45
45
  middleware: getDefaultMiddleware => getDefaultMiddleware().concat(...middlewares)
46
46
  });
47
47
 
48
- exports.createStoreWithState = createStoreWithState;
48
+ exports.createStoreWithState = createStoreWithState;
49
+
50
+ const createStoreWithoutState = (preloadedState, middlewares) => (0, _toolkit.configureStore)({
51
+ reducer: rootReducer,
52
+ preloadedState,
53
+ middleware: getDefaultMiddleware => getDefaultMiddleware().concat(...middlewares)
54
+ });
55
+
56
+ exports.createStoreWithoutState = createStoreWithoutState;
@@ -0,0 +1,49 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+ import React from "react";
8
+ import fileSaver from "file-saver";
9
+
10
+ const saveFile = (url) => {
11
+ let fileName;
12
+
13
+ if (url.endsWith("json") || url.endsWith("yaml") || url.endsWith("yml")) {
14
+ fileName = url.substring(url.lastIndexOf("/") + 1);
15
+ }
16
+
17
+ fileSaver.saveAs(url, fileName ? fileName : "openapi.txt");
18
+ };
19
+
20
+ function Export({ url, proxy }) {
21
+ return (
22
+ <div
23
+ style={{
24
+ float: "right",
25
+ }}
26
+ className="dropdown dropdown--hoverable dropdown--right"
27
+ >
28
+ <button className="export-button button button--sm button--secondary">
29
+ Export
30
+ </button>
31
+ <ul className="export-dropdown dropdown__menu">
32
+ <li>
33
+ <a
34
+ onClick={(e) => {
35
+ e.preventDefault();
36
+ saveFile(`${url}`);
37
+ }}
38
+ className="dropdown__link"
39
+ href={`${url}`}
40
+ >
41
+ OpenAPI Spec
42
+ </a>
43
+ </li>
44
+ </ul>
45
+ </div>
46
+ );
47
+ }
48
+
49
+ export default Export;
@@ -29,15 +29,13 @@ export function createPersistanceMiddleware(options) {
29
29
  state.auth.selected
30
30
  );
31
31
  }
32
- }
33
-
34
- if (action.type === "contentType/setContentType") {
35
- storage.setItem("contentType", action.payload);
36
- }
37
-
38
- if (action.type === "accept/setAccept") {
39
- storage.setItem("accept", action.payload);
40
- }
32
+ } // TODO: determine way to rehydrate without flashing
33
+ // if (action.type === "contentType/setContentType") {
34
+ // storage.setItem("contentType", action.payload);
35
+ // }
36
+ // if (action.type === "accept/setAccept") {
37
+ // storage.setItem("accept", action.payload);
38
+ // }
41
39
 
42
40
  if (action.type === "server/setServer") {
43
41
  storage.setItem("server", action.payload);
@@ -5,49 +5,45 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
  import React from "react";
8
+ import BrowserOnly from "@docusaurus/BrowserOnly";
8
9
  import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
9
10
  import { HtmlClassNameProvider } from "@docusaurus/theme-common";
10
11
  import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
11
- import clsx from "clsx";
12
+ import useIsBrowser from "@docusaurus/useIsBrowser";
12
13
  import { Provider } from "react-redux";
13
14
  import { createAuth } from "../ApiDemoPanel/Authorization/slice";
14
15
  import { createPersistanceMiddleware } from "../ApiDemoPanel/persistanceMiddleware";
15
16
  import DocItemLayout from "./Layout";
16
17
  import DocItemMetadata from "./Metadata";
17
- import { createStoreWithState } from "./store";
18
+ import { createStoreWithoutState, createStoreWithState } from "./store";
18
19
 
19
20
  const { DocProvider } = require("@docusaurus/theme-common/internal");
20
21
 
21
- let ApiDemoPanel = (_) => (
22
- <div
23
- style={{
24
- marginTop: "3.5em",
25
- }}
26
- />
27
- );
28
-
29
- let DocItem = (props) => {
30
- return (
31
- <div
32
- style={{
33
- marginTop: "3.5em",
34
- }}
35
- />
36
- );
37
- };
22
+ let ApiDemoPanel = (_) => <div />;
38
23
 
39
24
  if (ExecutionEnvironment.canUseDOM) {
40
25
  ApiDemoPanel = require("@theme/ApiDemoPanel").default;
26
+ }
27
+
28
+ export default function ApiItem(props) {
29
+ const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
30
+ const MDXComponent = props.content;
31
+ const { frontMatter } = MDXComponent;
32
+ const { info_path: infoPath } = frontMatter;
33
+ const { api } = frontMatter;
34
+ const { siteConfig } = useDocusaurusContext();
35
+ const themeConfig = siteConfig.themeConfig;
36
+ const options = themeConfig.api;
37
+ const isBrowser = useIsBrowser(); // Define store2
41
38
 
42
- DocItem = function DocItem(props) {
43
- const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
44
- const MDXComponent = props.content;
45
- const { frontMatter } = MDXComponent;
46
- const { info_path: infoPath } = frontMatter;
47
- const { api } = frontMatter;
48
- const { siteConfig } = useDocusaurusContext();
49
- const themeConfig = siteConfig.themeConfig;
50
- const options = themeConfig.api;
39
+ let store2 = {};
40
+ const persistanceMiddleware = createPersistanceMiddleware(options); // Init store for SSR
41
+
42
+ if (!isBrowser) {
43
+ store2 = createStoreWithoutState({}, [persistanceMiddleware]);
44
+ } // Init store for CSR to hydrate components
45
+
46
+ if (isBrowser) {
51
47
  const acceptArray = Array.from(
52
48
  new Set(
53
49
  Object.values(api?.responses ?? {})
@@ -73,20 +69,20 @@ if (ExecutionEnvironment.canUseDOM) {
73
69
  security: api?.security,
74
70
  securitySchemes: api?.securitySchemes,
75
71
  options,
76
- });
77
- const persistanceMiddleware = createPersistanceMiddleware(options);
78
- const acceptValue = window?.sessionStorage.getItem("accept");
79
- const contentTypeValue = window?.sessionStorage.getItem("contentType");
72
+ }); // TODO: determine way to rehydrate without flashing
73
+ // const acceptValue = window?.sessionStorage.getItem("accept");
74
+ // const contentTypeValue = window?.sessionStorage.getItem("contentType");
75
+
80
76
  const server = window?.sessionStorage.getItem("server");
81
77
  const serverObject = JSON.parse(server) ?? {};
82
- const store2 = createStoreWithState(
78
+ store2 = createStoreWithState(
83
79
  {
84
80
  accept: {
85
- value: acceptValue || acceptArray[0],
81
+ value: acceptArray[0],
86
82
  options: acceptArray,
87
83
  },
88
84
  contentType: {
89
- value: contentTypeValue || contentTypeArray[0],
85
+ value: contentTypeArray[0],
90
86
  options: contentTypeArray,
91
87
  },
92
88
  server: {
@@ -104,35 +100,46 @@ if (ExecutionEnvironment.canUseDOM) {
104
100
  },
105
101
  [persistanceMiddleware]
106
102
  );
103
+ }
107
104
 
108
- const DocContent = () => {
109
- return (
110
- <div className="row">
111
- <div className={clsx("col", api ? "col--7" : "col--12")}>
112
- <MDXComponent />
113
- </div>
114
- {api && (
115
- <div className="col col--5">
116
- <ApiDemoPanel item={api} infoPath={infoPath} />
117
- </div>
118
- )}
119
- </div>
120
- );
121
- };
122
-
105
+ if (api) {
123
106
  return (
124
- <Provider store={store2}>
125
- <DocProvider content={props.content}>
126
- <HtmlClassNameProvider className={docHtmlClassName}>
127
- <DocItemMetadata />
128
- <DocItemLayout>
129
- <DocContent />
130
- </DocItemLayout>
131
- </HtmlClassNameProvider>
132
- </DocProvider>
133
- </Provider>
107
+ <DocProvider content={props.content}>
108
+ <HtmlClassNameProvider className={docHtmlClassName}>
109
+ <DocItemMetadata />
110
+ <DocItemLayout>
111
+ <Provider store={store2}>
112
+ <div className="row">
113
+ <div className="col col--7">
114
+ <MDXComponent />
115
+ </div>
116
+ <div className="col col--5">
117
+ <BrowserOnly fallback={<div>Loading...</div>}>
118
+ {() => {
119
+ return <ApiDemoPanel item={api} infoPath={infoPath} />;
120
+ }}
121
+ </BrowserOnly>
122
+ </div>
123
+ </div>
124
+ </Provider>
125
+ </DocItemLayout>
126
+ </HtmlClassNameProvider>
127
+ </DocProvider>
134
128
  );
135
- };
136
- }
129
+ } // Non-API docs
137
130
 
138
- export default DocItem;
131
+ return (
132
+ <DocProvider content={props.content}>
133
+ <HtmlClassNameProvider className={docHtmlClassName}>
134
+ <DocItemMetadata />
135
+ <DocItemLayout>
136
+ <div className="row">
137
+ <div className="col col--12">
138
+ <MDXComponent />
139
+ </div>
140
+ </div>
141
+ </DocItemLayout>
142
+ </HtmlClassNameProvider>
143
+ </DocProvider>
144
+ );
145
+ }
@@ -28,3 +28,10 @@ export const createStoreWithState = (preloadedState, middlewares) =>
28
28
  middleware: (getDefaultMiddleware) =>
29
29
  getDefaultMiddleware().concat(...middlewares),
30
30
  });
31
+ export const createStoreWithoutState = (preloadedState, middlewares) =>
32
+ configureStore({
33
+ reducer: rootReducer,
34
+ preloadedState,
35
+ middleware: (getDefaultMiddleware) =>
36
+ getDefaultMiddleware().concat(...middlewares),
37
+ });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docusaurus-theme-openapi-docs",
3
3
  "description": "OpenAPI theme for Docusaurus.",
4
- "version": "1.3.2",
4
+ "version": "1.4.1",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -35,6 +35,7 @@
35
35
  "@docusaurus/types": "2.0.1",
36
36
  "@types/concurrently": "^6.3.0",
37
37
  "@types/crypto-js": "^4.1.0",
38
+ "@types/file-saver": "^2.0.5",
38
39
  "@types/fs-extra": "^9.0.13",
39
40
  "@types/lodash": "^4.14.176",
40
41
  "@types/mdx-js__react": "^1.5.4",
@@ -50,7 +51,8 @@
50
51
  "buffer": "^6.0.3",
51
52
  "clsx": "^1.1.1",
52
53
  "crypto-js": "^4.1.1",
53
- "docusaurus-plugin-openapi-docs": "^1.3.2",
54
+ "docusaurus-plugin-openapi-docs": "^1.4.1",
55
+ "file-saver": "^2.0.5",
54
56
  "immer": "^9.0.7",
55
57
  "lodash": "^4.17.20",
56
58
  "process": "^0.11.10",
@@ -71,5 +73,5 @@
71
73
  "engines": {
72
74
  "node": ">=14"
73
75
  },
74
- "gitHead": "761a89172da04573369441cf7342f6c643bc3ecd"
76
+ "gitHead": "ddfa49093f75f628536b8d9e25f88eb9e541667c"
75
77
  }
@@ -0,0 +1,47 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+
8
+ import React from "react";
9
+
10
+ import fileSaver from "file-saver";
11
+
12
+ const saveFile = (url: string) => {
13
+ let fileName;
14
+ if (url.endsWith("json") || url.endsWith("yaml") || url.endsWith("yml")) {
15
+ fileName = url.substring(url.lastIndexOf("/") + 1);
16
+ }
17
+ fileSaver.saveAs(url, fileName ? fileName : "openapi.txt");
18
+ };
19
+
20
+ function Export({ url, proxy }: any) {
21
+ return (
22
+ <div
23
+ style={{ float: "right" }}
24
+ className="dropdown dropdown--hoverable dropdown--right"
25
+ >
26
+ <button className="export-button button button--sm button--secondary">
27
+ Export
28
+ </button>
29
+ <ul className="export-dropdown dropdown__menu">
30
+ <li>
31
+ <a
32
+ onClick={(e) => {
33
+ e.preventDefault();
34
+ saveFile(`${url}`);
35
+ }}
36
+ className="dropdown__link"
37
+ href={`${url}`}
38
+ >
39
+ OpenAPI Spec
40
+ </a>
41
+ </li>
42
+ </ul>
43
+ </div>
44
+ );
45
+ }
46
+
47
+ export default Export;
@@ -40,13 +40,14 @@ export function createPersistanceMiddleware(options: ThemeConfig["api"]) {
40
40
  }
41
41
  }
42
42
 
43
- if (action.type === "contentType/setContentType") {
44
- storage.setItem("contentType", action.payload);
45
- }
43
+ // TODO: determine way to rehydrate without flashing
44
+ // if (action.type === "contentType/setContentType") {
45
+ // storage.setItem("contentType", action.payload);
46
+ // }
46
47
 
47
- if (action.type === "accept/setAccept") {
48
- storage.setItem("accept", action.payload);
49
- }
48
+ // if (action.type === "accept/setAccept") {
49
+ // storage.setItem("accept", action.payload);
50
+ // }
50
51
 
51
52
  if (action.type === "server/setServer") {
52
53
  storage.setItem("server", action.payload);
@@ -7,11 +7,12 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import BrowserOnly from "@docusaurus/BrowserOnly";
10
11
  import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
11
12
  import { HtmlClassNameProvider } from "@docusaurus/theme-common";
12
13
  import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
14
+ import useIsBrowser from "@docusaurus/useIsBrowser";
13
15
  import type { Props } from "@theme/DocItem";
14
- import clsx from "clsx";
15
16
  import { ServerObject } from "docusaurus-plugin-openapi-docs/lib/openapi/types";
16
17
  import type { ApiItem as ApiItemType } from "docusaurus-plugin-openapi-docs/lib/types";
17
18
  import { ParameterObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
@@ -23,35 +24,42 @@ import { createAuth } from "../ApiDemoPanel/Authorization/slice";
23
24
  import { createPersistanceMiddleware } from "../ApiDemoPanel/persistanceMiddleware";
24
25
  import DocItemLayout from "./Layout";
25
26
  import DocItemMetadata from "./Metadata";
26
- import { createStoreWithState } from "./store";
27
+ import { createStoreWithoutState, createStoreWithState } from "./store";
27
28
 
28
29
  const { DocProvider } = require("@docusaurus/theme-common/internal");
29
30
 
30
- let ApiDemoPanel = (_: { item: any; infoPath: any }) => (
31
- <div style={{ marginTop: "3.5em" }} />
32
- );
31
+ let ApiDemoPanel = (_: { item: any; infoPath: any }) => <div />;
33
32
 
34
- let DocItem = (props: Props) => {
35
- return <div style={{ marginTop: "3.5em" }} />;
36
- };
33
+ if (ExecutionEnvironment.canUseDOM) {
34
+ ApiDemoPanel = require("@theme/ApiDemoPanel").default;
35
+ }
37
36
 
38
37
  interface ApiFrontMatter extends DocFrontMatter {
39
38
  readonly api?: ApiItemType;
40
39
  }
41
40
 
42
- if (ExecutionEnvironment.canUseDOM) {
43
- ApiDemoPanel = require("@theme/ApiDemoPanel").default;
44
-
45
- DocItem = function DocItem(props: Props): JSX.Element {
46
- const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
47
- const MDXComponent = props.content;
48
- const { frontMatter } = MDXComponent;
49
- const { info_path: infoPath } = frontMatter as DocFrontMatter;
50
- const { api } = frontMatter as ApiFrontMatter;
51
- const { siteConfig } = useDocusaurusContext();
52
- const themeConfig = siteConfig.themeConfig as ThemeConfig;
53
- const options = themeConfig.api;
54
-
41
+ export default function ApiItem(props: Props): JSX.Element {
42
+ const docHtmlClassName = `docs-doc-id-${props.content.metadata.unversionedId}`;
43
+ const MDXComponent = props.content;
44
+ const { frontMatter } = MDXComponent;
45
+ const { info_path: infoPath } = frontMatter as DocFrontMatter;
46
+ const { api } = frontMatter as ApiFrontMatter;
47
+ const { siteConfig } = useDocusaurusContext();
48
+ const themeConfig = siteConfig.themeConfig as ThemeConfig;
49
+ const options = themeConfig.api;
50
+ const isBrowser = useIsBrowser();
51
+
52
+ // Define store2
53
+ let store2: any = {};
54
+ const persistanceMiddleware = createPersistanceMiddleware(options);
55
+
56
+ // Init store for SSR
57
+ if (!isBrowser) {
58
+ store2 = createStoreWithoutState({}, [persistanceMiddleware]);
59
+ }
60
+
61
+ // Init store for CSR to hydrate components
62
+ if (isBrowser) {
55
63
  const acceptArray = Array.from(
56
64
  new Set(
57
65
  Object.values(api?.responses ?? {})
@@ -59,18 +67,15 @@ if (ExecutionEnvironment.canUseDOM) {
59
67
  .flat()
60
68
  )
61
69
  );
62
-
63
70
  const content = api?.requestBody?.content ?? {};
64
71
  const contentTypeArray = Object.keys(content);
65
72
  const servers = api?.servers ?? [];
66
-
67
73
  const params = {
68
74
  path: [] as ParameterObject[],
69
75
  query: [] as ParameterObject[],
70
76
  header: [] as ParameterObject[],
71
77
  cookie: [] as ParameterObject[],
72
78
  };
73
-
74
79
  api?.parameters?.forEach(
75
80
  (param: { in: "path" | "query" | "header" | "cookie" }) => {
76
81
  const paramType = param.in;
@@ -78,23 +83,25 @@ if (ExecutionEnvironment.canUseDOM) {
78
83
  paramsArray.push(param as ParameterObject);
79
84
  }
80
85
  );
81
-
82
86
  const auth = createAuth({
83
87
  security: api?.security,
84
88
  securitySchemes: api?.securitySchemes,
85
89
  options,
86
90
  });
87
-
88
- const persistanceMiddleware = createPersistanceMiddleware(options);
89
- const acceptValue = window?.sessionStorage.getItem("accept");
90
- const contentTypeValue = window?.sessionStorage.getItem("contentType");
91
+ // TODO: determine way to rehydrate without flashing
92
+ // const acceptValue = window?.sessionStorage.getItem("accept");
93
+ // const contentTypeValue = window?.sessionStorage.getItem("contentType");
91
94
  const server = window?.sessionStorage.getItem("server");
92
95
  const serverObject = (JSON.parse(server!) as ServerObject) ?? {};
93
- const store2 = createStoreWithState(
96
+
97
+ store2 = createStoreWithState(
94
98
  {
95
- accept: { value: acceptValue || acceptArray[0], options: acceptArray },
99
+ accept: {
100
+ value: acceptArray[0],
101
+ options: acceptArray,
102
+ },
96
103
  contentType: {
97
- value: contentTypeValue || contentTypeArray[0],
104
+ value: contentTypeArray[0],
98
105
  options: contentTypeArray,
99
106
  },
100
107
  server: {
@@ -108,35 +115,47 @@ if (ExecutionEnvironment.canUseDOM) {
108
115
  },
109
116
  [persistanceMiddleware]
110
117
  );
118
+ }
111
119
 
112
- const DocContent = () => {
113
- return (
114
- <div className="row">
115
- <div className={clsx("col", api ? "col--7" : "col--12")}>
116
- <MDXComponent />
117
- </div>
118
- {api && (
119
- <div className="col col--5">
120
- <ApiDemoPanel item={api} infoPath={infoPath} />
121
- </div>
122
- )}
123
- </div>
124
- );
125
- };
126
-
120
+ if (api) {
127
121
  return (
128
- <Provider store={store2}>
129
- <DocProvider content={props.content}>
130
- <HtmlClassNameProvider className={docHtmlClassName}>
131
- <DocItemMetadata />
132
- <DocItemLayout>
133
- <DocContent />
134
- </DocItemLayout>
135
- </HtmlClassNameProvider>
136
- </DocProvider>
137
- </Provider>
122
+ <DocProvider content={props.content}>
123
+ <HtmlClassNameProvider className={docHtmlClassName}>
124
+ <DocItemMetadata />
125
+ <DocItemLayout>
126
+ <Provider store={store2}>
127
+ <div className="row">
128
+ <div className="col col--7">
129
+ <MDXComponent />
130
+ </div>
131
+ <div className="col col--5">
132
+ <BrowserOnly fallback={<div>Loading...</div>}>
133
+ {() => {
134
+ return <ApiDemoPanel item={api} infoPath={infoPath} />;
135
+ }}
136
+ </BrowserOnly>
137
+ </div>
138
+ </div>
139
+ </Provider>
140
+ </DocItemLayout>
141
+ </HtmlClassNameProvider>
142
+ </DocProvider>
138
143
  );
139
- };
144
+ }
145
+
146
+ // Non-API docs
147
+ return (
148
+ <DocProvider content={props.content}>
149
+ <HtmlClassNameProvider className={docHtmlClassName}>
150
+ <DocItemMetadata />
151
+ <DocItemLayout>
152
+ <div className="row">
153
+ <div className="col col--12">
154
+ <MDXComponent />
155
+ </div>
156
+ </div>
157
+ </DocItemLayout>
158
+ </HtmlClassNameProvider>
159
+ </DocProvider>
160
+ );
140
161
  }
141
-
142
- export default DocItem;
@@ -38,4 +38,15 @@ export const createStoreWithState = (
38
38
  getDefaultMiddleware().concat(...middlewares),
39
39
  });
40
40
 
41
+ export const createStoreWithoutState = (
42
+ preloadedState: {},
43
+ middlewares: any[]
44
+ ) =>
45
+ configureStore({
46
+ reducer: rootReducer,
47
+ preloadedState,
48
+ middleware: (getDefaultMiddleware) =>
49
+ getDefaultMiddleware().concat(...middlewares),
50
+ });
51
+
41
52
  export type AppDispatch = ReturnType<typeof createStoreWithState>["dispatch"];