@backstage/plugin-techdocs 1.10.8-next.3 → 1.10.9-next.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 +53 -0
- package/alpha/package.json +1 -1
- package/dist/alpha.d.ts +151 -13
- package/dist/alpha.esm.js +82 -65
- package/dist/alpha.esm.js.map +1 -1
- package/dist/reader/components/TechDocsReaderPageContent/dom.esm.js +1 -1
- package/dist/reader/components/TechDocsReaderPageContent/dom.esm.js.map +1 -1
- package/dist/reader/components/TechDocsRedirectNotification/TechDocsRedirectNotification.esm.js +46 -0
- package/dist/reader/components/TechDocsRedirectNotification/TechDocsRedirectNotification.esm.js.map +1 -0
- package/dist/reader/transformers/handleMetaRedirects.esm.js +9 -45
- package/dist/reader/transformers/handleMetaRedirects.esm.js.map +1 -1
- package/package.json +18 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,58 @@
|
|
|
1
1
|
# @backstage/plugin-techdocs
|
|
2
2
|
|
|
3
|
+
## 1.10.9-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- fec8b57: Updated exports to use the new type parameters for extensions and extension blueprints.
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @backstage/frontend-plugin-api@0.8.0-next.0
|
|
10
|
+
- @backstage/plugin-techdocs-react@1.2.8-next.0
|
|
11
|
+
- @backstage/core-compat-api@0.2.9-next.0
|
|
12
|
+
- @backstage/plugin-catalog-react@1.12.4-next.0
|
|
13
|
+
- @backstage/plugin-search-react@1.8.0-next.0
|
|
14
|
+
- @backstage/catalog-model@1.6.0
|
|
15
|
+
- @backstage/config@1.2.0
|
|
16
|
+
- @backstage/core-components@0.14.10
|
|
17
|
+
- @backstage/core-plugin-api@1.9.3
|
|
18
|
+
- @backstage/errors@1.2.4
|
|
19
|
+
- @backstage/integration@1.14.0
|
|
20
|
+
- @backstage/integration-react@1.1.30
|
|
21
|
+
- @backstage/theme@0.5.6
|
|
22
|
+
- @backstage/plugin-auth-react@0.1.5
|
|
23
|
+
- @backstage/plugin-search-common@1.2.14
|
|
24
|
+
- @backstage/plugin-techdocs-common@0.1.0
|
|
25
|
+
|
|
26
|
+
## 1.10.8
|
|
27
|
+
|
|
28
|
+
### Patch Changes
|
|
29
|
+
|
|
30
|
+
- 69bd940: Use annotation constants from new techdocs-common package.
|
|
31
|
+
- c7603e8: Deprecate the old pattern of `create*Extension`, and replace it with the equivalent Blueprint implementation instead
|
|
32
|
+
- 27794d1: Allow for more granular control of TechDocsReaderPage styling. Theme overrides can now be provided to TechDocs without affecting the theme in other areas of Backstage.
|
|
33
|
+
- 4490d73: Refactor TechDocs' mkdocs-redirects support.
|
|
34
|
+
- 8543e72: TechDocs redirect feature now includes a notification to the user before they are redirected.
|
|
35
|
+
- 67e76f2: TechDocs now supports the `mkdocs-redirects` plugin. Redirects defined using the `mkdocs-redirect` plugin will be handled automatically in TechDocs. Redirecting to external urls is not supported. In the case that an external redirect url is provided, TechDocs will redirect to the current documentation site home.
|
|
36
|
+
- bdc5471: Fixed issue where header styles were incorrectly generated when themes used CSS variables to define font size.
|
|
37
|
+
- 6349099: Added config input type to the extensions
|
|
38
|
+
- Updated dependencies
|
|
39
|
+
- @backstage/frontend-plugin-api@0.7.0
|
|
40
|
+
- @backstage/plugin-catalog-react@1.12.3
|
|
41
|
+
- @backstage/plugin-search-react@1.7.14
|
|
42
|
+
- @backstage/core-components@0.14.10
|
|
43
|
+
- @backstage/core-compat-api@0.2.8
|
|
44
|
+
- @backstage/plugin-search-common@1.2.14
|
|
45
|
+
- @backstage/integration@1.14.0
|
|
46
|
+
- @backstage/plugin-techdocs-common@0.1.0
|
|
47
|
+
- @backstage/plugin-auth-react@0.1.5
|
|
48
|
+
- @backstage/catalog-model@1.6.0
|
|
49
|
+
- @backstage/config@1.2.0
|
|
50
|
+
- @backstage/core-plugin-api@1.9.3
|
|
51
|
+
- @backstage/errors@1.2.4
|
|
52
|
+
- @backstage/integration-react@1.1.30
|
|
53
|
+
- @backstage/theme@0.5.6
|
|
54
|
+
- @backstage/plugin-techdocs-react@1.2.7
|
|
55
|
+
|
|
3
56
|
## 1.10.8-next.3
|
|
4
57
|
|
|
5
58
|
### Patch Changes
|
package/alpha/package.json
CHANGED
package/dist/alpha.d.ts
CHANGED
|
@@ -1,19 +1,41 @@
|
|
|
1
|
+
import * as _backstage_catalog_model from '@backstage/catalog-model';
|
|
2
|
+
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
1
3
|
import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
|
|
4
|
+
import * as _backstage_plugin_search_react_alpha from '@backstage/plugin-search-react/alpha';
|
|
5
|
+
import React__default from 'react';
|
|
2
6
|
|
|
3
7
|
/** @alpha */
|
|
4
8
|
declare const techDocsSearchResultListItemExtension: _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
9
|
+
config: {
|
|
10
|
+
title: string | undefined;
|
|
11
|
+
lineClamp: number;
|
|
12
|
+
asLink: boolean;
|
|
13
|
+
asListItem: boolean;
|
|
14
|
+
} & {
|
|
15
|
+
noTrack: boolean;
|
|
16
|
+
};
|
|
17
|
+
configInput: {
|
|
18
|
+
title?: string | undefined;
|
|
19
|
+
lineClamp?: number | undefined;
|
|
20
|
+
asListItem?: boolean | undefined;
|
|
21
|
+
asLink?: boolean | undefined;
|
|
22
|
+
} & {
|
|
23
|
+
noTrack?: boolean | undefined;
|
|
24
|
+
};
|
|
25
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
|
|
26
|
+
predicate?: _backstage_plugin_search_react_alpha.SearchResultItemExtensionPredicate | undefined;
|
|
27
|
+
component: _backstage_plugin_search_react_alpha.SearchResultItemExtensionComponent;
|
|
28
|
+
}, "search.search-result-list-item.item", {}>;
|
|
29
|
+
inputs: {
|
|
30
|
+
[x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.AnyExtensionDataRef, {
|
|
31
|
+
optional: boolean;
|
|
32
|
+
singleton: boolean;
|
|
33
|
+
}>;
|
|
34
|
+
};
|
|
35
|
+
kind: "search-result-list-item";
|
|
36
|
+
namespace: undefined;
|
|
37
|
+
name: undefined;
|
|
38
|
+
}>;
|
|
17
39
|
/** @alpha */
|
|
18
40
|
declare const _default: _backstage_frontend_plugin_api.BackstagePlugin<{
|
|
19
41
|
root: _backstage_frontend_plugin_api.RouteRef<undefined>;
|
|
@@ -23,6 +45,122 @@ declare const _default: _backstage_frontend_plugin_api.BackstagePlugin<{
|
|
|
23
45
|
namespace: string;
|
|
24
46
|
}>;
|
|
25
47
|
entityContent: _backstage_frontend_plugin_api.RouteRef<undefined>;
|
|
26
|
-
}, {}, {
|
|
48
|
+
}, {}, {
|
|
49
|
+
"api:techdocs": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
50
|
+
kind: "api";
|
|
51
|
+
namespace: undefined;
|
|
52
|
+
name: undefined;
|
|
53
|
+
config: {};
|
|
54
|
+
configInput: {};
|
|
55
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
56
|
+
inputs: {};
|
|
57
|
+
}>;
|
|
58
|
+
"page:techdocs": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
59
|
+
kind: "page";
|
|
60
|
+
namespace: undefined;
|
|
61
|
+
name: undefined;
|
|
62
|
+
config: {
|
|
63
|
+
path: string | undefined;
|
|
64
|
+
};
|
|
65
|
+
configInput: {
|
|
66
|
+
path?: string | undefined;
|
|
67
|
+
};
|
|
68
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React__default.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
69
|
+
optional: true;
|
|
70
|
+
}>;
|
|
71
|
+
inputs: {};
|
|
72
|
+
}>;
|
|
73
|
+
"nav-item:techdocs": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
74
|
+
kind: "nav-item";
|
|
75
|
+
namespace: undefined;
|
|
76
|
+
name: undefined;
|
|
77
|
+
config: {};
|
|
78
|
+
configInput: {};
|
|
79
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
|
|
80
|
+
title: string;
|
|
81
|
+
icon: _backstage_core_plugin_api.IconComponent;
|
|
82
|
+
routeRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
|
|
83
|
+
}, "core.nav-item.target", {}>;
|
|
84
|
+
inputs: {};
|
|
85
|
+
}>;
|
|
86
|
+
"api:techdocs/storage": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
87
|
+
kind: "api";
|
|
88
|
+
namespace: undefined;
|
|
89
|
+
name: "storage";
|
|
90
|
+
config: {};
|
|
91
|
+
configInput: {};
|
|
92
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
93
|
+
inputs: {};
|
|
94
|
+
}>;
|
|
95
|
+
"search-result-list-item:techdocs": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
96
|
+
config: {
|
|
97
|
+
title: string | undefined;
|
|
98
|
+
lineClamp: number;
|
|
99
|
+
asLink: boolean;
|
|
100
|
+
asListItem: boolean;
|
|
101
|
+
} & {
|
|
102
|
+
noTrack: boolean;
|
|
103
|
+
};
|
|
104
|
+
configInput: {
|
|
105
|
+
title?: string | undefined;
|
|
106
|
+
lineClamp?: number | undefined;
|
|
107
|
+
asListItem?: boolean | undefined;
|
|
108
|
+
asLink?: boolean | undefined;
|
|
109
|
+
} & {
|
|
110
|
+
noTrack?: boolean | undefined;
|
|
111
|
+
};
|
|
112
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<{
|
|
113
|
+
predicate?: _backstage_plugin_search_react_alpha.SearchResultItemExtensionPredicate | undefined;
|
|
114
|
+
component: _backstage_plugin_search_react_alpha.SearchResultItemExtensionComponent;
|
|
115
|
+
}, "search.search-result-list-item.item", {}>;
|
|
116
|
+
inputs: {
|
|
117
|
+
[x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.AnyExtensionDataRef, {
|
|
118
|
+
optional: boolean;
|
|
119
|
+
singleton: boolean;
|
|
120
|
+
}>;
|
|
121
|
+
};
|
|
122
|
+
kind: "search-result-list-item";
|
|
123
|
+
namespace: undefined;
|
|
124
|
+
name: undefined;
|
|
125
|
+
}>;
|
|
126
|
+
"page:techdocs/reader": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
127
|
+
kind: "page";
|
|
128
|
+
namespace: undefined;
|
|
129
|
+
name: "reader";
|
|
130
|
+
config: {
|
|
131
|
+
path: string | undefined;
|
|
132
|
+
};
|
|
133
|
+
configInput: {
|
|
134
|
+
path?: string | undefined;
|
|
135
|
+
};
|
|
136
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React__default.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
137
|
+
optional: true;
|
|
138
|
+
}>;
|
|
139
|
+
inputs: {};
|
|
140
|
+
}>;
|
|
141
|
+
"entity-content:techdocs": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
142
|
+
kind: "entity-content";
|
|
143
|
+
namespace: undefined;
|
|
144
|
+
name: undefined;
|
|
145
|
+
config: {
|
|
146
|
+
path: string | undefined;
|
|
147
|
+
title: string | undefined;
|
|
148
|
+
filter: string | undefined;
|
|
149
|
+
};
|
|
150
|
+
configInput: {
|
|
151
|
+
filter?: string | undefined;
|
|
152
|
+
title?: string | undefined;
|
|
153
|
+
path?: string | undefined;
|
|
154
|
+
};
|
|
155
|
+
output: _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<React__default.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
156
|
+
optional: true;
|
|
157
|
+
}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-content-title", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
158
|
+
optional: true;
|
|
159
|
+
}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "catalog.entity-filter-expression", {
|
|
160
|
+
optional: true;
|
|
161
|
+
}>;
|
|
162
|
+
inputs: {};
|
|
163
|
+
}>;
|
|
164
|
+
}>;
|
|
27
165
|
|
|
28
166
|
export { _default as default, techDocsSearchResultListItemExtension };
|
package/dist/alpha.esm.js
CHANGED
|
@@ -1,87 +1,104 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import LibraryBooks from '@material-ui/icons/LibraryBooks';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { ApiBlueprint, PageBlueprint, NavItemBlueprint, createFrontendPlugin } from '@backstage/frontend-plugin-api';
|
|
4
|
+
import { SearchResultListItemBlueprint } from '@backstage/plugin-search-react/alpha';
|
|
5
5
|
import { createApiFactory, configApiRef, discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';
|
|
6
6
|
import { compatWrapper, convertLegacyRouteRef, convertLegacyRouteRefs } from '@backstage/core-compat-api';
|
|
7
7
|
import { techdocsStorageApiRef, techdocsApiRef } from '@backstage/plugin-techdocs-react';
|
|
8
8
|
import { TechDocsStorageClient, TechDocsClient } from './client.esm.js';
|
|
9
9
|
import { rootRouteRef, rootDocsRouteRef, rootCatalogDocsRouteRef } from './routes.esm.js';
|
|
10
|
-
import {
|
|
10
|
+
import { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';
|
|
11
11
|
|
|
12
|
-
const techDocsStorageApi =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
discoveryApi,
|
|
23
|
-
|
|
12
|
+
const techDocsStorageApi = ApiBlueprint.make({
|
|
13
|
+
name: "storage",
|
|
14
|
+
params: {
|
|
15
|
+
factory: createApiFactory({
|
|
16
|
+
api: techdocsStorageApiRef,
|
|
17
|
+
deps: {
|
|
18
|
+
configApi: configApiRef,
|
|
19
|
+
discoveryApi: discoveryApiRef,
|
|
20
|
+
fetchApi: fetchApiRef
|
|
21
|
+
},
|
|
22
|
+
factory: ({ configApi, discoveryApi, fetchApi }) => new TechDocsStorageClient({
|
|
23
|
+
configApi,
|
|
24
|
+
discoveryApi,
|
|
25
|
+
fetchApi
|
|
26
|
+
})
|
|
24
27
|
})
|
|
25
|
-
}
|
|
28
|
+
}
|
|
26
29
|
});
|
|
27
|
-
const techDocsClientApi =
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
configApi,
|
|
37
|
-
|
|
38
|
-
|
|
30
|
+
const techDocsClientApi = ApiBlueprint.make({
|
|
31
|
+
params: {
|
|
32
|
+
factory: createApiFactory({
|
|
33
|
+
api: techdocsApiRef,
|
|
34
|
+
deps: {
|
|
35
|
+
configApi: configApiRef,
|
|
36
|
+
discoveryApi: discoveryApiRef,
|
|
37
|
+
fetchApi: fetchApiRef
|
|
38
|
+
},
|
|
39
|
+
factory: ({ configApi, discoveryApi, fetchApi }) => new TechDocsClient({
|
|
40
|
+
configApi,
|
|
41
|
+
discoveryApi,
|
|
42
|
+
fetchApi
|
|
43
|
+
})
|
|
39
44
|
})
|
|
40
|
-
}
|
|
45
|
+
}
|
|
41
46
|
});
|
|
42
|
-
const techDocsSearchResultListItemExtension =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
47
|
+
const techDocsSearchResultListItemExtension = SearchResultListItemBlueprint.makeWithOverrides({
|
|
48
|
+
config: {
|
|
49
|
+
schema: {
|
|
50
|
+
title: (z) => z.string().optional(),
|
|
51
|
+
lineClamp: (z) => z.number().default(5),
|
|
52
|
+
asLink: (z) => z.boolean().default(true),
|
|
53
|
+
asListItem: (z) => z.boolean().default(true)
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
factory(originalFactory, { config }) {
|
|
57
|
+
return originalFactory({
|
|
58
|
+
predicate: (result) => result.type === "techdocs",
|
|
59
|
+
component: async () => {
|
|
60
|
+
const { TechDocsSearchResultListItem } = await import('./search/components/TechDocsSearchResultListItem.esm.js');
|
|
61
|
+
return (props) => compatWrapper(
|
|
62
|
+
/* @__PURE__ */ React.createElement(TechDocsSearchResultListItem, { ...props, ...config })
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
57
66
|
}
|
|
58
67
|
});
|
|
59
|
-
const techDocsPage =
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
(
|
|
64
|
-
|
|
68
|
+
const techDocsPage = PageBlueprint.make({
|
|
69
|
+
params: {
|
|
70
|
+
defaultPath: "/docs",
|
|
71
|
+
routeRef: convertLegacyRouteRef(rootRouteRef),
|
|
72
|
+
loader: () => import('./home/components/TechDocsIndexPage.esm.js').then(
|
|
73
|
+
(m) => compatWrapper(/* @__PURE__ */ React.createElement(m.TechDocsIndexPage, null))
|
|
74
|
+
)
|
|
75
|
+
}
|
|
65
76
|
});
|
|
66
|
-
const techDocsReaderPage =
|
|
77
|
+
const techDocsReaderPage = PageBlueprint.make({
|
|
67
78
|
name: "reader",
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
(
|
|
72
|
-
|
|
79
|
+
params: {
|
|
80
|
+
defaultPath: "/docs/:namespace/:kind/:name",
|
|
81
|
+
routeRef: convertLegacyRouteRef(rootDocsRouteRef),
|
|
82
|
+
loader: () => import('./reader/components/TechDocsReaderPage/index.esm.js').then(
|
|
83
|
+
(m) => compatWrapper(/* @__PURE__ */ React.createElement(m.TechDocsReaderPage, null))
|
|
84
|
+
)
|
|
85
|
+
}
|
|
73
86
|
});
|
|
74
|
-
const techDocsEntityContent =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
const techDocsEntityContent = EntityContentBlueprint.make({
|
|
88
|
+
params: {
|
|
89
|
+
defaultPath: "docs",
|
|
90
|
+
defaultTitle: "TechDocs",
|
|
91
|
+
loader: () => import('./Router.esm.js').then((m) => compatWrapper(/* @__PURE__ */ React.createElement(m.EmbeddedDocsRouter, null)))
|
|
92
|
+
}
|
|
78
93
|
});
|
|
79
|
-
const techDocsNavItem =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
const techDocsNavItem = NavItemBlueprint.make({
|
|
95
|
+
params: {
|
|
96
|
+
icon: LibraryBooks,
|
|
97
|
+
title: "Docs",
|
|
98
|
+
routeRef: convertLegacyRouteRef(rootRouteRef)
|
|
99
|
+
}
|
|
83
100
|
});
|
|
84
|
-
var alpha =
|
|
101
|
+
var alpha = createFrontendPlugin({
|
|
85
102
|
id: "techdocs",
|
|
86
103
|
extensions: [
|
|
87
104
|
techDocsClientApi,
|
package/dist/alpha.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport LibraryBooks from '@material-ui/icons/LibraryBooks';\nimport {\n
|
|
1
|
+
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport LibraryBooks from '@material-ui/icons/LibraryBooks';\nimport {\n createFrontendPlugin,\n ApiBlueprint,\n PageBlueprint,\n NavItemBlueprint,\n} from '@backstage/frontend-plugin-api';\nimport { SearchResultListItemBlueprint } from '@backstage/plugin-search-react/alpha';\nimport {\n configApiRef,\n createApiFactory,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n compatWrapper,\n convertLegacyRouteRef,\n convertLegacyRouteRefs,\n} from '@backstage/core-compat-api';\nimport {\n techdocsApiRef,\n techdocsStorageApiRef,\n} from '@backstage/plugin-techdocs-react';\nimport { TechDocsClient, TechDocsStorageClient } from './client';\nimport {\n rootCatalogDocsRouteRef,\n rootDocsRouteRef,\n rootRouteRef,\n} from './routes';\nimport { EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';\n\n/** @alpha */\nconst techDocsStorageApi = ApiBlueprint.make({\n name: 'storage',\n params: {\n factory: createApiFactory({\n api: techdocsStorageApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n new TechDocsStorageClient({\n configApi,\n discoveryApi,\n fetchApi,\n }),\n }),\n },\n});\n\n/** @alpha */\nconst techDocsClientApi = ApiBlueprint.make({\n params: {\n factory: createApiFactory({\n api: techdocsApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n new TechDocsClient({\n configApi,\n discoveryApi,\n fetchApi,\n }),\n }),\n },\n});\n\n/** @alpha */\nexport const techDocsSearchResultListItemExtension =\n SearchResultListItemBlueprint.makeWithOverrides({\n config: {\n schema: {\n title: z => z.string().optional(),\n lineClamp: z => z.number().default(5),\n asLink: z => z.boolean().default(true),\n asListItem: z => z.boolean().default(true),\n },\n },\n factory(originalFactory, { config }) {\n return originalFactory({\n predicate: result => result.type === 'techdocs',\n component: async () => {\n const { TechDocsSearchResultListItem } = await import(\n './search/components/TechDocsSearchResultListItem'\n );\n return props =>\n compatWrapper(\n <TechDocsSearchResultListItem {...props} {...config} />,\n );\n },\n });\n },\n });\n\n/**\n * Responsible for rendering the provided router element\n *\n * @alpha\n */\nconst techDocsPage = PageBlueprint.make({\n params: {\n defaultPath: '/docs',\n routeRef: convertLegacyRouteRef(rootRouteRef),\n loader: () =>\n import('./home/components/TechDocsIndexPage').then(m =>\n compatWrapper(<m.TechDocsIndexPage />),\n ),\n },\n});\n\n/**\n * Component responsible for composing a TechDocs reader page experience\n *\n * @alpha\n */\nconst techDocsReaderPage = PageBlueprint.make({\n name: 'reader',\n params: {\n defaultPath: '/docs/:namespace/:kind/:name',\n routeRef: convertLegacyRouteRef(rootDocsRouteRef),\n loader: () =>\n import('./reader/components/TechDocsReaderPage').then(m =>\n compatWrapper(<m.TechDocsReaderPage />),\n ),\n },\n});\n\n/**\n * Component responsible for rendering techdocs on entity pages\n *\n * @alpha\n */\nconst techDocsEntityContent = EntityContentBlueprint.make({\n params: {\n defaultPath: 'docs',\n defaultTitle: 'TechDocs',\n loader: () =>\n import('./Router').then(m => compatWrapper(<m.EmbeddedDocsRouter />)),\n },\n});\n\n/** @alpha */\nconst techDocsNavItem = NavItemBlueprint.make({\n params: {\n icon: LibraryBooks,\n title: 'Docs',\n routeRef: convertLegacyRouteRef(rootRouteRef),\n },\n});\n\n/** @alpha */\nexport default createFrontendPlugin({\n id: 'techdocs',\n extensions: [\n techDocsClientApi,\n techDocsStorageApi,\n techDocsNavItem,\n techDocsPage,\n techDocsReaderPage,\n techDocsEntityContent,\n techDocsSearchResultListItemExtension,\n ],\n routes: convertLegacyRouteRefs({\n root: rootRouteRef,\n docRoot: rootDocsRouteRef,\n entityContent: rootCatalogDocsRouteRef,\n }),\n});\n"],"names":[],"mappings":"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"}
|
|
@@ -18,8 +18,8 @@ import { simplifyMkdocsFooter } from '../../transformers/simplifyMkdocsFooter.es
|
|
|
18
18
|
import { onCssReady } from '../../transformers/onCssReady.esm.js';
|
|
19
19
|
import { scrollIntoNavigation } from '../../transformers/scrollIntoNavigation.esm.js';
|
|
20
20
|
import { transform } from '../../transformers/transformer.esm.js';
|
|
21
|
-
import { useNavigateUrl } from './useNavigateUrl.esm.js';
|
|
22
21
|
import { handleMetaRedirects } from '../../transformers/handleMetaRedirects.esm.js';
|
|
22
|
+
import { useNavigateUrl } from './useNavigateUrl.esm.js';
|
|
23
23
|
|
|
24
24
|
const MOBILE_MEDIA_QUERY = "screen and (max-width: 76.1875em)";
|
|
25
25
|
const useTechDocsReaderDom = (entityRef) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dom.esm.js","sources":["../../../../src/reader/components/TechDocsReaderPageContent/dom.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useEffect, useState } from 'react';\n\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { useTheme } from '@material-ui/core/styles';\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport { scmIntegrationsApiRef } from '@backstage/integration-react';\n\nimport {\n techdocsStorageApiRef,\n useShadowDomStylesLoading,\n} from '@backstage/plugin-techdocs-react';\n\nimport { useTechDocsReader } from '../TechDocsReaderProvider';\n\nimport {\n addBaseUrl,\n addGitFeedbackLink,\n addLinkClickListener,\n addSidebarToggle,\n onCssReady,\n removeMkdocsHeader,\n rewriteDocLinks,\n simplifyMkdocsFooter,\n scrollIntoNavigation,\n transform as transformer,\n copyToClipboard,\n useSanitizerTransformer,\n useStylesTransformer,\n} from '../../transformers';\nimport { useNavigateUrl } from './useNavigateUrl';\nimport { handleMetaRedirects } from '../../transformers/handleMetaRedirects';\n\nconst MOBILE_MEDIA_QUERY = 'screen and (max-width: 76.1875em)';\n\n/**\n * Hook that encapsulates the behavior of getting raw HTML and applying\n * transforms to it in order to make it function at a basic level in the\n * Backstage UI.\n */\nexport const useTechDocsReaderDom = (\n entityRef: CompoundEntityRef,\n): Element | null => {\n const navigate = useNavigateUrl();\n const theme = useTheme();\n const isMobileMedia = useMediaQuery(MOBILE_MEDIA_QUERY);\n const sanitizerTransformer = useSanitizerTransformer();\n const stylesTransformer = useStylesTransformer();\n const analytics = useAnalytics();\n\n const techdocsStorageApi = useApi(techdocsStorageApiRef);\n const scmIntegrationsApi = useApi(scmIntegrationsApiRef);\n\n const { state, path, content: rawPage } = useTechDocsReader();\n\n const [dom, setDom] = useState<HTMLElement | null>(null);\n const isStyleLoading = useShadowDomStylesLoading(dom);\n\n const updateSidebarPositionAndHeight = useCallback(() => {\n if (!dom) return;\n\n const sidebars = dom.querySelectorAll<HTMLElement>('.md-sidebar');\n\n sidebars.forEach(element => {\n // set sidebar position to render in correct position\n if (isMobileMedia) {\n element.style.top = '0px';\n } else {\n const page = document?.querySelector('.techdocs-reader-page');\n const pageTop = page?.getBoundingClientRect().top ?? 0;\n let domTop = dom.getBoundingClientRect().top ?? 0;\n\n const tabs = dom.querySelector('.md-container > .md-tabs');\n const tabsHeight = tabs?.getBoundingClientRect().height ?? 0;\n\n // the sidebars should not scroll beyond the total height of the header and tabs\n if (domTop < pageTop) {\n domTop = pageTop;\n }\n\n const scrollbarTopPx = Math.max(domTop, 0) + tabsHeight;\n\n element.style.top = `${scrollbarTopPx}px`;\n\n // set scrollbar height to ensure all links can be seen when content is small\n const footer = dom.querySelector('.md-container > .md-footer');\n // if no footer, fallback to using the bottom of the window\n const scrollbarEndPx =\n footer?.getBoundingClientRect().top ?? window.innerHeight;\n\n element.style.height = `${scrollbarEndPx - scrollbarTopPx}px`;\n }\n\n // show the sidebar only after updating its position\n element.style.setProperty('opacity', '1');\n });\n }, [dom, isMobileMedia]);\n\n useEffect(() => {\n window.addEventListener('resize', updateSidebarPositionAndHeight);\n window.addEventListener('scroll', updateSidebarPositionAndHeight, true);\n return () => {\n window.removeEventListener('resize', updateSidebarPositionAndHeight);\n window.removeEventListener(\n 'scroll',\n updateSidebarPositionAndHeight,\n true,\n );\n };\n }, [dom, updateSidebarPositionAndHeight]);\n\n // dynamically set width of footer to accommodate for pinning of the sidebar\n const updateFooterWidth = useCallback(() => {\n if (!dom) return;\n const footer = dom.querySelector<HTMLElement>('.md-footer');\n if (footer) {\n footer.style.width = `${dom.getBoundingClientRect().width}px`;\n }\n }, [dom]);\n\n useEffect(() => {\n window.addEventListener('resize', updateFooterWidth);\n return () => {\n window.removeEventListener('resize', updateFooterWidth);\n };\n }, [dom, updateFooterWidth]);\n\n // an update to \"state\" might lead to an updated UI so we include it as a trigger\n useEffect(() => {\n if (!isStyleLoading) {\n updateFooterWidth();\n updateSidebarPositionAndHeight();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n state,\n isStyleLoading,\n updateFooterWidth,\n updateSidebarPositionAndHeight,\n ]);\n\n // a function that performs transformations that are executed prior to adding it to the DOM\n const preRender = useCallback(\n (rawContent: string, contentPath: string) =>\n transformer(rawContent, [\n sanitizerTransformer,\n addBaseUrl({\n techdocsStorageApi,\n entityId: entityRef,\n path: contentPath,\n }),\n rewriteDocLinks(),\n addSidebarToggle(),\n removeMkdocsHeader(),\n simplifyMkdocsFooter(),\n addGitFeedbackLink(scmIntegrationsApi),\n stylesTransformer,\n ]),\n [\n // only add dependencies that are in state or memorized variables to avoid unnecessary calls between re-renders\n entityRef,\n scmIntegrationsApi,\n techdocsStorageApi,\n sanitizerTransformer,\n stylesTransformer,\n ],\n );\n\n // a function that performs transformations that are executed after adding it to the DOM\n const postRender = useCallback(\n async (transformedElement: Element) =>\n transformer(transformedElement, [\n handleMetaRedirects(navigate, entityRef.name),\n scrollIntoNavigation(),\n copyToClipboard(theme),\n addLinkClickListener({\n baseUrl: window.location.origin,\n onClick: (event: MouseEvent, url: string) => {\n // detect if CTRL or META keys are pressed so that links can be opened in a new tab with `window.open`\n const modifierActive = event.ctrlKey || event.metaKey;\n const parsedUrl = new URL(url);\n\n // capture link clicks within documentation\n const linkText =\n (event.target as HTMLAnchorElement | undefined)?.innerText || url;\n const to = url.replace(window.location.origin, '');\n analytics.captureEvent('click', linkText, { attributes: { to } });\n\n // hash exists when anchor is clicked on secondary sidebar\n if (parsedUrl.hash) {\n if (modifierActive) {\n window.open(url, '_blank');\n } else {\n navigate(url);\n // Scroll to hash if it's on the current page\n transformedElement\n ?.querySelector(`[id=\"${parsedUrl.hash.slice(1)}\"]`)\n ?.scrollIntoView();\n }\n } else {\n if (modifierActive) {\n window.open(url, '_blank');\n } else {\n navigate(url);\n }\n }\n },\n }),\n // disable MkDocs drawer toggling ('for' attribute => checkbox mechanism)\n onCssReady({\n onLoading: () => {},\n onLoaded: () => {\n transformedElement\n .querySelector('.md-nav__title')\n ?.removeAttribute('for');\n },\n }),\n // hide sidebars until their positions are updated\n onCssReady({\n onLoading: () => {\n const sidebars = Array.from(\n transformedElement.querySelectorAll<HTMLElement>('.md-sidebar'),\n );\n sidebars.forEach(element => {\n element.style.setProperty('opacity', '0');\n });\n },\n onLoaded: () => {},\n }),\n ]),\n [theme, navigate, analytics, entityRef.name],\n );\n\n useEffect(() => {\n if (!rawPage) return () => {};\n\n // if false, there is already a newer execution of this effect\n let shouldReplaceContent = true;\n\n // Pre-render\n preRender(rawPage, path).then(async preTransformedDomElement => {\n if (!preTransformedDomElement?.innerHTML) {\n return; // An unexpected error occurred\n }\n\n // don't manipulate the shadow dom if this isn't the latest effect execution\n if (!shouldReplaceContent) {\n return;\n }\n\n // Scroll to top after render\n window.scroll({ top: 0 });\n\n // Post-render\n const postTransformedDomElement = await postRender(\n preTransformedDomElement,\n );\n setDom(postTransformedDomElement as HTMLElement);\n });\n\n // cancel this execution\n return () => {\n shouldReplaceContent = false;\n };\n }, [rawPage, path, preRender, postRender]);\n\n return dom;\n};\n"],"names":["transformer"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dom.esm.js","sources":["../../../../src/reader/components/TechDocsReaderPageContent/dom.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { useCallback, useEffect, useState } from 'react';\n\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { useTheme } from '@material-ui/core/styles';\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { useAnalytics, useApi } from '@backstage/core-plugin-api';\nimport { scmIntegrationsApiRef } from '@backstage/integration-react';\n\nimport {\n techdocsStorageApiRef,\n useShadowDomStylesLoading,\n} from '@backstage/plugin-techdocs-react';\n\nimport { useTechDocsReader } from '../TechDocsReaderProvider';\n\nimport {\n addBaseUrl,\n addGitFeedbackLink,\n addLinkClickListener,\n addSidebarToggle,\n onCssReady,\n removeMkdocsHeader,\n rewriteDocLinks,\n simplifyMkdocsFooter,\n scrollIntoNavigation,\n transform as transformer,\n copyToClipboard,\n useSanitizerTransformer,\n useStylesTransformer,\n handleMetaRedirects,\n} from '../../transformers';\nimport { useNavigateUrl } from './useNavigateUrl';\n\nconst MOBILE_MEDIA_QUERY = 'screen and (max-width: 76.1875em)';\n\n/**\n * Hook that encapsulates the behavior of getting raw HTML and applying\n * transforms to it in order to make it function at a basic level in the\n * Backstage UI.\n */\nexport const useTechDocsReaderDom = (\n entityRef: CompoundEntityRef,\n): Element | null => {\n const navigate = useNavigateUrl();\n const theme = useTheme();\n const isMobileMedia = useMediaQuery(MOBILE_MEDIA_QUERY);\n const sanitizerTransformer = useSanitizerTransformer();\n const stylesTransformer = useStylesTransformer();\n const analytics = useAnalytics();\n\n const techdocsStorageApi = useApi(techdocsStorageApiRef);\n const scmIntegrationsApi = useApi(scmIntegrationsApiRef);\n\n const { state, path, content: rawPage } = useTechDocsReader();\n\n const [dom, setDom] = useState<HTMLElement | null>(null);\n const isStyleLoading = useShadowDomStylesLoading(dom);\n\n const updateSidebarPositionAndHeight = useCallback(() => {\n if (!dom) return;\n\n const sidebars = dom.querySelectorAll<HTMLElement>('.md-sidebar');\n\n sidebars.forEach(element => {\n // set sidebar position to render in correct position\n if (isMobileMedia) {\n element.style.top = '0px';\n } else {\n const page = document?.querySelector('.techdocs-reader-page');\n const pageTop = page?.getBoundingClientRect().top ?? 0;\n let domTop = dom.getBoundingClientRect().top ?? 0;\n\n const tabs = dom.querySelector('.md-container > .md-tabs');\n const tabsHeight = tabs?.getBoundingClientRect().height ?? 0;\n\n // the sidebars should not scroll beyond the total height of the header and tabs\n if (domTop < pageTop) {\n domTop = pageTop;\n }\n\n const scrollbarTopPx = Math.max(domTop, 0) + tabsHeight;\n\n element.style.top = `${scrollbarTopPx}px`;\n\n // set scrollbar height to ensure all links can be seen when content is small\n const footer = dom.querySelector('.md-container > .md-footer');\n // if no footer, fallback to using the bottom of the window\n const scrollbarEndPx =\n footer?.getBoundingClientRect().top ?? window.innerHeight;\n\n element.style.height = `${scrollbarEndPx - scrollbarTopPx}px`;\n }\n\n // show the sidebar only after updating its position\n element.style.setProperty('opacity', '1');\n });\n }, [dom, isMobileMedia]);\n\n useEffect(() => {\n window.addEventListener('resize', updateSidebarPositionAndHeight);\n window.addEventListener('scroll', updateSidebarPositionAndHeight, true);\n return () => {\n window.removeEventListener('resize', updateSidebarPositionAndHeight);\n window.removeEventListener(\n 'scroll',\n updateSidebarPositionAndHeight,\n true,\n );\n };\n }, [dom, updateSidebarPositionAndHeight]);\n\n // dynamically set width of footer to accommodate for pinning of the sidebar\n const updateFooterWidth = useCallback(() => {\n if (!dom) return;\n const footer = dom.querySelector<HTMLElement>('.md-footer');\n if (footer) {\n footer.style.width = `${dom.getBoundingClientRect().width}px`;\n }\n }, [dom]);\n\n useEffect(() => {\n window.addEventListener('resize', updateFooterWidth);\n return () => {\n window.removeEventListener('resize', updateFooterWidth);\n };\n }, [dom, updateFooterWidth]);\n\n // an update to \"state\" might lead to an updated UI so we include it as a trigger\n useEffect(() => {\n if (!isStyleLoading) {\n updateFooterWidth();\n updateSidebarPositionAndHeight();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n state,\n isStyleLoading,\n updateFooterWidth,\n updateSidebarPositionAndHeight,\n ]);\n\n // a function that performs transformations that are executed prior to adding it to the DOM\n const preRender = useCallback(\n (rawContent: string, contentPath: string) =>\n transformer(rawContent, [\n sanitizerTransformer,\n addBaseUrl({\n techdocsStorageApi,\n entityId: entityRef,\n path: contentPath,\n }),\n rewriteDocLinks(),\n addSidebarToggle(),\n removeMkdocsHeader(),\n simplifyMkdocsFooter(),\n addGitFeedbackLink(scmIntegrationsApi),\n stylesTransformer,\n ]),\n [\n // only add dependencies that are in state or memorized variables to avoid unnecessary calls between re-renders\n entityRef,\n scmIntegrationsApi,\n techdocsStorageApi,\n sanitizerTransformer,\n stylesTransformer,\n ],\n );\n\n // a function that performs transformations that are executed after adding it to the DOM\n const postRender = useCallback(\n async (transformedElement: Element) =>\n transformer(transformedElement, [\n handleMetaRedirects(navigate, entityRef.name),\n scrollIntoNavigation(),\n copyToClipboard(theme),\n addLinkClickListener({\n baseUrl: window.location.origin,\n onClick: (event: MouseEvent, url: string) => {\n // detect if CTRL or META keys are pressed so that links can be opened in a new tab with `window.open`\n const modifierActive = event.ctrlKey || event.metaKey;\n const parsedUrl = new URL(url);\n\n // capture link clicks within documentation\n const linkText =\n (event.target as HTMLAnchorElement | undefined)?.innerText || url;\n const to = url.replace(window.location.origin, '');\n analytics.captureEvent('click', linkText, { attributes: { to } });\n\n // hash exists when anchor is clicked on secondary sidebar\n if (parsedUrl.hash) {\n if (modifierActive) {\n window.open(url, '_blank');\n } else {\n navigate(url);\n // Scroll to hash if it's on the current page\n transformedElement\n ?.querySelector(`[id=\"${parsedUrl.hash.slice(1)}\"]`)\n ?.scrollIntoView();\n }\n } else {\n if (modifierActive) {\n window.open(url, '_blank');\n } else {\n navigate(url);\n }\n }\n },\n }),\n // disable MkDocs drawer toggling ('for' attribute => checkbox mechanism)\n onCssReady({\n onLoading: () => {},\n onLoaded: () => {\n transformedElement\n .querySelector('.md-nav__title')\n ?.removeAttribute('for');\n },\n }),\n // hide sidebars until their positions are updated\n onCssReady({\n onLoading: () => {\n const sidebars = Array.from(\n transformedElement.querySelectorAll<HTMLElement>('.md-sidebar'),\n );\n sidebars.forEach(element => {\n element.style.setProperty('opacity', '0');\n });\n },\n onLoaded: () => {},\n }),\n ]),\n [theme, navigate, analytics, entityRef.name],\n );\n\n useEffect(() => {\n if (!rawPage) return () => {};\n\n // if false, there is already a newer execution of this effect\n let shouldReplaceContent = true;\n\n // Pre-render\n preRender(rawPage, path).then(async preTransformedDomElement => {\n if (!preTransformedDomElement?.innerHTML) {\n return; // An unexpected error occurred\n }\n\n // don't manipulate the shadow dom if this isn't the latest effect execution\n if (!shouldReplaceContent) {\n return;\n }\n\n // Scroll to top after render\n window.scroll({ top: 0 });\n\n // Post-render\n const postTransformedDomElement = await postRender(\n preTransformedDomElement,\n );\n setDom(postTransformedDomElement as HTMLElement);\n });\n\n // cancel this execution\n return () => {\n shouldReplaceContent = false;\n };\n }, [rawPage, path, preRender, postRender]);\n\n return dom;\n};\n"],"names":["transformer"],"mappings":"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"}
|
package/dist/reader/components/TechDocsRedirectNotification/TechDocsRedirectNotification.esm.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
2
|
+
import React, { useState } from 'react';
|
|
3
|
+
import Snackbar from '@material-ui/core/Snackbar';
|
|
4
|
+
import Button from '@material-ui/core/Button';
|
|
5
|
+
|
|
6
|
+
const useStyles = makeStyles((theme) => ({
|
|
7
|
+
button: {
|
|
8
|
+
color: theme.palette.primary.light,
|
|
9
|
+
textDecoration: "underline"
|
|
10
|
+
}
|
|
11
|
+
}));
|
|
12
|
+
const TechDocsRedirectNotification = ({
|
|
13
|
+
message,
|
|
14
|
+
handleButtonClick,
|
|
15
|
+
autoHideDuration
|
|
16
|
+
}) => {
|
|
17
|
+
const classes = useStyles();
|
|
18
|
+
const [open, setOpen] = useState(true);
|
|
19
|
+
const handleClose = () => setOpen(false);
|
|
20
|
+
return /* @__PURE__ */ React.createElement(
|
|
21
|
+
Snackbar,
|
|
22
|
+
{
|
|
23
|
+
open,
|
|
24
|
+
anchorOrigin: { vertical: "top", horizontal: "right" },
|
|
25
|
+
autoHideDuration,
|
|
26
|
+
color: "primary",
|
|
27
|
+
onClose: handleClose,
|
|
28
|
+
message,
|
|
29
|
+
action: /* @__PURE__ */ React.createElement(
|
|
30
|
+
Button,
|
|
31
|
+
{
|
|
32
|
+
classes: { root: classes.button },
|
|
33
|
+
size: "small",
|
|
34
|
+
onClick: () => {
|
|
35
|
+
handleClose();
|
|
36
|
+
handleButtonClick();
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"Redirect now"
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export { TechDocsRedirectNotification };
|
|
46
|
+
//# sourceMappingURL=TechDocsRedirectNotification.esm.js.map
|
package/dist/reader/components/TechDocsRedirectNotification/TechDocsRedirectNotification.esm.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TechDocsRedirectNotification.esm.js","sources":["../../../../src/reader/components/TechDocsRedirectNotification/TechDocsRedirectNotification.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { makeStyles } from '@material-ui/core/styles';\nimport React, { useState } from 'react';\nimport Snackbar from '@material-ui/core/Snackbar';\nimport Button from '@material-ui/core/Button';\n\ntype TechDocsRedirectNotificationProps = {\n handleButtonClick: () => void;\n message: string;\n autoHideDuration: number;\n};\n\nconst useStyles = makeStyles(theme => ({\n button: {\n color: theme.palette.primary.light,\n textDecoration: 'underline',\n },\n}));\n\nexport const TechDocsRedirectNotification = ({\n message,\n handleButtonClick,\n autoHideDuration,\n}: TechDocsRedirectNotificationProps) => {\n const classes = useStyles();\n const [open, setOpen] = useState(true);\n\n const handleClose = () => setOpen(false);\n\n return (\n <Snackbar\n open={open}\n anchorOrigin={{ vertical: 'top', horizontal: 'right' }}\n autoHideDuration={autoHideDuration}\n color=\"primary\"\n onClose={handleClose}\n message={message}\n action={\n <Button\n classes={{ root: classes.button }}\n size=\"small\"\n onClick={() => {\n handleClose();\n handleButtonClick();\n }}\n >\n Redirect now\n </Button>\n }\n />\n );\n};\n"],"names":[],"mappings":";;;;;AA2BA,MAAM,SAAA,GAAY,WAAW,CAAU,KAAA,MAAA;AAAA,EACrC,MAAQ,EAAA;AAAA,IACN,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,OAAQ,CAAA,KAAA;AAAA,IAC7B,cAAgB,EAAA,WAAA;AAAA,GAClB;AACF,CAAE,CAAA,CAAA,CAAA;AAEK,MAAM,+BAA+B,CAAC;AAAA,EAC3C,OAAA;AAAA,EACA,iBAAA;AAAA,EACA,gBAAA;AACF,CAAyC,KAAA;AACvC,EAAA,MAAM,UAAU,SAAU,EAAA,CAAA;AAC1B,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,IAAI,CAAA,CAAA;AAErC,EAAM,MAAA,WAAA,GAAc,MAAM,OAAA,CAAQ,KAAK,CAAA,CAAA;AAEvC,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,YAAc,EAAA,EAAE,QAAU,EAAA,KAAA,EAAO,YAAY,OAAQ,EAAA;AAAA,MACrD,gBAAA;AAAA,MACA,KAAM,EAAA,SAAA;AAAA,MACN,OAAS,EAAA,WAAA;AAAA,MACT,OAAA;AAAA,MACA,MACE,kBAAA,KAAA,CAAA,aAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,OAAS,EAAA,EAAE,IAAM,EAAA,OAAA,CAAQ,MAAO,EAAA;AAAA,UAChC,IAAK,EAAA,OAAA;AAAA,UACL,SAAS,MAAM;AACb,YAAY,WAAA,EAAA,CAAA;AACZ,YAAkB,iBAAA,EAAA,CAAA;AAAA,WACpB;AAAA,SAAA;AAAA,QACD,cAAA;AAAA,OAED;AAAA,KAAA;AAAA,GAEJ,CAAA;AAEJ;;;;"}
|
|
@@ -1,49 +1,10 @@
|
|
|
1
1
|
import { normalizeUrl } from './rewriteDocLinks.esm.js';
|
|
2
|
-
import
|
|
3
|
-
import React, { useState } from 'react';
|
|
2
|
+
import React from 'react';
|
|
4
3
|
import { renderReactElement } from './renderReactElement.esm.js';
|
|
5
|
-
import
|
|
6
|
-
import { makeStyles } from '@material-ui/core/styles';
|
|
4
|
+
import { TechDocsRedirectNotification } from '../components/TechDocsRedirectNotification/TechDocsRedirectNotification.esm.js';
|
|
7
5
|
|
|
8
|
-
const useStyles = makeStyles((theme) => ({
|
|
9
|
-
button: {
|
|
10
|
-
color: theme.palette.primary.light,
|
|
11
|
-
textDecoration: "underline"
|
|
12
|
-
}
|
|
13
|
-
}));
|
|
14
|
-
const RedirectNotification = ({
|
|
15
|
-
message,
|
|
16
|
-
handleButtonClick,
|
|
17
|
-
autoHideDuration
|
|
18
|
-
}) => {
|
|
19
|
-
const classes = useStyles();
|
|
20
|
-
const [open, setOpen] = useState(true);
|
|
21
|
-
const handleClose = () => {
|
|
22
|
-
setOpen((prev) => !prev);
|
|
23
|
-
};
|
|
24
|
-
return /* @__PURE__ */ React.createElement(
|
|
25
|
-
Snackbar,
|
|
26
|
-
{
|
|
27
|
-
open,
|
|
28
|
-
anchorOrigin: { vertical: "top", horizontal: "right" },
|
|
29
|
-
autoHideDuration,
|
|
30
|
-
color: "primary",
|
|
31
|
-
onClose: handleClose,
|
|
32
|
-
message,
|
|
33
|
-
action: /* @__PURE__ */ React.createElement(
|
|
34
|
-
Button,
|
|
35
|
-
{
|
|
36
|
-
classes: { root: classes.button },
|
|
37
|
-
size: "small",
|
|
38
|
-
onClick: handleButtonClick
|
|
39
|
-
},
|
|
40
|
-
"Redirect now"
|
|
41
|
-
)
|
|
42
|
-
}
|
|
43
|
-
);
|
|
44
|
-
};
|
|
45
6
|
const handleMetaRedirects = (navigate, entityName) => {
|
|
46
|
-
const redirectAfterMs =
|
|
7
|
+
const redirectAfterMs = 3e3;
|
|
47
8
|
const determineRedirectURL = (metaUrl) => {
|
|
48
9
|
const normalizedCurrentUrl = normalizeUrl(window.location.href);
|
|
49
10
|
const absoluteRedirectObj = new URL(metaUrl, normalizedCurrentUrl);
|
|
@@ -55,7 +16,7 @@ const handleMetaRedirects = (navigate, entityName) => {
|
|
|
55
16
|
0,
|
|
56
17
|
indexOfSiteHome + entityName.length
|
|
57
18
|
);
|
|
58
|
-
return siteHomePath;
|
|
19
|
+
return new URL(siteHomePath, normalizedCurrentUrl).href;
|
|
59
20
|
}
|
|
60
21
|
return absoluteRedirectObj.href;
|
|
61
22
|
};
|
|
@@ -64,14 +25,17 @@ const handleMetaRedirects = (navigate, entityName) => {
|
|
|
64
25
|
if (elem.getAttribute("http-equiv") === "refresh") {
|
|
65
26
|
const metaContentParameters = elem.getAttribute("content")?.split("url=");
|
|
66
27
|
if (!metaContentParameters || metaContentParameters.length < 2) {
|
|
67
|
-
|
|
28
|
+
return dom;
|
|
68
29
|
}
|
|
69
30
|
const metaUrl = metaContentParameters[1];
|
|
70
31
|
const redirectURL = determineRedirectURL(metaUrl);
|
|
32
|
+
if (window.location.href === redirectURL) {
|
|
33
|
+
return dom;
|
|
34
|
+
}
|
|
71
35
|
const container = document.createElement("div");
|
|
72
36
|
renderReactElement(
|
|
73
37
|
/* @__PURE__ */ React.createElement(
|
|
74
|
-
|
|
38
|
+
TechDocsRedirectNotification,
|
|
75
39
|
{
|
|
76
40
|
message: "This TechDocs page is no longer maintained. Will automatically redirect to the designated replacement.",
|
|
77
41
|
handleButtonClick: () => navigate(redirectURL),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handleMetaRedirects.esm.js","sources":["../../../src/reader/transformers/handleMetaRedirects.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Transformer } from './transformer';\nimport { normalizeUrl } from './rewriteDocLinks';\nimport
|
|
1
|
+
{"version":3,"file":"handleMetaRedirects.esm.js","sources":["../../../src/reader/transformers/handleMetaRedirects.tsx"],"sourcesContent":["/*\n * Copyright 2024 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Transformer } from './transformer';\nimport { normalizeUrl } from './rewriteDocLinks';\nimport React from 'react';\nimport { renderReactElement } from './renderReactElement';\nimport { TechDocsRedirectNotification } from '../components/TechDocsRedirectNotification';\n\nexport const handleMetaRedirects = (\n navigate: (to: string) => void,\n entityName: string,\n): Transformer => {\n const redirectAfterMs = 3000;\n\n const determineRedirectURL = (metaUrl: string) => {\n const normalizedCurrentUrl = normalizeUrl(window.location.href);\n // When creating URL object, if the metaUrl is relative, it will be resolved with base href. If it is absolute, it will replace the base href.\n const absoluteRedirectObj = new URL(metaUrl, normalizedCurrentUrl);\n const isExternalRedirect =\n absoluteRedirectObj.hostname !== window.location.hostname;\n\n if (isExternalRedirect) {\n const currentTechDocPath = window.location.pathname;\n const indexOfSiteHome = currentTechDocPath.indexOf(entityName);\n const siteHomePath = currentTechDocPath.slice(\n 0,\n indexOfSiteHome + entityName.length,\n );\n return new URL(siteHomePath, normalizedCurrentUrl).href;\n }\n return absoluteRedirectObj.href;\n };\n\n return dom => {\n for (const elem of Array.from(dom.querySelectorAll('meta'))) {\n if (elem.getAttribute('http-equiv') === 'refresh') {\n const metaContentParameters = elem\n .getAttribute('content')\n ?.split('url=');\n\n if (!metaContentParameters || metaContentParameters.length < 2) {\n return dom;\n }\n\n const metaUrl = metaContentParameters[1];\n const redirectURL = determineRedirectURL(metaUrl);\n\n // If the current URL is the same as the redirect URL, do not proceed with the redirect.\n if (window.location.href === redirectURL) {\n return dom;\n }\n\n const container = document.createElement('div');\n\n renderReactElement(\n <TechDocsRedirectNotification\n message=\"This TechDocs page is no longer maintained. Will automatically redirect to the designated replacement.\"\n handleButtonClick={() => navigate(redirectURL)}\n autoHideDuration={redirectAfterMs}\n />,\n container,\n );\n document.body.appendChild(container);\n\n setTimeout(() => {\n navigate(redirectURL);\n }, redirectAfterMs);\n\n return dom;\n }\n }\n return dom;\n };\n};\n"],"names":[],"mappings":";;;;;AAsBa,MAAA,mBAAA,GAAsB,CACjC,QAAA,EACA,UACgB,KAAA;AAChB,EAAA,MAAM,eAAkB,GAAA,GAAA,CAAA;AAExB,EAAM,MAAA,oBAAA,GAAuB,CAAC,OAAoB,KAAA;AAChD,IAAA,MAAM,oBAAuB,GAAA,YAAA,CAAa,MAAO,CAAA,QAAA,CAAS,IAAI,CAAA,CAAA;AAE9D,IAAA,MAAM,mBAAsB,GAAA,IAAI,GAAI,CAAA,OAAA,EAAS,oBAAoB,CAAA,CAAA;AACjE,IAAA,MAAM,kBACJ,GAAA,mBAAA,CAAoB,QAAa,KAAA,MAAA,CAAO,QAAS,CAAA,QAAA,CAAA;AAEnD,IAAA,IAAI,kBAAoB,EAAA;AACtB,MAAM,MAAA,kBAAA,GAAqB,OAAO,QAAS,CAAA,QAAA,CAAA;AAC3C,MAAM,MAAA,eAAA,GAAkB,kBAAmB,CAAA,OAAA,CAAQ,UAAU,CAAA,CAAA;AAC7D,MAAA,MAAM,eAAe,kBAAmB,CAAA,KAAA;AAAA,QACtC,CAAA;AAAA,QACA,kBAAkB,UAAW,CAAA,MAAA;AAAA,OAC/B,CAAA;AACA,MAAA,OAAO,IAAI,GAAA,CAAI,YAAc,EAAA,oBAAoB,CAAE,CAAA,IAAA,CAAA;AAAA,KACrD;AACA,IAAA,OAAO,mBAAoB,CAAA,IAAA,CAAA;AAAA,GAC7B,CAAA;AAEA,EAAA,OAAO,CAAO,GAAA,KAAA;AACZ,IAAA,KAAA,MAAW,QAAQ,KAAM,CAAA,IAAA,CAAK,IAAI,gBAAiB,CAAA,MAAM,CAAC,CAAG,EAAA;AAC3D,MAAA,IAAI,IAAK,CAAA,YAAA,CAAa,YAAY,CAAA,KAAM,SAAW,EAAA;AACjD,QAAA,MAAM,wBAAwB,IAC3B,CAAA,YAAA,CAAa,SAAS,CAAA,EACrB,MAAM,MAAM,CAAA,CAAA;AAEhB,QAAA,IAAI,CAAC,qBAAA,IAAyB,qBAAsB,CAAA,MAAA,GAAS,CAAG,EAAA;AAC9D,UAAO,OAAA,GAAA,CAAA;AAAA,SACT;AAEA,QAAM,MAAA,OAAA,GAAU,sBAAsB,CAAC,CAAA,CAAA;AACvC,QAAM,MAAA,WAAA,GAAc,qBAAqB,OAAO,CAAA,CAAA;AAGhD,QAAI,IAAA,MAAA,CAAO,QAAS,CAAA,IAAA,KAAS,WAAa,EAAA;AACxC,UAAO,OAAA,GAAA,CAAA;AAAA,SACT;AAEA,QAAM,MAAA,SAAA,GAAY,QAAS,CAAA,aAAA,CAAc,KAAK,CAAA,CAAA;AAE9C,QAAA,kBAAA;AAAA,0BACE,KAAA,CAAA,aAAA;AAAA,YAAC,4BAAA;AAAA,YAAA;AAAA,cACC,OAAQ,EAAA,wGAAA;AAAA,cACR,iBAAA,EAAmB,MAAM,QAAA,CAAS,WAAW,CAAA;AAAA,cAC7C,gBAAkB,EAAA,eAAA;AAAA,aAAA;AAAA,WACpB;AAAA,UACA,SAAA;AAAA,SACF,CAAA;AACA,QAAS,QAAA,CAAA,IAAA,CAAK,YAAY,SAAS,CAAA,CAAA;AAEnC,QAAA,UAAA,CAAW,MAAM;AACf,UAAA,QAAA,CAAS,WAAW,CAAA,CAAA;AAAA,WACnB,eAAe,CAAA,CAAA;AAElB,QAAO,OAAA,GAAA,CAAA;AAAA,OACT;AAAA,KACF;AACA,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-techdocs",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.9-next.0",
|
|
4
4
|
"description": "The Backstage plugin that renders technical documentation for your components",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "frontend-plugin",
|
|
@@ -58,21 +58,21 @@
|
|
|
58
58
|
"test": "backstage-cli package test"
|
|
59
59
|
},
|
|
60
60
|
"dependencies": {
|
|
61
|
-
"@backstage/catalog-model": "^1.6.0
|
|
61
|
+
"@backstage/catalog-model": "^1.6.0",
|
|
62
62
|
"@backstage/config": "^1.2.0",
|
|
63
|
-
"@backstage/core-compat-api": "^0.2.
|
|
64
|
-
"@backstage/core-components": "^0.14.10
|
|
63
|
+
"@backstage/core-compat-api": "^0.2.9-next.0",
|
|
64
|
+
"@backstage/core-components": "^0.14.10",
|
|
65
65
|
"@backstage/core-plugin-api": "^1.9.3",
|
|
66
66
|
"@backstage/errors": "^1.2.4",
|
|
67
|
-
"@backstage/frontend-plugin-api": "^0.
|
|
68
|
-
"@backstage/integration": "^1.14.0
|
|
69
|
-
"@backstage/integration-react": "^1.1.30
|
|
70
|
-
"@backstage/plugin-auth-react": "^0.1.5
|
|
71
|
-
"@backstage/plugin-catalog-react": "^1.12.
|
|
72
|
-
"@backstage/plugin-search-common": "^1.2.14
|
|
73
|
-
"@backstage/plugin-search-react": "^1.
|
|
74
|
-
"@backstage/plugin-techdocs-common": "^0.1.0
|
|
75
|
-
"@backstage/plugin-techdocs-react": "^1.2.
|
|
67
|
+
"@backstage/frontend-plugin-api": "^0.8.0-next.0",
|
|
68
|
+
"@backstage/integration": "^1.14.0",
|
|
69
|
+
"@backstage/integration-react": "^1.1.30",
|
|
70
|
+
"@backstage/plugin-auth-react": "^0.1.5",
|
|
71
|
+
"@backstage/plugin-catalog-react": "^1.12.4-next.0",
|
|
72
|
+
"@backstage/plugin-search-common": "^1.2.14",
|
|
73
|
+
"@backstage/plugin-search-react": "^1.8.0-next.0",
|
|
74
|
+
"@backstage/plugin-techdocs-common": "^0.1.0",
|
|
75
|
+
"@backstage/plugin-techdocs-react": "^1.2.8-next.0",
|
|
76
76
|
"@backstage/theme": "^0.5.6",
|
|
77
77
|
"@material-ui/core": "^4.12.2",
|
|
78
78
|
"@material-ui/icons": "^4.9.1",
|
|
@@ -88,11 +88,11 @@
|
|
|
88
88
|
"react-use": "^17.2.4"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
|
-
"@backstage/cli": "^0.27.
|
|
92
|
-
"@backstage/core-app-api": "^1.14.2
|
|
93
|
-
"@backstage/dev-utils": "^1.0.
|
|
94
|
-
"@backstage/plugin-techdocs-module-addons-contrib": "^1.1.
|
|
95
|
-
"@backstage/test-utils": "^1.
|
|
91
|
+
"@backstage/cli": "^0.27.1-next.0",
|
|
92
|
+
"@backstage/core-app-api": "^1.14.2",
|
|
93
|
+
"@backstage/dev-utils": "^1.0.38-next.0",
|
|
94
|
+
"@backstage/plugin-techdocs-module-addons-contrib": "^1.1.14-next.0",
|
|
95
|
+
"@backstage/test-utils": "^1.6.0-next.0",
|
|
96
96
|
"@testing-library/dom": "^10.0.0",
|
|
97
97
|
"@testing-library/jest-dom": "^6.0.0",
|
|
98
98
|
"@testing-library/react": "^15.0.0",
|