@backstage/plugin-techdocs 0.12.12 → 0.13.0
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.
- package/CHANGELOG.md +141 -0
- package/dist/index.d.ts +51 -18
- package/dist/index.esm.js +75 -48
- package/dist/index.esm.js.map +1 -1
- package/package.json +16 -16
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,146 @@
|
|
|
1
1
|
# @backstage/plugin-techdocs
|
|
2
2
|
|
|
3
|
+
## 0.13.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- aecfe4f403: Make `TechDocsClient` and `TechDocsStorageClient` use the `FetchApi`. You now
|
|
8
|
+
need to pass in an instance of that API when constructing the client, if you
|
|
9
|
+
create a custom instance in your app.
|
|
10
|
+
|
|
11
|
+
If you are replacing the factory:
|
|
12
|
+
|
|
13
|
+
```diff
|
|
14
|
+
+import { fetchApiRef } from '@backstage/core-plugin-api';
|
|
15
|
+
|
|
16
|
+
createApiFactory({
|
|
17
|
+
api: techdocsStorageApiRef,
|
|
18
|
+
deps: {
|
|
19
|
+
configApi: configApiRef,
|
|
20
|
+
discoveryApi: discoveryApiRef,
|
|
21
|
+
identityApi: identityApiRef,
|
|
22
|
+
+ fetchApi: fetchApiRef,
|
|
23
|
+
},
|
|
24
|
+
factory: ({
|
|
25
|
+
configApi,
|
|
26
|
+
discoveryApi,
|
|
27
|
+
identityApi,
|
|
28
|
+
+ fetchApi,
|
|
29
|
+
}) =>
|
|
30
|
+
new TechDocsStorageClient({
|
|
31
|
+
configApi,
|
|
32
|
+
discoveryApi,
|
|
33
|
+
identityApi,
|
|
34
|
+
+ fetchApi,
|
|
35
|
+
}),
|
|
36
|
+
}),
|
|
37
|
+
createApiFactory({
|
|
38
|
+
api: techdocsApiRef,
|
|
39
|
+
deps: {
|
|
40
|
+
configApi: configApiRef,
|
|
41
|
+
discoveryApi: discoveryApiRef,
|
|
42
|
+
- identityApi: identityApiRef,
|
|
43
|
+
+ fetchApi: fetchApiRef,
|
|
44
|
+
},
|
|
45
|
+
factory: ({
|
|
46
|
+
configApi,
|
|
47
|
+
discoveryApi,
|
|
48
|
+
- identityApi,
|
|
49
|
+
+ fetchApi,
|
|
50
|
+
}) =>
|
|
51
|
+
new TechDocsClient({
|
|
52
|
+
configApi,
|
|
53
|
+
discoveryApi,
|
|
54
|
+
- identityApi,
|
|
55
|
+
+ fetchApi,
|
|
56
|
+
}),
|
|
57
|
+
}),
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
If instantiating directly:
|
|
61
|
+
|
|
62
|
+
```diff
|
|
63
|
+
+import { fetchApiRef } from '@backstage/core-plugin-api';
|
|
64
|
+
|
|
65
|
+
+const fetchApi = useApi(fetchApiRef);
|
|
66
|
+
const storageClient = new TechDocsStorageClient({
|
|
67
|
+
configApi,
|
|
68
|
+
discoveryApi,
|
|
69
|
+
identityApi,
|
|
70
|
+
+ fetchApi,
|
|
71
|
+
});
|
|
72
|
+
const techdocsClient = new TechDocsClient({
|
|
73
|
+
configApi,
|
|
74
|
+
discoveryApi,
|
|
75
|
+
- identityApi,
|
|
76
|
+
+ fetchApi,
|
|
77
|
+
}),
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Patch Changes
|
|
81
|
+
|
|
82
|
+
- 51fbedc445: Migrated usage of deprecated `IdentityApi` methods.
|
|
83
|
+
- 29710c91c2: use lighter color for block quotes and horizontal rulers
|
|
84
|
+
- Updated dependencies
|
|
85
|
+
- @backstage/core-components@0.8.5
|
|
86
|
+
- @backstage/integration@0.7.2
|
|
87
|
+
- @backstage/plugin-search@0.5.6
|
|
88
|
+
- @backstage/core-plugin-api@0.6.0
|
|
89
|
+
- @backstage/plugin-catalog@0.7.9
|
|
90
|
+
- @backstage/plugin-catalog-react@0.6.12
|
|
91
|
+
- @backstage/config@0.1.13
|
|
92
|
+
- @backstage/catalog-model@0.9.10
|
|
93
|
+
- @backstage/integration-react@0.1.19
|
|
94
|
+
|
|
95
|
+
## 0.12.15-next.0
|
|
96
|
+
|
|
97
|
+
### Patch Changes
|
|
98
|
+
|
|
99
|
+
- 51fbedc445: Migrated usage of deprecated `IdentityApi` methods.
|
|
100
|
+
- 29710c91c2: use lighter color for block quotes and horizontal rulers
|
|
101
|
+
- Updated dependencies
|
|
102
|
+
- @backstage/core-components@0.8.5-next.0
|
|
103
|
+
- @backstage/core-plugin-api@0.6.0-next.0
|
|
104
|
+
- @backstage/plugin-catalog@0.7.9-next.0
|
|
105
|
+
- @backstage/config@0.1.13-next.0
|
|
106
|
+
- @backstage/plugin-catalog-react@0.6.12-next.0
|
|
107
|
+
- @backstage/plugin-search@0.5.6-next.0
|
|
108
|
+
- @backstage/catalog-model@0.9.10-next.0
|
|
109
|
+
- @backstage/integration-react@0.1.19-next.0
|
|
110
|
+
- @backstage/integration@0.7.2-next.0
|
|
111
|
+
|
|
112
|
+
## 0.12.14
|
|
113
|
+
|
|
114
|
+
### Patch Changes
|
|
115
|
+
|
|
116
|
+
- 5333451def: Cleaned up API exports
|
|
117
|
+
- 1628ca3f49: Fix an issue where the TechDocs sidebar is hidden when the Backstage sidebar is pinned at smaller screen sizes
|
|
118
|
+
- Updated dependencies
|
|
119
|
+
- @backstage/config@0.1.12
|
|
120
|
+
- @backstage/integration@0.7.1
|
|
121
|
+
- @backstage/core-components@0.8.4
|
|
122
|
+
- @backstage/core-plugin-api@0.5.0
|
|
123
|
+
- @backstage/plugin-catalog-react@0.6.11
|
|
124
|
+
- @backstage/errors@0.2.0
|
|
125
|
+
- @backstage/catalog-model@0.9.9
|
|
126
|
+
- @backstage/integration-react@0.1.18
|
|
127
|
+
- @backstage/plugin-catalog@0.7.8
|
|
128
|
+
- @backstage/plugin-search@0.5.5
|
|
129
|
+
|
|
130
|
+
## 0.12.13
|
|
131
|
+
|
|
132
|
+
### Patch Changes
|
|
133
|
+
|
|
134
|
+
- fe9de6c25b: Adds support for opening internal Techdocs links in a new tab with CTRL+Click or CMD+Click
|
|
135
|
+
- 4ce51ab0f1: Internal refactor of the `react-use` imports to use `react-use/lib/*` instead.
|
|
136
|
+
- e0271456d8: Updated Techdocs footer navigation to dynamically resize to the width of the dom, resolving an issue where a pinned sidebar causes navigation to go off of the screen
|
|
137
|
+
- Updated dependencies
|
|
138
|
+
- @backstage/plugin-search@0.5.4
|
|
139
|
+
- @backstage/core-plugin-api@0.4.1
|
|
140
|
+
- @backstage/plugin-catalog-react@0.6.10
|
|
141
|
+
- @backstage/core-components@0.8.3
|
|
142
|
+
- @backstage/plugin-catalog@0.7.7
|
|
143
|
+
|
|
3
144
|
## 0.12.12
|
|
4
145
|
|
|
5
146
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
3
|
-
import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';
|
|
3
|
+
import { DiscoveryApi, FetchApi, IdentityApi } from '@backstage/core-plugin-api';
|
|
4
4
|
import * as _backstage_catalog_model from '@backstage/catalog-model';
|
|
5
5
|
import { Entity, LocationSpec, EntityName } from '@backstage/catalog-model';
|
|
6
6
|
import { Config } from '@backstage/config';
|
|
@@ -19,10 +19,33 @@ declare type TechDocsEntityMetadata = Entity & {
|
|
|
19
19
|
locationMetadata?: LocationSpec;
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Utility API reference for the {@link TechDocsStorageApi}.
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
22
27
|
declare const techdocsStorageApiRef: _backstage_core_plugin_api.ApiRef<TechDocsStorageApi>;
|
|
28
|
+
/**
|
|
29
|
+
* Utility API reference for the {@link TechDocsApi}.
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
23
33
|
declare const techdocsApiRef: _backstage_core_plugin_api.ApiRef<TechDocsApi>;
|
|
34
|
+
/**
|
|
35
|
+
* The outcome of a docs sync operation.
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
24
39
|
declare type SyncResult = 'cached' | 'updated';
|
|
40
|
+
/**
|
|
41
|
+
* API which talks to TechDocs storage to fetch files to render.
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
25
45
|
interface TechDocsStorageApi {
|
|
46
|
+
/**
|
|
47
|
+
* Set to techdocs.requestUrl as the URL for techdocs-backend API.
|
|
48
|
+
*/
|
|
26
49
|
getApiOrigin(): Promise<string>;
|
|
27
50
|
getStorageUrl(): Promise<string>;
|
|
28
51
|
getBuilder(): Promise<string>;
|
|
@@ -30,25 +53,33 @@ interface TechDocsStorageApi {
|
|
|
30
53
|
syncEntityDocs(entityId: EntityName, logHandler?: (line: string) => void): Promise<SyncResult>;
|
|
31
54
|
getBaseUrl(oldBaseUrl: string, entityId: EntityName, path: string): Promise<string>;
|
|
32
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* API to talk to techdocs-backend.
|
|
58
|
+
*
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
33
61
|
interface TechDocsApi {
|
|
62
|
+
/**
|
|
63
|
+
* Set to techdocs.requestUrl as the URL for techdocs-backend API.
|
|
64
|
+
*/
|
|
34
65
|
getApiOrigin(): Promise<string>;
|
|
35
66
|
getTechDocsMetadata(entityId: EntityName): Promise<TechDocsMetadata>;
|
|
36
67
|
getEntityMetadata(entityId: EntityName): Promise<TechDocsEntityMetadata>;
|
|
37
68
|
}
|
|
38
69
|
|
|
39
70
|
/**
|
|
40
|
-
* API to talk to techdocs-backend
|
|
71
|
+
* API to talk to `techdocs-backend`.
|
|
41
72
|
*
|
|
42
|
-
* @
|
|
73
|
+
* @public
|
|
43
74
|
*/
|
|
44
75
|
declare class TechDocsClient implements TechDocsApi {
|
|
45
76
|
configApi: Config;
|
|
46
77
|
discoveryApi: DiscoveryApi;
|
|
47
|
-
|
|
48
|
-
constructor(
|
|
78
|
+
private fetchApi;
|
|
79
|
+
constructor(options: {
|
|
49
80
|
configApi: Config;
|
|
50
81
|
discoveryApi: DiscoveryApi;
|
|
51
|
-
|
|
82
|
+
fetchApi: FetchApi;
|
|
52
83
|
});
|
|
53
84
|
getApiOrigin(): Promise<string>;
|
|
54
85
|
/**
|
|
@@ -58,7 +89,7 @@ declare class TechDocsClient implements TechDocsApi {
|
|
|
58
89
|
* static files. It includes necessary data about the docs site. This method requests techdocs-backend
|
|
59
90
|
* which retrieves the TechDocs metadata.
|
|
60
91
|
*
|
|
61
|
-
* @param
|
|
92
|
+
* @param entityId - Object containing entity data like name, namespace, etc.
|
|
62
93
|
*/
|
|
63
94
|
getTechDocsMetadata(entityId: EntityName): Promise<TechDocsMetadata>;
|
|
64
95
|
/**
|
|
@@ -67,23 +98,25 @@ declare class TechDocsClient implements TechDocsApi {
|
|
|
67
98
|
* This method requests techdocs-backend which uses the catalog APIs to respond with filtered
|
|
68
99
|
* information required here.
|
|
69
100
|
*
|
|
70
|
-
* @param
|
|
101
|
+
* @param entityId - Object containing entity data like name, namespace, etc.
|
|
71
102
|
*/
|
|
72
103
|
getEntityMetadata(entityId: EntityName): Promise<TechDocsEntityMetadata>;
|
|
73
104
|
}
|
|
74
105
|
/**
|
|
75
106
|
* API which talks to TechDocs storage to fetch files to render.
|
|
76
107
|
*
|
|
77
|
-
* @
|
|
108
|
+
* @public
|
|
78
109
|
*/
|
|
79
110
|
declare class TechDocsStorageClient implements TechDocsStorageApi {
|
|
80
111
|
configApi: Config;
|
|
81
112
|
discoveryApi: DiscoveryApi;
|
|
82
113
|
identityApi: IdentityApi;
|
|
83
|
-
|
|
114
|
+
private fetchApi;
|
|
115
|
+
constructor(options: {
|
|
84
116
|
configApi: Config;
|
|
85
117
|
discoveryApi: DiscoveryApi;
|
|
86
118
|
identityApi: IdentityApi;
|
|
119
|
+
fetchApi: FetchApi;
|
|
87
120
|
});
|
|
88
121
|
getApiOrigin(): Promise<string>;
|
|
89
122
|
getStorageUrl(): Promise<string>;
|
|
@@ -91,19 +124,19 @@ declare class TechDocsStorageClient implements TechDocsStorageApi {
|
|
|
91
124
|
/**
|
|
92
125
|
* Fetch HTML content as text for an individual docs page in an entity's docs site.
|
|
93
126
|
*
|
|
94
|
-
* @param
|
|
95
|
-
* @param
|
|
96
|
-
* @returns
|
|
97
|
-
* @throws
|
|
127
|
+
* @param entityId - Object containing entity data like name, namespace, etc.
|
|
128
|
+
* @param path - The unique path to an individual docs page e.g. overview/what-is-new
|
|
129
|
+
* @returns HTML content of the docs page as string
|
|
130
|
+
* @throws Throws error when the page is not found.
|
|
98
131
|
*/
|
|
99
132
|
getEntityDocs(entityId: EntityName, path: string): Promise<string>;
|
|
100
133
|
/**
|
|
101
134
|
* Check if docs are on the latest version and trigger rebuild if not
|
|
102
135
|
*
|
|
103
|
-
* @param
|
|
104
|
-
* @param
|
|
105
|
-
* @returns
|
|
106
|
-
* @throws
|
|
136
|
+
* @param entityId - Object containing entity data like name, namespace, etc.
|
|
137
|
+
* @param logHandler - Callback to receive log messages from the build process
|
|
138
|
+
* @returns Whether documents are currently synchronized to newest version
|
|
139
|
+
* @throws Throws error on error from sync endpoint in Techdocs Backend
|
|
107
140
|
*/
|
|
108
141
|
syncEntityDocs(entityId: EntityName, logHandler?: (line: string) => void): Promise<SyncResult>;
|
|
109
142
|
getBaseUrl(oldBaseUrl: string, entityId: EntityName, path: string): Promise<string>;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { createApiRef, createRouteRef, useRouteRef, useApi, configApiRef, createPlugin, createApiFactory, discoveryApiRef, identityApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
|
|
1
|
+
import { createApiRef, createRouteRef, useRouteRef, useApi, configApiRef, createPlugin, createApiFactory, discoveryApiRef, identityApiRef, fetchApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
|
|
2
2
|
import { ResponseError, NotFoundError } from '@backstage/errors';
|
|
3
3
|
import { EventSourcePolyfill } from 'event-source-polyfill';
|
|
4
4
|
import React, { useEffect, useState, useReducer, useRef, useMemo, createContext, useContext, useCallback } from 'react';
|
|
5
5
|
import { makeStyles, ListItemText, ListItem, Divider, Card, CardMedia, CardContent, CardActions, Grid, TextField, InputAdornment, IconButton, CircularProgress, createStyles, Button as Button$1, Drawer, Typography, useTheme } from '@material-ui/core';
|
|
6
|
-
import { Link, SubvalueCell, Table, EmptyState, Button, WarningPanel, CodeSnippet, PageWithHeader, Content, ContentHeader, SupportButton, ItemCardGrid, ItemCardHeader, Progress, LogViewer, ErrorPage, HeaderLabel, Header, Page, HeaderTabs, MissingAnnotationEmptyState } from '@backstage/core-components';
|
|
6
|
+
import { Link, SubvalueCell, Table, EmptyState, Button, WarningPanel, CodeSnippet, PageWithHeader, Content, ContentHeader, SupportButton, ItemCardGrid, ItemCardHeader, Progress, LogViewer, ErrorPage, SidebarPinStateContext, HeaderLabel, Header, Page, HeaderTabs, MissingAnnotationEmptyState } from '@backstage/core-components';
|
|
7
7
|
import TextTruncate from 'react-text-truncate';
|
|
8
8
|
import { FilteredEntityLayout, FilterContainer, EntityListContainer } from '@backstage/plugin-catalog';
|
|
9
9
|
import { favoriteEntityIcon, favoriteEntityTooltip, EntityRefLinks, getEntityRelations, formatEntityRefTitle, useEntityListProvider, useStarredEntities, CATALOG_FILTER_EXISTS, EntityListProvider, UserListPicker, EntityOwnerPicker, EntityTagPicker, EntityRefLink, catalogApiRef, useOwnUser, isOwnerOf, useEntity } from '@backstage/plugin-catalog-react';
|
|
10
|
-
import
|
|
10
|
+
import useCopyToClipboard from 'react-use/lib/useCopyToClipboard';
|
|
11
11
|
import { capitalize } from 'lodash';
|
|
12
12
|
import { RELATION_OWNED_BY } from '@backstage/catalog-model';
|
|
13
13
|
import ShareIcon from '@material-ui/icons/Share';
|
|
@@ -22,8 +22,11 @@ import { SearchContextProvider, useSearch } from '@backstage/plugin-search';
|
|
|
22
22
|
import SearchIcon from '@material-ui/icons/Search';
|
|
23
23
|
import Autocomplete from '@material-ui/lab/Autocomplete';
|
|
24
24
|
import { useNavigate, useOutlet } from 'react-router';
|
|
25
|
+
import useDebounce from 'react-use/lib/useDebounce';
|
|
25
26
|
import { Alert } from '@material-ui/lab';
|
|
26
27
|
import Close from '@material-ui/icons/Close';
|
|
28
|
+
import useAsync from 'react-use/lib/useAsync';
|
|
29
|
+
import useAsyncRetry from 'react-use/lib/useAsyncRetry';
|
|
27
30
|
import CodeIcon from '@material-ui/icons/Code';
|
|
28
31
|
|
|
29
32
|
const techdocsStorageApiRef = createApiRef({
|
|
@@ -34,14 +37,10 @@ const techdocsApiRef = createApiRef({
|
|
|
34
37
|
});
|
|
35
38
|
|
|
36
39
|
class TechDocsClient {
|
|
37
|
-
constructor({
|
|
38
|
-
configApi
|
|
39
|
-
discoveryApi
|
|
40
|
-
|
|
41
|
-
}) {
|
|
42
|
-
this.configApi = configApi;
|
|
43
|
-
this.discoveryApi = discoveryApi;
|
|
44
|
-
this.identityApi = identityApi;
|
|
40
|
+
constructor(options) {
|
|
41
|
+
this.configApi = options.configApi;
|
|
42
|
+
this.discoveryApi = options.discoveryApi;
|
|
43
|
+
this.fetchApi = options.fetchApi;
|
|
45
44
|
}
|
|
46
45
|
async getApiOrigin() {
|
|
47
46
|
var _a;
|
|
@@ -51,10 +50,7 @@ class TechDocsClient {
|
|
|
51
50
|
const { kind, namespace, name } = entityId;
|
|
52
51
|
const apiOrigin = await this.getApiOrigin();
|
|
53
52
|
const requestUrl = `${apiOrigin}/metadata/techdocs/${namespace}/${kind}/${name}`;
|
|
54
|
-
const
|
|
55
|
-
const request = await fetch(`${requestUrl}`, {
|
|
56
|
-
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
57
|
-
});
|
|
53
|
+
const request = await this.fetchApi.fetch(`${requestUrl}`);
|
|
58
54
|
if (!request.ok) {
|
|
59
55
|
throw await ResponseError.fromResponse(request);
|
|
60
56
|
}
|
|
@@ -64,10 +60,7 @@ class TechDocsClient {
|
|
|
64
60
|
const { kind, namespace, name } = entityId;
|
|
65
61
|
const apiOrigin = await this.getApiOrigin();
|
|
66
62
|
const requestUrl = `${apiOrigin}/metadata/entity/${namespace}/${kind}/${name}`;
|
|
67
|
-
const
|
|
68
|
-
const request = await fetch(`${requestUrl}`, {
|
|
69
|
-
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
70
|
-
});
|
|
63
|
+
const request = await this.fetchApi.fetch(`${requestUrl}`);
|
|
71
64
|
if (!request.ok) {
|
|
72
65
|
throw await ResponseError.fromResponse(request);
|
|
73
66
|
}
|
|
@@ -75,14 +68,11 @@ class TechDocsClient {
|
|
|
75
68
|
}
|
|
76
69
|
}
|
|
77
70
|
class TechDocsStorageClient {
|
|
78
|
-
constructor({
|
|
79
|
-
configApi
|
|
80
|
-
discoveryApi
|
|
81
|
-
identityApi
|
|
82
|
-
|
|
83
|
-
this.configApi = configApi;
|
|
84
|
-
this.discoveryApi = discoveryApi;
|
|
85
|
-
this.identityApi = identityApi;
|
|
71
|
+
constructor(options) {
|
|
72
|
+
this.configApi = options.configApi;
|
|
73
|
+
this.discoveryApi = options.discoveryApi;
|
|
74
|
+
this.identityApi = options.identityApi;
|
|
75
|
+
this.fetchApi = options.fetchApi;
|
|
86
76
|
}
|
|
87
77
|
async getApiOrigin() {
|
|
88
78
|
var _a;
|
|
@@ -99,10 +89,7 @@ class TechDocsStorageClient {
|
|
|
99
89
|
const { kind, namespace, name } = entityId;
|
|
100
90
|
const storageUrl = await this.getStorageUrl();
|
|
101
91
|
const url = `${storageUrl}/${namespace}/${kind}/${name}/${path}`;
|
|
102
|
-
const
|
|
103
|
-
const request = await fetch(`${url.endsWith("/") ? url : `${url}/`}index.html`, {
|
|
104
|
-
headers: token ? { Authorization: `Bearer ${token}` } : {}
|
|
105
|
-
});
|
|
92
|
+
const request = await this.fetchApi.fetch(`${url.endsWith("/") ? url : `${url}/`}index.html`);
|
|
106
93
|
let errorMessage = "";
|
|
107
94
|
switch (request.status) {
|
|
108
95
|
case 404:
|
|
@@ -122,7 +109,7 @@ class TechDocsStorageClient {
|
|
|
122
109
|
const { kind, namespace, name } = entityId;
|
|
123
110
|
const apiOrigin = await this.getApiOrigin();
|
|
124
111
|
const url = `${apiOrigin}/sync/${namespace}/${kind}/${name}`;
|
|
125
|
-
const token = await this.identityApi.
|
|
112
|
+
const { token } = await this.identityApi.getCredentials();
|
|
126
113
|
return new Promise((resolve, reject) => {
|
|
127
114
|
const source = new EventSourcePolyfill(url, {
|
|
128
115
|
withCredentials: true,
|
|
@@ -492,12 +479,14 @@ const techdocsPlugin = createPlugin({
|
|
|
492
479
|
deps: {
|
|
493
480
|
configApi: configApiRef,
|
|
494
481
|
discoveryApi: discoveryApiRef,
|
|
495
|
-
identityApi: identityApiRef
|
|
482
|
+
identityApi: identityApiRef,
|
|
483
|
+
fetchApi: fetchApiRef
|
|
496
484
|
},
|
|
497
|
-
factory: ({ configApi, discoveryApi, identityApi }) => new TechDocsStorageClient({
|
|
485
|
+
factory: ({ configApi, discoveryApi, identityApi, fetchApi }) => new TechDocsStorageClient({
|
|
498
486
|
configApi,
|
|
499
487
|
discoveryApi,
|
|
500
|
-
identityApi
|
|
488
|
+
identityApi,
|
|
489
|
+
fetchApi
|
|
501
490
|
})
|
|
502
491
|
}),
|
|
503
492
|
createApiFactory({
|
|
@@ -505,12 +494,12 @@ const techdocsPlugin = createPlugin({
|
|
|
505
494
|
deps: {
|
|
506
495
|
configApi: configApiRef,
|
|
507
496
|
discoveryApi: discoveryApiRef,
|
|
508
|
-
|
|
497
|
+
fetchApi: fetchApiRef
|
|
509
498
|
},
|
|
510
|
-
factory: ({ configApi, discoveryApi,
|
|
499
|
+
factory: ({ configApi, discoveryApi, fetchApi }) => new TechDocsClient({
|
|
511
500
|
configApi,
|
|
512
501
|
discoveryApi,
|
|
513
|
-
|
|
502
|
+
fetchApi
|
|
514
503
|
})
|
|
515
504
|
})
|
|
516
505
|
],
|
|
@@ -1269,6 +1258,7 @@ const useTechDocsReaderDom = (entityRef) => {
|
|
|
1269
1258
|
const { state, path, content: rawPage } = useTechDocsReader();
|
|
1270
1259
|
const [sidebars, setSidebars] = useState();
|
|
1271
1260
|
const [dom, setDom] = useState(null);
|
|
1261
|
+
const { isPinned } = useContext(SidebarPinStateContext);
|
|
1272
1262
|
const updateSidebarPosition = useCallback(() => {
|
|
1273
1263
|
if (!dom || !sidebars)
|
|
1274
1264
|
return;
|
|
@@ -1287,6 +1277,21 @@ const useTechDocsReaderDom = (entityRef) => {
|
|
|
1287
1277
|
window.removeEventListener("resize", updateSidebarPosition);
|
|
1288
1278
|
};
|
|
1289
1279
|
}, [updateSidebarPosition, state]);
|
|
1280
|
+
const updateFooterWidth = useCallback(() => {
|
|
1281
|
+
if (!dom)
|
|
1282
|
+
return;
|
|
1283
|
+
const footer = dom.querySelector(".md-footer");
|
|
1284
|
+
if (footer) {
|
|
1285
|
+
footer.style.width = `${dom.getBoundingClientRect().width}px`;
|
|
1286
|
+
}
|
|
1287
|
+
}, [dom]);
|
|
1288
|
+
useEffect(() => {
|
|
1289
|
+
updateFooterWidth();
|
|
1290
|
+
window.addEventListener("resize", updateFooterWidth);
|
|
1291
|
+
return () => {
|
|
1292
|
+
window.removeEventListener("resize", updateFooterWidth);
|
|
1293
|
+
};
|
|
1294
|
+
});
|
|
1290
1295
|
const preRender = useCallback((rawContent, contentPath) => transform(rawContent, [
|
|
1291
1296
|
sanitizeDOM(techdocsSanitizer.getOptionalConfig("techdocs.sanitizer")),
|
|
1292
1297
|
addBaseUrl({
|
|
@@ -1316,13 +1321,20 @@ const useTechDocsReaderDom = (entityRef) => {
|
|
|
1316
1321
|
.md-sidebar { position: fixed; bottom: 100px; width: 20rem; }
|
|
1317
1322
|
.md-sidebar--secondary { right: 2rem; }
|
|
1318
1323
|
.md-content { margin-bottom: 50px }
|
|
1319
|
-
.md-footer { position: fixed; bottom: 0px;
|
|
1324
|
+
.md-footer { position: fixed; bottom: 0px; }
|
|
1320
1325
|
.md-footer-nav__link { width: 20rem;}
|
|
1321
1326
|
.md-content { margin-left: 20rem; max-width: calc(100% - 20rem * 2 - 3rem); }
|
|
1322
1327
|
.md-typeset { font-size: 1rem; }
|
|
1323
1328
|
.md-typeset h1, .md-typeset h2, .md-typeset h3 { font-weight: bold; }
|
|
1324
1329
|
.md-nav { font-size: 1rem; }
|
|
1325
1330
|
.md-grid { max-width: 90vw; margin: 0 }
|
|
1331
|
+
.md-typeset blockquote {
|
|
1332
|
+
color: ${theme.palette.textSubtle};
|
|
1333
|
+
border-left: 0.2rem solid ${theme.palette.textVerySubtle};
|
|
1334
|
+
}
|
|
1335
|
+
.md-typeset hr {
|
|
1336
|
+
border-bottom: 0.05rem dotted ${theme.palette.textVerySubtle};
|
|
1337
|
+
}
|
|
1326
1338
|
.md-typeset table:not([class]) {
|
|
1327
1339
|
font-size: 1rem;
|
|
1328
1340
|
border: 1px solid ${theme.palette.text.primary};
|
|
@@ -1352,13 +1364,16 @@ const useTechDocsReaderDom = (entityRef) => {
|
|
|
1352
1364
|
transition: none !important
|
|
1353
1365
|
}
|
|
1354
1366
|
.md-sidebar--secondary { display: none; }
|
|
1355
|
-
.md-sidebar--primary { left: 72px; width: 10rem }
|
|
1367
|
+
.md-sidebar--primary { left: ${isPinned ? "242px" : "72px"}; width: 10rem }
|
|
1356
1368
|
.md-content { margin-left: 10rem; max-width: calc(100% - 10rem); }
|
|
1357
1369
|
.md-content__inner { font-size: 0.9rem }
|
|
1358
1370
|
.md-footer {
|
|
1359
1371
|
position: static;
|
|
1360
|
-
|
|
1361
|
-
|
|
1372
|
+
padding-left: 10rem;
|
|
1373
|
+
}
|
|
1374
|
+
.md-footer-nav__link {
|
|
1375
|
+
/* footer links begin to overlap at small sizes without setting width */
|
|
1376
|
+
width: 50%;
|
|
1362
1377
|
}
|
|
1363
1378
|
.md-nav--primary .md-nav__title {
|
|
1364
1379
|
white-space: normal;
|
|
@@ -1430,21 +1445,33 @@ const useTechDocsReaderDom = (entityRef) => {
|
|
|
1430
1445
|
theme.palette.primary.main,
|
|
1431
1446
|
theme.palette.success.main,
|
|
1432
1447
|
theme.palette.text.primary,
|
|
1433
|
-
theme.
|
|
1448
|
+
theme.palette.textSubtle,
|
|
1449
|
+
theme.palette.textVerySubtle,
|
|
1450
|
+
theme.typography.fontFamily,
|
|
1451
|
+
isPinned
|
|
1434
1452
|
]);
|
|
1435
1453
|
const postRender = useCallback(async (transformedElement) => transform(transformedElement, [
|
|
1436
1454
|
scrollIntoAnchor(),
|
|
1437
1455
|
addLinkClickListener({
|
|
1438
1456
|
baseUrl: window.location.origin,
|
|
1439
|
-
onClick: (
|
|
1457
|
+
onClick: (event, url) => {
|
|
1440
1458
|
var _a, _b;
|
|
1459
|
+
const modifierActive = event.ctrlKey || event.metaKey;
|
|
1441
1460
|
const parsedUrl = new URL(url);
|
|
1442
1461
|
if (parsedUrl.hash) {
|
|
1443
|
-
|
|
1444
|
-
|
|
1462
|
+
if (modifierActive) {
|
|
1463
|
+
window.open(`${parsedUrl.pathname}${parsedUrl.hash}`, "_blank");
|
|
1464
|
+
} else {
|
|
1465
|
+
navigate(`${parsedUrl.pathname}${parsedUrl.hash}`);
|
|
1466
|
+
(_a = transformedElement == null ? void 0 : transformedElement.querySelector(`#${parsedUrl.hash.slice(1)}`)) == null ? void 0 : _a.scrollIntoView();
|
|
1467
|
+
}
|
|
1445
1468
|
} else {
|
|
1446
|
-
|
|
1447
|
-
|
|
1469
|
+
if (modifierActive) {
|
|
1470
|
+
window.open(parsedUrl.pathname, "_blank");
|
|
1471
|
+
} else {
|
|
1472
|
+
navigate(parsedUrl.pathname);
|
|
1473
|
+
(_b = transformedElement == null ? void 0 : transformedElement.querySelector(".md-content__inner")) == null ? void 0 : _b.scrollIntoView();
|
|
1474
|
+
}
|
|
1448
1475
|
}
|
|
1449
1476
|
}
|
|
1450
1477
|
}),
|