@backstage/plugin-techdocs 1.13.3-next.0 → 1.14.0-next.2
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 +52 -0
- package/config.d.ts +10 -0
- package/dist/alpha.d.ts +30 -29
- package/dist/alpha.esm.js +29 -33
- package/dist/alpha.esm.js.map +1 -1
- package/dist/package.json.esm.js +1 -1
- package/dist/reader/transformers/html/transformer.esm.js +25 -0
- package/dist/reader/transformers/html/transformer.esm.js.map +1 -1
- package/package.json +15 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,57 @@
|
|
|
1
1
|
# @backstage/plugin-techdocs
|
|
2
2
|
|
|
3
|
+
## 1.14.0-next.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e4ddf22: Internal update to align with new blueprint parameter naming in the new frontend system.
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @backstage/frontend-plugin-api@0.11.0-next.1
|
|
10
|
+
- @backstage/core-compat-api@0.5.0-next.2
|
|
11
|
+
- @backstage/plugin-search-react@1.9.3-next.1
|
|
12
|
+
- @backstage/plugin-catalog-react@1.20.0-next.2
|
|
13
|
+
- @backstage/core-components@0.17.5-next.1
|
|
14
|
+
- @backstage/catalog-client@1.11.0-next.0
|
|
15
|
+
- @backstage/catalog-model@1.7.5
|
|
16
|
+
- @backstage/config@1.3.3
|
|
17
|
+
- @backstage/core-plugin-api@1.10.9
|
|
18
|
+
- @backstage/errors@1.2.7
|
|
19
|
+
- @backstage/integration@1.17.1
|
|
20
|
+
- @backstage/integration-react@1.2.9
|
|
21
|
+
- @backstage/theme@0.6.8-next.0
|
|
22
|
+
- @backstage/plugin-auth-react@0.1.18-next.0
|
|
23
|
+
- @backstage/plugin-search-common@1.2.19
|
|
24
|
+
- @backstage/plugin-techdocs-common@0.1.1
|
|
25
|
+
- @backstage/plugin-techdocs-react@1.3.2-next.0
|
|
26
|
+
|
|
27
|
+
## 1.14.0-next.1
|
|
28
|
+
|
|
29
|
+
### Minor Changes
|
|
30
|
+
|
|
31
|
+
- cb0541f: Adds `additionalAllowedURIProtocols` to sanitizer config
|
|
32
|
+
|
|
33
|
+
### Patch Changes
|
|
34
|
+
|
|
35
|
+
- f2f133c: Internal update to use the new variant of `ApiBlueprint`.
|
|
36
|
+
- Updated dependencies
|
|
37
|
+
- @backstage/core-compat-api@0.4.5-next.1
|
|
38
|
+
- @backstage/plugin-catalog-react@1.20.0-next.1
|
|
39
|
+
- @backstage/frontend-plugin-api@0.11.0-next.0
|
|
40
|
+
- @backstage/theme@0.6.8-next.0
|
|
41
|
+
- @backstage/catalog-client@1.11.0-next.0
|
|
42
|
+
- @backstage/plugin-search-react@1.9.3-next.0
|
|
43
|
+
- @backstage/plugin-techdocs-react@1.3.2-next.0
|
|
44
|
+
- @backstage/core-components@0.17.5-next.0
|
|
45
|
+
- @backstage/catalog-model@1.7.5
|
|
46
|
+
- @backstage/config@1.3.3
|
|
47
|
+
- @backstage/core-plugin-api@1.10.9
|
|
48
|
+
- @backstage/errors@1.2.7
|
|
49
|
+
- @backstage/integration@1.17.1
|
|
50
|
+
- @backstage/integration-react@1.2.9
|
|
51
|
+
- @backstage/plugin-auth-react@0.1.18-next.0
|
|
52
|
+
- @backstage/plugin-search-common@1.2.19
|
|
53
|
+
- @backstage/plugin-techdocs-common@0.1.1
|
|
54
|
+
|
|
3
55
|
## 1.13.3-next.0
|
|
4
56
|
|
|
5
57
|
### Patch Changes
|
package/config.d.ts
CHANGED
|
@@ -58,6 +58,16 @@ export interface Config {
|
|
|
58
58
|
* @visibility frontend
|
|
59
59
|
*/
|
|
60
60
|
allowedCustomElementAttributeNameRegExp?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Allows listed protocols in attributes with URI values
|
|
63
|
+
* Example:
|
|
64
|
+
* additionalAllowedURIProtocols: ['vscode']
|
|
65
|
+
* this will allow all attributes with URI values to have `vscode` protocol like `vscode://some/path` in addition to the default protocols
|
|
66
|
+
* matched by DOMPurify's IS_ALLOWED_URI RegExp:
|
|
67
|
+
* @see: https://raw.githubusercontent.com/cure53/DOMPurify/master/src/regexp.ts
|
|
68
|
+
* @visibility frontend
|
|
69
|
+
*/
|
|
70
|
+
additionalAllowedURIProtocols?: string;
|
|
61
71
|
};
|
|
62
72
|
};
|
|
63
73
|
}
|
package/dist/alpha.d.ts
CHANGED
|
@@ -25,12 +25,12 @@ declare const techDocsSearchResultListItemExtension: _backstage_frontend_plugin_
|
|
|
25
25
|
} & {
|
|
26
26
|
noTrack?: boolean | undefined;
|
|
27
27
|
};
|
|
28
|
-
output: _backstage_frontend_plugin_api.
|
|
28
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<{
|
|
29
29
|
predicate?: _backstage_plugin_search_react_alpha.SearchResultItemExtensionPredicate;
|
|
30
30
|
component: _backstage_plugin_search_react_alpha.SearchResultItemExtensionComponent;
|
|
31
31
|
}, "search.search-result-list-item.item", {}>;
|
|
32
32
|
inputs: {
|
|
33
|
-
[x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.
|
|
33
|
+
[x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ExtensionDataRef, {
|
|
34
34
|
optional: boolean;
|
|
35
35
|
singleton: boolean;
|
|
36
36
|
}>;
|
|
@@ -54,31 +54,27 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
54
54
|
name: undefined;
|
|
55
55
|
config: {};
|
|
56
56
|
configInput: {};
|
|
57
|
-
output: _backstage_frontend_plugin_api.
|
|
57
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
58
58
|
inputs: {};
|
|
59
|
-
params: {
|
|
60
|
-
factory: _backstage_frontend_plugin_api.AnyApiFactory;
|
|
61
|
-
};
|
|
59
|
+
params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
62
60
|
}>;
|
|
63
61
|
"api:techdocs/storage": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
64
62
|
kind: "api";
|
|
65
63
|
name: "storage";
|
|
66
64
|
config: {};
|
|
67
65
|
configInput: {};
|
|
68
|
-
output: _backstage_frontend_plugin_api.
|
|
66
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
|
|
69
67
|
inputs: {};
|
|
70
|
-
params: {
|
|
71
|
-
factory: _backstage_frontend_plugin_api.AnyApiFactory;
|
|
72
|
-
};
|
|
68
|
+
params: <TApi, TImpl extends TApi, TDeps extends { [name in string]: unknown; }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
|
|
73
69
|
}>;
|
|
74
70
|
"empty-state:techdocs/entity-content": _backstage_frontend_plugin_api.ExtensionDefinition<{
|
|
75
71
|
config: {};
|
|
76
72
|
configInput: {};
|
|
77
|
-
output: _backstage_frontend_plugin_api.
|
|
73
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {
|
|
78
74
|
optional: true;
|
|
79
75
|
}>;
|
|
80
76
|
inputs: {
|
|
81
|
-
[x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.
|
|
77
|
+
[x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ExtensionDataRef, {
|
|
82
78
|
optional: boolean;
|
|
83
79
|
singleton: boolean;
|
|
84
80
|
}>;
|
|
@@ -100,13 +96,13 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
100
96
|
path?: string | undefined;
|
|
101
97
|
group?: string | false | undefined;
|
|
102
98
|
};
|
|
103
|
-
output: _backstage_frontend_plugin_api.
|
|
99
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
104
100
|
optional: true;
|
|
105
|
-
}> | _backstage_frontend_plugin_api.
|
|
101
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
106
102
|
optional: true;
|
|
107
|
-
}> | _backstage_frontend_plugin_api.
|
|
103
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-filter-expression", {
|
|
108
104
|
optional: true;
|
|
109
|
-
}> | _backstage_frontend_plugin_api.
|
|
105
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-content-title", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-content-group", {
|
|
110
106
|
optional: true;
|
|
111
107
|
}>;
|
|
112
108
|
inputs: {
|
|
@@ -124,10 +120,13 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
124
120
|
kind: "entity-content";
|
|
125
121
|
name: undefined;
|
|
126
122
|
params: {
|
|
123
|
+
defaultPath?: [Error: `Use the 'path' param instead`];
|
|
124
|
+
path: string;
|
|
125
|
+
defaultTitle?: [Error: `Use the 'title' param instead`];
|
|
126
|
+
title: string;
|
|
127
|
+
defaultGroup?: [Error: `Use the 'group' param instead`];
|
|
128
|
+
group?: keyof typeof _backstage_plugin_catalog_react_alpha.defaultEntityContentGroups | (string & {});
|
|
127
129
|
loader: () => Promise<JSX.Element>;
|
|
128
|
-
defaultPath: string;
|
|
129
|
-
defaultTitle: string;
|
|
130
|
-
defaultGroup?: keyof typeof _backstage_plugin_catalog_react_alpha.defaultEntityContentGroups | (string & {});
|
|
131
130
|
routeRef?: _backstage_frontend_plugin_api.RouteRef;
|
|
132
131
|
filter?: string | _backstage_plugin_catalog_react_alpha.EntityPredicate | ((entity: _backstage_catalog_model.Entity) => boolean);
|
|
133
132
|
};
|
|
@@ -145,11 +144,11 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
145
144
|
label?: string | undefined;
|
|
146
145
|
title?: string | undefined;
|
|
147
146
|
};
|
|
148
|
-
output: _backstage_frontend_plugin_api.
|
|
147
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
|
|
149
148
|
optional: true;
|
|
150
|
-
}> | _backstage_frontend_plugin_api.
|
|
149
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-filter-expression", {
|
|
151
150
|
optional: true;
|
|
152
|
-
}> | _backstage_frontend_plugin_api.
|
|
151
|
+
}> | _backstage_frontend_plugin_api.ExtensionDataRef<() => _backstage_core_components.IconLinkVerticalProps, "entity-icon-link-props", {}>;
|
|
153
152
|
inputs: {};
|
|
154
153
|
params: {
|
|
155
154
|
useProps: () => Omit<_backstage_core_components.IconLinkVerticalProps, "color">;
|
|
@@ -161,7 +160,7 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
161
160
|
name: undefined;
|
|
162
161
|
config: {};
|
|
163
162
|
configInput: {};
|
|
164
|
-
output: _backstage_frontend_plugin_api.
|
|
163
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<{
|
|
165
164
|
title: string;
|
|
166
165
|
icon: _backstage_core_plugin_api.IconComponent;
|
|
167
166
|
routeRef: _backstage_frontend_plugin_api.RouteRef<undefined>;
|
|
@@ -182,12 +181,13 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
182
181
|
configInput: {
|
|
183
182
|
path?: string | undefined;
|
|
184
183
|
};
|
|
185
|
-
output: _backstage_frontend_plugin_api.
|
|
184
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
186
185
|
optional: true;
|
|
187
186
|
}>;
|
|
188
187
|
inputs: {};
|
|
189
188
|
params: {
|
|
190
|
-
defaultPath:
|
|
189
|
+
defaultPath?: [Error: `Use the 'path' param instead`];
|
|
190
|
+
path: string;
|
|
191
191
|
loader: () => Promise<JSX.Element>;
|
|
192
192
|
routeRef?: _backstage_frontend_plugin_api.RouteRef;
|
|
193
193
|
};
|
|
@@ -199,7 +199,7 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
199
199
|
configInput: {
|
|
200
200
|
path?: string | undefined;
|
|
201
201
|
};
|
|
202
|
-
output: _backstage_frontend_plugin_api.
|
|
202
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
|
|
203
203
|
optional: true;
|
|
204
204
|
}>;
|
|
205
205
|
inputs: {
|
|
@@ -211,7 +211,8 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
211
211
|
kind: "page";
|
|
212
212
|
name: "reader";
|
|
213
213
|
params: {
|
|
214
|
-
defaultPath:
|
|
214
|
+
defaultPath?: [Error: `Use the 'path' param instead`];
|
|
215
|
+
path: string;
|
|
215
216
|
loader: () => Promise<JSX.Element>;
|
|
216
217
|
routeRef?: _backstage_frontend_plugin_api.RouteRef;
|
|
217
218
|
};
|
|
@@ -233,12 +234,12 @@ declare const _default: _backstage_frontend_plugin_api.FrontendPlugin<{
|
|
|
233
234
|
} & {
|
|
234
235
|
noTrack?: boolean | undefined;
|
|
235
236
|
};
|
|
236
|
-
output: _backstage_frontend_plugin_api.
|
|
237
|
+
output: _backstage_frontend_plugin_api.ExtensionDataRef<{
|
|
237
238
|
predicate?: _backstage_plugin_search_react_alpha.SearchResultItemExtensionPredicate;
|
|
238
239
|
component: _backstage_plugin_search_react_alpha.SearchResultItemExtensionComponent;
|
|
239
240
|
}, "search.search-result-list-item.item", {}>;
|
|
240
241
|
inputs: {
|
|
241
|
-
[x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.
|
|
242
|
+
[x: string]: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ExtensionDataRef, {
|
|
242
243
|
optional: boolean;
|
|
243
244
|
singleton: boolean;
|
|
244
245
|
}>;
|
package/dist/alpha.esm.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import LibraryBooks from '@material-ui/icons/LibraryBooks';
|
|
3
3
|
import { ApiBlueprint, PageBlueprint, createExtensionInput, coreExtensionData, createExtension, NavItemBlueprint, createFrontendPlugin } from '@backstage/frontend-plugin-api';
|
|
4
|
-
import {
|
|
4
|
+
import { configApiRef, discoveryApiRef, fetchApiRef } from '@backstage/core-plugin-api';
|
|
5
5
|
import { compatWrapper, convertLegacyRouteRef, convertLegacyRouteRefs } from '@backstage/core-compat-api';
|
|
6
6
|
import { EntityIconLinkBlueprint, EntityContentBlueprint } from '@backstage/plugin-catalog-react/alpha';
|
|
7
7
|
import { SearchResultListItemBlueprint } from '@backstage/plugin-search-react/alpha';
|
|
@@ -33,38 +33,34 @@ const techdocsEntityIconLink = EntityIconLinkBlueprint.make({
|
|
|
33
33
|
});
|
|
34
34
|
const techDocsStorageApi = ApiBlueprint.make({
|
|
35
35
|
name: "storage",
|
|
36
|
-
params: {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
fetchApi
|
|
48
|
-
})
|
|
36
|
+
params: (defineParams) => defineParams({
|
|
37
|
+
api: techdocsStorageApiRef,
|
|
38
|
+
deps: {
|
|
39
|
+
configApi: configApiRef,
|
|
40
|
+
discoveryApi: discoveryApiRef,
|
|
41
|
+
fetchApi: fetchApiRef
|
|
42
|
+
},
|
|
43
|
+
factory: ({ configApi, discoveryApi, fetchApi }) => new TechDocsStorageClient({
|
|
44
|
+
configApi,
|
|
45
|
+
discoveryApi,
|
|
46
|
+
fetchApi
|
|
49
47
|
})
|
|
50
|
-
}
|
|
48
|
+
})
|
|
51
49
|
});
|
|
52
50
|
const techDocsClientApi = ApiBlueprint.make({
|
|
53
|
-
params: {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
fetchApi
|
|
65
|
-
})
|
|
51
|
+
params: (defineParams) => defineParams({
|
|
52
|
+
api: techdocsApiRef,
|
|
53
|
+
deps: {
|
|
54
|
+
configApi: configApiRef,
|
|
55
|
+
discoveryApi: discoveryApiRef,
|
|
56
|
+
fetchApi: fetchApiRef
|
|
57
|
+
},
|
|
58
|
+
factory: ({ configApi, discoveryApi, fetchApi }) => new TechDocsClient({
|
|
59
|
+
configApi,
|
|
60
|
+
discoveryApi,
|
|
61
|
+
fetchApi
|
|
66
62
|
})
|
|
67
|
-
}
|
|
63
|
+
})
|
|
68
64
|
});
|
|
69
65
|
const techDocsSearchResultListItemExtension = SearchResultListItemBlueprint.makeWithOverrides({
|
|
70
66
|
config: {
|
|
@@ -89,7 +85,7 @@ const techDocsSearchResultListItemExtension = SearchResultListItemBlueprint.make
|
|
|
89
85
|
});
|
|
90
86
|
const techDocsPage = PageBlueprint.make({
|
|
91
87
|
params: {
|
|
92
|
-
|
|
88
|
+
path: "/docs",
|
|
93
89
|
routeRef: convertLegacyRouteRef(rootRouteRef),
|
|
94
90
|
loader: () => import('./home/components/TechDocsIndexPage.esm.js').then(
|
|
95
91
|
(m) => compatWrapper(/* @__PURE__ */ jsx(m.TechDocsIndexPage, {}))
|
|
@@ -109,7 +105,7 @@ const techDocsReaderPage = PageBlueprint.makeWithOverrides({
|
|
|
109
105
|
return /* @__PURE__ */ jsx(Addon, {}, options.name);
|
|
110
106
|
});
|
|
111
107
|
return originalFactory({
|
|
112
|
-
|
|
108
|
+
path: "/docs/:namespace/:kind/:name",
|
|
113
109
|
routeRef: convertLegacyRouteRef(rootDocsRouteRef),
|
|
114
110
|
loader: async () => await import('./Router.esm.js').then(({ TechDocsReaderRouter }) => {
|
|
115
111
|
return compatWrapper(
|
|
@@ -136,8 +132,8 @@ const techDocsEntityContent = EntityContentBlueprint.makeWithOverrides({
|
|
|
136
132
|
factory(originalFactory, context) {
|
|
137
133
|
return originalFactory(
|
|
138
134
|
{
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
path: "docs",
|
|
136
|
+
title: "TechDocs",
|
|
141
137
|
routeRef: convertLegacyRouteRef(rootCatalogDocsRouteRef),
|
|
142
138
|
loader: () => import('./Router.esm.js').then(({ EmbeddedDocsRouter }) => {
|
|
143
139
|
const addons = context.inputs.addons.map((output) => {
|
package/dist/alpha.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha/index.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 LibraryBooks from '@material-ui/icons/LibraryBooks';\nimport {\n createFrontendPlugin,\n ApiBlueprint,\n PageBlueprint,\n NavItemBlueprint,\n createExtensionInput,\n coreExtensionData,\n createExtension,\n} from '@backstage/frontend-plugin-api';\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 EntityContentBlueprint,\n EntityIconLinkBlueprint,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { SearchResultListItemBlueprint } from '@backstage/plugin-search-react/alpha';\nimport { AddonBlueprint } from '@backstage/plugin-techdocs-react/alpha';\nimport { TechDocsClient, TechDocsStorageClient } from '../client';\nimport {\n rootCatalogDocsRouteRef,\n rootDocsRouteRef,\n rootRouteRef,\n} from '../routes';\nimport { TechDocsReaderLayout } from '../reader';\nimport { attachTechDocsAddonComponentData } from '@backstage/plugin-techdocs-react/alpha';\nimport {\n TechDocsAddons,\n techdocsApiRef,\n techdocsStorageApiRef,\n} from '@backstage/plugin-techdocs-react';\n\nimport { useTechdocsReaderIconLinkProps } from './hooks/useTechdocsReaderIconLinkProps';\n\n/** @alpha */\nconst techdocsEntityIconLink = EntityIconLinkBlueprint.make({\n name: 'read-docs',\n params: {\n useProps: useTechdocsReaderIconLinkProps,\n },\n});\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.makeWithOverrides({\n name: 'reader',\n inputs: {\n addons: createExtensionInput([AddonBlueprint.dataRefs.addon]),\n },\n factory(originalFactory, { inputs }) {\n const addons = inputs.addons.map(output => {\n const options = output.get(AddonBlueprint.dataRefs.addon);\n const Addon = options.component;\n attachTechDocsAddonComponentData(Addon, options);\n return <Addon key={options.name} />;\n });\n\n return originalFactory({\n defaultPath: '/docs/:namespace/:kind/:name',\n routeRef: convertLegacyRouteRef(rootDocsRouteRef),\n loader: async () =>\n await import('../Router').then(({ TechDocsReaderRouter }) => {\n return compatWrapper(\n <TechDocsReaderRouter>\n <TechDocsReaderLayout />\n <TechDocsAddons>{addons}</TechDocsAddons>\n </TechDocsReaderRouter>,\n );\n }),\n });\n },\n});\n\n/**\n * Component responsible for rendering techdocs on entity pages\n *\n * @alpha\n */\nconst techDocsEntityContent = EntityContentBlueprint.makeWithOverrides({\n inputs: {\n addons: createExtensionInput([AddonBlueprint.dataRefs.addon]),\n emptyState: createExtensionInput(\n [coreExtensionData.reactElement.optional()],\n {\n singleton: true,\n optional: true,\n },\n ),\n },\n factory(originalFactory, context) {\n return originalFactory(\n {\n defaultPath: 'docs',\n defaultTitle: 'TechDocs',\n routeRef: convertLegacyRouteRef(rootCatalogDocsRouteRef),\n loader: () =>\n import('../Router').then(({ EmbeddedDocsRouter }) => {\n const addons = context.inputs.addons.map(output => {\n const options = output.get(AddonBlueprint.dataRefs.addon);\n const Addon = options.component;\n attachTechDocsAddonComponentData(Addon, options);\n return <Addon key={options.name} />;\n });\n return compatWrapper(\n <EmbeddedDocsRouter\n emptyState={context.inputs.emptyState?.get(\n coreExtensionData.reactElement,\n )}\n >\n <TechDocsAddons>{addons}</TechDocsAddons>\n </EmbeddedDocsRouter>,\n );\n }),\n },\n context,\n );\n },\n});\n\nconst techDocsEntityContentEmptyState = createExtension({\n kind: 'empty-state',\n name: 'entity-content',\n attachTo: { id: 'entity-content:techdocs', input: 'emptyState' },\n output: [coreExtensionData.reactElement.optional()],\n factory: () => [],\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 pluginId: 'techdocs',\n info: { packageJson: () => import('../../package.json') },\n extensions: [\n techDocsClientApi,\n techDocsStorageApi,\n techDocsNavItem,\n techDocsPage,\n techDocsReaderPage,\n techdocsEntityIconLink,\n techDocsEntityContent,\n techDocsEntityContentEmptyState,\n techDocsSearchResultListItemExtension,\n ],\n routes: convertLegacyRouteRefs({\n root: rootRouteRef,\n docRoot: rootDocsRouteRef,\n entityContent: rootCatalogDocsRouteRef,\n }),\n});\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4DA,MAAM,sBAAA,GAAyB,wBAAwB,IAAK,CAAA;AAAA,EAC1D,IAAM,EAAA,WAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,QAAU,EAAA;AAAA;AAEd,CAAC,CAAA;AAGD,MAAM,kBAAA,GAAqB,aAAa,IAAK,CAAA;AAAA,EAC3C,IAAM,EAAA,SAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,SAAS,gBAAiB,CAAA;AAAA,MACxB,GAAK,EAAA,qBAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,SAAW,EAAA,YAAA;AAAA,QACX,YAAc,EAAA,eAAA;AAAA,QACd,QAAU,EAAA;AAAA,OACZ;AAAA,MACA,OAAA,EAAS,CAAC,EAAE,SAAA,EAAW,cAAc,QAAS,EAAA,KAC5C,IAAI,qBAAsB,CAAA;AAAA,QACxB,SAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA,OACD;AAAA,KACJ;AAAA;AAEL,CAAC,CAAA;AAGD,MAAM,iBAAA,GAAoB,aAAa,IAAK,CAAA;AAAA,EAC1C,MAAQ,EAAA;AAAA,IACN,SAAS,gBAAiB,CAAA;AAAA,MACxB,GAAK,EAAA,cAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,SAAW,EAAA,YAAA;AAAA,QACX,YAAc,EAAA,eAAA;AAAA,QACd,QAAU,EAAA;AAAA,OACZ;AAAA,MACA,OAAA,EAAS,CAAC,EAAE,SAAA,EAAW,cAAc,QAAS,EAAA,KAC5C,IAAI,cAAe,CAAA;AAAA,QACjB,SAAA;AAAA,QACA,YAAA;AAAA,QACA;AAAA,OACD;AAAA,KACJ;AAAA;AAEL,CAAC,CAAA;AAGY,MAAA,qCAAA,GACX,8BAA8B,iBAAkB,CAAA;AAAA,EAC9C,MAAQ,EAAA;AAAA,IACN,MAAQ,EAAA;AAAA,MACN,KAAO,EAAA,CAAA,CAAA,KAAK,CAAE,CAAA,MAAA,GAAS,QAAS,EAAA;AAAA,MAChC,WAAW,CAAK,CAAA,KAAA,CAAA,CAAE,MAAO,EAAA,CAAE,QAAQ,CAAC,CAAA;AAAA,MACpC,QAAQ,CAAK,CAAA,KAAA,CAAA,CAAE,OAAQ,EAAA,CAAE,QAAQ,IAAI,CAAA;AAAA,MACrC,YAAY,CAAK,CAAA,KAAA,CAAA,CAAE,OAAQ,EAAA,CAAE,QAAQ,IAAI;AAAA;AAC3C,GACF;AAAA,EACA,OAAQ,CAAA,eAAA,EAAiB,EAAE,MAAA,EAAU,EAAA;AACnC,IAAA,OAAO,eAAgB,CAAA;AAAA,MACrB,SAAA,EAAW,CAAU,MAAA,KAAA,MAAA,CAAO,IAAS,KAAA,UAAA;AAAA,MACrC,WAAW,YAAY;AACrB,QAAA,MAAM,EAAE,4BAAA,EAAiC,GAAA,MAAM,OAC7C,yDACF,CAAA;AACA,QAAA,OAAO,CACL,KAAA,KAAA,aAAA;AAAA,0BACG,GAAA,CAAA,4BAAA,EAAA,EAA8B,GAAG,KAAA,EAAQ,GAAG,MAAQ,EAAA;AAAA,SACvD;AAAA;AACJ,KACD,CAAA;AAAA;AAEL,CAAC;AAOH,MAAM,YAAA,GAAe,cAAc,IAAK,CAAA;AAAA,EACtC,MAAQ,EAAA;AAAA,IACN,WAAa,EAAA,OAAA;AAAA,IACb,QAAA,EAAU,sBAAsB,YAAY,CAAA;AAAA,IAC5C,MAAQ,EAAA,MACN,OAAO,4CAAsC,CAAE,CAAA,IAAA;AAAA,MAAK,OAClD,aAAc,iBAAA,GAAA,CAAC,CAAE,CAAA,iBAAA,EAAF,EAAoB,CAAE;AAAA;AACvC;AAEN,CAAC,CAAA;AAOD,MAAM,kBAAA,GAAqB,cAAc,iBAAkB,CAAA;AAAA,EACzD,IAAM,EAAA,QAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,QAAQ,oBAAqB,CAAA,CAAC,cAAe,CAAA,QAAA,CAAS,KAAK,CAAC;AAAA,GAC9D;AAAA,EACA,OAAQ,CAAA,eAAA,EAAiB,EAAE,MAAA,EAAU,EAAA;AACnC,IAAA,MAAM,MAAS,GAAA,MAAA,CAAO,MAAO,CAAA,GAAA,CAAI,CAAU,MAAA,KAAA;AACzC,MAAA,MAAM,OAAU,GAAA,MAAA,CAAO,GAAI,CAAA,cAAA,CAAe,SAAS,KAAK,CAAA;AACxD,MAAA,MAAM,QAAQ,OAAQ,CAAA,SAAA;AACtB,MAAA,gCAAA,CAAiC,OAAO,OAAO,CAAA;AAC/C,MAAO,uBAAA,GAAA,CAAC,KAAW,EAAA,EAAA,EAAA,OAAA,CAAQ,IAAM,CAAA;AAAA,KAClC,CAAA;AAED,IAAA,OAAO,eAAgB,CAAA;AAAA,MACrB,WAAa,EAAA,8BAAA;AAAA,MACb,QAAA,EAAU,sBAAsB,gBAAgB,CAAA;AAAA,MAChD,MAAA,EAAQ,YACN,MAAM,OAAO,iBAAW,EAAE,IAAK,CAAA,CAAC,EAAE,oBAAA,EAA2B,KAAA;AAC3D,QAAO,OAAA,aAAA;AAAA,+BACJ,oBACC,EAAA,EAAA,QAAA,EAAA;AAAA,4BAAA,GAAA,CAAC,oBAAqB,EAAA,EAAA,CAAA;AAAA,4BACtB,GAAA,CAAC,kBAAgB,QAAO,EAAA,MAAA,EAAA;AAAA,WAC1B,EAAA;AAAA,SACF;AAAA,OACD;AAAA,KACJ,CAAA;AAAA;AAEL,CAAC,CAAA;AAOD,MAAM,qBAAA,GAAwB,uBAAuB,iBAAkB,CAAA;AAAA,EACrE,MAAQ,EAAA;AAAA,IACN,QAAQ,oBAAqB,CAAA,CAAC,cAAe,CAAA,QAAA,CAAS,KAAK,CAAC,CAAA;AAAA,IAC5D,UAAY,EAAA,oBAAA;AAAA,MACV,CAAC,iBAAA,CAAkB,YAAa,CAAA,QAAA,EAAU,CAAA;AAAA,MAC1C;AAAA,QACE,SAAW,EAAA,IAAA;AAAA,QACX,QAAU,EAAA;AAAA;AACZ;AACF,GACF;AAAA,EACA,OAAA,CAAQ,iBAAiB,OAAS,EAAA;AAChC,IAAO,OAAA,eAAA;AAAA,MACL;AAAA,QACE,WAAa,EAAA,MAAA;AAAA,QACb,YAAc,EAAA,UAAA;AAAA,QACd,QAAA,EAAU,sBAAsB,uBAAuB,CAAA;AAAA,QACvD,MAAA,EAAQ,MACN,OAAO,iBAAW,EAAE,IAAK,CAAA,CAAC,EAAE,kBAAA,EAAyB,KAAA;AACnD,UAAA,MAAM,MAAS,GAAA,OAAA,CAAQ,MAAO,CAAA,MAAA,CAAO,IAAI,CAAU,MAAA,KAAA;AACjD,YAAA,MAAM,OAAU,GAAA,MAAA,CAAO,GAAI,CAAA,cAAA,CAAe,SAAS,KAAK,CAAA;AACxD,YAAA,MAAM,QAAQ,OAAQ,CAAA,SAAA;AACtB,YAAA,gCAAA,CAAiC,OAAO,OAAO,CAAA;AAC/C,YAAO,uBAAA,GAAA,CAAC,KAAW,EAAA,EAAA,EAAA,OAAA,CAAQ,IAAM,CAAA;AAAA,WAClC,CAAA;AACD,UAAO,OAAA,aAAA;AAAA,4BACL,GAAA;AAAA,cAAC,kBAAA;AAAA,cAAA;AAAA,gBACC,UAAA,EAAY,OAAQ,CAAA,MAAA,CAAO,UAAY,EAAA,GAAA;AAAA,kBACrC,iBAAkB,CAAA;AAAA,iBACpB;AAAA,gBAEA,QAAA,kBAAA,GAAA,CAAC,kBAAgB,QAAO,EAAA,MAAA,EAAA;AAAA;AAAA;AAC1B,WACF;AAAA,SACD;AAAA,OACL;AAAA,MACA;AAAA,KACF;AAAA;AAEJ,CAAC,CAAA;AAED,MAAM,kCAAkC,eAAgB,CAAA;AAAA,EACtD,IAAM,EAAA,aAAA;AAAA,EACN,IAAM,EAAA,gBAAA;AAAA,EACN,QAAU,EAAA,EAAE,EAAI,EAAA,yBAAA,EAA2B,OAAO,YAAa,EAAA;AAAA,EAC/D,MAAQ,EAAA,CAAC,iBAAkB,CAAA,YAAA,CAAa,UAAU,CAAA;AAAA,EAClD,OAAA,EAAS,MAAM;AACjB,CAAC,CAAA;AAGD,MAAM,eAAA,GAAkB,iBAAiB,IAAK,CAAA;AAAA,EAC5C,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,YAAA;AAAA,IACN,KAAO,EAAA,MAAA;AAAA,IACP,QAAA,EAAU,sBAAsB,YAAY;AAAA;AAEhD,CAAC,CAAA;AAGD,YAAe,oBAAqB,CAAA;AAAA,EAClC,QAAU,EAAA,UAAA;AAAA,EACV,MAAM,EAAE,WAAA,EAAa,MAAM,OAAO,uBAAoB,CAAE,EAAA;AAAA,EACxD,UAAY,EAAA;AAAA,IACV,iBAAA;AAAA,IACA,kBAAA;AAAA,IACA,eAAA;AAAA,IACA,YAAA;AAAA,IACA,kBAAA;AAAA,IACA,sBAAA;AAAA,IACA,qBAAA;AAAA,IACA,+BAAA;AAAA,IACA;AAAA,GACF;AAAA,EACA,QAAQ,sBAAuB,CAAA;AAAA,IAC7B,IAAM,EAAA,YAAA;AAAA,IACN,OAAS,EAAA,gBAAA;AAAA,IACT,aAAe,EAAA;AAAA,GAChB;AACH,CAAC,CAAA;;;;"}
|
|
1
|
+
{"version":3,"file":"alpha.esm.js","sources":["../src/alpha/index.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 LibraryBooks from '@material-ui/icons/LibraryBooks';\nimport {\n createFrontendPlugin,\n ApiBlueprint,\n PageBlueprint,\n NavItemBlueprint,\n createExtensionInput,\n coreExtensionData,\n createExtension,\n} from '@backstage/frontend-plugin-api';\nimport {\n configApiRef,\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 EntityContentBlueprint,\n EntityIconLinkBlueprint,\n} from '@backstage/plugin-catalog-react/alpha';\nimport { SearchResultListItemBlueprint } from '@backstage/plugin-search-react/alpha';\nimport { AddonBlueprint } from '@backstage/plugin-techdocs-react/alpha';\nimport { TechDocsClient, TechDocsStorageClient } from '../client';\nimport {\n rootCatalogDocsRouteRef,\n rootDocsRouteRef,\n rootRouteRef,\n} from '../routes';\nimport { TechDocsReaderLayout } from '../reader';\nimport { attachTechDocsAddonComponentData } from '@backstage/plugin-techdocs-react/alpha';\nimport {\n TechDocsAddons,\n techdocsApiRef,\n techdocsStorageApiRef,\n} from '@backstage/plugin-techdocs-react';\n\nimport { useTechdocsReaderIconLinkProps } from './hooks/useTechdocsReaderIconLinkProps';\n\n/** @alpha */\nconst techdocsEntityIconLink = EntityIconLinkBlueprint.make({\n name: 'read-docs',\n params: {\n useProps: useTechdocsReaderIconLinkProps,\n },\n});\n\n/** @alpha */\nconst techDocsStorageApi = ApiBlueprint.make({\n name: 'storage',\n params: defineParams =>\n defineParams({\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/** @alpha */\nconst techDocsClientApi = ApiBlueprint.make({\n params: defineParams =>\n defineParams({\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/** @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 path: '/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.makeWithOverrides({\n name: 'reader',\n inputs: {\n addons: createExtensionInput([AddonBlueprint.dataRefs.addon]),\n },\n factory(originalFactory, { inputs }) {\n const addons = inputs.addons.map(output => {\n const options = output.get(AddonBlueprint.dataRefs.addon);\n const Addon = options.component;\n attachTechDocsAddonComponentData(Addon, options);\n return <Addon key={options.name} />;\n });\n\n return originalFactory({\n path: '/docs/:namespace/:kind/:name',\n routeRef: convertLegacyRouteRef(rootDocsRouteRef),\n loader: async () =>\n await import('../Router').then(({ TechDocsReaderRouter }) => {\n return compatWrapper(\n <TechDocsReaderRouter>\n <TechDocsReaderLayout />\n <TechDocsAddons>{addons}</TechDocsAddons>\n </TechDocsReaderRouter>,\n );\n }),\n });\n },\n});\n\n/**\n * Component responsible for rendering techdocs on entity pages\n *\n * @alpha\n */\nconst techDocsEntityContent = EntityContentBlueprint.makeWithOverrides({\n inputs: {\n addons: createExtensionInput([AddonBlueprint.dataRefs.addon]),\n emptyState: createExtensionInput(\n [coreExtensionData.reactElement.optional()],\n {\n singleton: true,\n optional: true,\n },\n ),\n },\n factory(originalFactory, context) {\n return originalFactory(\n {\n path: 'docs',\n title: 'TechDocs',\n routeRef: convertLegacyRouteRef(rootCatalogDocsRouteRef),\n loader: () =>\n import('../Router').then(({ EmbeddedDocsRouter }) => {\n const addons = context.inputs.addons.map(output => {\n const options = output.get(AddonBlueprint.dataRefs.addon);\n const Addon = options.component;\n attachTechDocsAddonComponentData(Addon, options);\n return <Addon key={options.name} />;\n });\n return compatWrapper(\n <EmbeddedDocsRouter\n emptyState={context.inputs.emptyState?.get(\n coreExtensionData.reactElement,\n )}\n >\n <TechDocsAddons>{addons}</TechDocsAddons>\n </EmbeddedDocsRouter>,\n );\n }),\n },\n context,\n );\n },\n});\n\nconst techDocsEntityContentEmptyState = createExtension({\n kind: 'empty-state',\n name: 'entity-content',\n attachTo: { id: 'entity-content:techdocs', input: 'emptyState' },\n output: [coreExtensionData.reactElement.optional()],\n factory: () => [],\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 pluginId: 'techdocs',\n info: { packageJson: () => import('../../package.json') },\n extensions: [\n techDocsClientApi,\n techDocsStorageApi,\n techDocsNavItem,\n techDocsPage,\n techDocsReaderPage,\n techdocsEntityIconLink,\n techDocsEntityContent,\n techDocsEntityContentEmptyState,\n techDocsSearchResultListItemExtension,\n ],\n routes: convertLegacyRouteRefs({\n root: rootRouteRef,\n docRoot: rootDocsRouteRef,\n entityContent: rootCatalogDocsRouteRef,\n }),\n});\n"],"names":[],"mappings":"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"}
|
package/dist/package.json.esm.js
CHANGED
|
@@ -42,12 +42,37 @@ const useSanitizerTransformer = () => {
|
|
|
42
42
|
const attributeNameCheck = config?.getOptionalString(
|
|
43
43
|
"allowedCustomElementAttributeNameRegExp"
|
|
44
44
|
);
|
|
45
|
+
const additionalAllowedURIProtocols = config?.getOptionalStringArray("additionalAllowedURIProtocols") || [];
|
|
46
|
+
const allowedURIProtocols = [
|
|
47
|
+
"callto",
|
|
48
|
+
"cid",
|
|
49
|
+
"ftp",
|
|
50
|
+
"ftps",
|
|
51
|
+
"http",
|
|
52
|
+
"https",
|
|
53
|
+
"mailto",
|
|
54
|
+
"matrix",
|
|
55
|
+
"sms",
|
|
56
|
+
"tel",
|
|
57
|
+
"xmpp",
|
|
58
|
+
...additionalAllowedURIProtocols
|
|
59
|
+
].filter(Boolean);
|
|
60
|
+
const allowedURIRegExp = new RegExp(
|
|
61
|
+
// This regex is not exposed by DOMPurify, so we need to define it ourselves.
|
|
62
|
+
// It is possible for this to drift from the default in future versions of DOMPurify.
|
|
63
|
+
// See: https://raw.githubusercontent.com/cure53/DOMPurify/master/src/regexp.ts
|
|
64
|
+
`^(?:${allowedURIProtocols.join(
|
|
65
|
+
"|"
|
|
66
|
+
)}:|[^a-z]|[a-z+.-]+(?:[^a-z+.\\-:]|$))`,
|
|
67
|
+
"i"
|
|
68
|
+
);
|
|
45
69
|
return DOMPurify.sanitize(dom.outerHTML, {
|
|
46
70
|
ADD_TAGS: tags,
|
|
47
71
|
FORBID_TAGS: ["style"],
|
|
48
72
|
ADD_ATTR: ["http-equiv", "content", "dominant-baseline"],
|
|
49
73
|
WHOLE_DOCUMENT: true,
|
|
50
74
|
RETURN_DOM: true,
|
|
75
|
+
ALLOWED_URI_REGEXP: allowedURIRegExp,
|
|
51
76
|
CUSTOM_ELEMENT_HANDLING: {
|
|
52
77
|
tagNameCheck: tagNameCheck ? new RegExp(tagNameCheck) : void 0,
|
|
53
78
|
attributeNameCheck: attributeNameCheck ? new RegExp(attributeNameCheck) : void 0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transformer.esm.js","sources":["../../../../src/reader/transformers/html/transformer.ts"],"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 DOMPurify from 'dompurify';\nimport { useCallback, useMemo } from 'react';\n\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { Transformer } from '../transformer';\nimport { removeUnsafeIframes, removeUnsafeLinks } from './hooks';\n\n/**\n * Returns html sanitizer configuration\n */\nconst useSanitizerConfig = () => {\n const configApi = useApi(configApiRef);\n\n return useMemo(() => {\n return configApi.getOptionalConfig('techdocs.sanitizer');\n }, [configApi]);\n};\n\n/**\n * Returns a transformer that sanitizes the dom\n */\nexport const useSanitizerTransformer = (): Transformer => {\n const config = useSanitizerConfig();\n\n return useCallback(\n async (dom: Element) => {\n const hosts = config?.getOptionalStringArray('allowedIframeHosts');\n\n DOMPurify.addHook('beforeSanitizeElements', removeUnsafeLinks);\n const tags = ['link', 'meta'];\n\n if (hosts) {\n tags.push('iframe');\n DOMPurify.addHook('beforeSanitizeElements', removeUnsafeIframes(hosts));\n }\n\n // Only allow meta tags if they are used for refreshing the page. They are required for the redirect feature.\n DOMPurify.addHook('uponSanitizeElement', (currNode, data) => {\n if (data.tagName === 'meta') {\n const isMetaRefreshTag =\n currNode.getAttribute('http-equiv') === 'refresh' &&\n currNode.getAttribute('content')?.includes('url=');\n if (!isMetaRefreshTag) {\n currNode.parentNode?.removeChild(currNode);\n }\n }\n });\n\n // Only allow http-equiv and content attributes on meta tags. They are required for the redirect feature.\n DOMPurify.addHook('uponSanitizeAttribute', (currNode, data) => {\n if (currNode.tagName !== 'meta') {\n if (data.attrName === 'http-equiv' || data.attrName === 'content') {\n currNode.removeAttribute(data.attrName);\n }\n }\n });\n\n const tagNameCheck = config?.getOptionalString(\n 'allowedCustomElementTagNameRegExp',\n );\n const attributeNameCheck = config?.getOptionalString(\n 'allowedCustomElementAttributeNameRegExp',\n );\n\n // using outerHTML as we want to preserve the html tag attributes (lang)\n return DOMPurify.sanitize(dom.outerHTML, {\n ADD_TAGS: tags,\n FORBID_TAGS: ['style'],\n ADD_ATTR: ['http-equiv', 'content', 'dominant-baseline'],\n WHOLE_DOCUMENT: true,\n RETURN_DOM: true,\n CUSTOM_ELEMENT_HANDLING: {\n tagNameCheck: tagNameCheck ? new RegExp(tagNameCheck) : undefined,\n attributeNameCheck: attributeNameCheck\n ? new RegExp(attributeNameCheck)\n : undefined,\n },\n });\n },\n [config],\n );\n};\n"],"names":[],"mappings":";;;;;;AA2BA,MAAM,qBAAqB,MAAM;AAC/B,EAAM,MAAA,SAAA,GAAY,OAAO,YAAY,CAAA;AAErC,EAAA,OAAO,QAAQ,MAAM;AACnB,IAAO,OAAA,SAAA,CAAU,kBAAkB,oBAAoB,CAAA;AAAA,GACzD,EAAG,CAAC,SAAS,CAAC,CAAA;AAChB,CAAA;AAKO,MAAM,0BAA0B,MAAmB;AACxD,EAAA,MAAM,SAAS,kBAAmB,EAAA;AAElC,EAAO,OAAA,WAAA;AAAA,IACL,OAAO,GAAiB,KAAA;AACtB,MAAM,MAAA,KAAA,GAAQ,MAAQ,EAAA,sBAAA,CAAuB,oBAAoB,CAAA;AAEjE,MAAU,SAAA,CAAA,OAAA,CAAQ,0BAA0B,iBAAiB,CAAA;AAC7D,MAAM,MAAA,IAAA,GAAO,CAAC,MAAA,EAAQ,MAAM,CAAA;AAE5B,MAAA,IAAI,KAAO,EAAA;AACT,QAAA,IAAA,CAAK,KAAK,QAAQ,CAAA;AAClB,QAAA,SAAA,CAAU,OAAQ,CAAA,wBAAA,EAA0B,mBAAoB,CAAA,KAAK,CAAC,CAAA;AAAA;AAIxE,MAAA,SAAA,CAAU,OAAQ,CAAA,qBAAA,EAAuB,CAAC,QAAA,EAAU,IAAS,KAAA;AAC3D,QAAI,IAAA,IAAA,CAAK,YAAY,MAAQ,EAAA;AAC3B,UAAM,MAAA,gBAAA,GACJ,QAAS,CAAA,YAAA,CAAa,YAAY,CAAA,KAAM,SACxC,IAAA,QAAA,CAAS,YAAa,CAAA,SAAS,CAAG,EAAA,QAAA,CAAS,MAAM,CAAA;AACnD,UAAA,IAAI,CAAC,gBAAkB,EAAA;AACrB,YAAS,QAAA,CAAA,UAAA,EAAY,YAAY,QAAQ,CAAA;AAAA;AAC3C;AACF,OACD,CAAA;AAGD,MAAA,SAAA,CAAU,OAAQ,CAAA,uBAAA,EAAyB,CAAC,QAAA,EAAU,IAAS,KAAA;AAC7D,QAAI,IAAA,QAAA,CAAS,YAAY,MAAQ,EAAA;AAC/B,UAAA,IAAI,IAAK,CAAA,QAAA,KAAa,YAAgB,IAAA,IAAA,CAAK,aAAa,SAAW,EAAA;AACjE,YAAS,QAAA,CAAA,eAAA,CAAgB,KAAK,QAAQ,CAAA;AAAA;AACxC;AACF,OACD,CAAA;AAED,MAAA,MAAM,eAAe,MAAQ,EAAA,iBAAA;AAAA,QAC3B;AAAA,OACF;AACA,MAAA,MAAM,qBAAqB,MAAQ,EAAA,iBAAA;AAAA,QACjC;AAAA,OACF;AAGA,MAAO,OAAA,SAAA,CAAU,QAAS,CAAA,GAAA,CAAI,SAAW,EAAA;AAAA,QACvC,QAAU,EAAA,IAAA;AAAA,QACV,WAAA,EAAa,CAAC,OAAO,CAAA;AAAA,QACrB,QAAU,EAAA,CAAC,YAAc,EAAA,SAAA,EAAW,mBAAmB,CAAA;AAAA,QACvD,cAAgB,EAAA,IAAA;AAAA,QAChB,UAAY,EAAA,IAAA;AAAA,QACZ,uBAAyB,EAAA;AAAA,UACvB,YAAc,EAAA,YAAA,GAAe,IAAI,MAAA,CAAO,YAAY,CAAI,GAAA,KAAA,CAAA;AAAA,UACxD,kBAAoB,EAAA,kBAAA,GAChB,IAAI,MAAA,CAAO,kBAAkB,CAC7B,GAAA,KAAA;AAAA;AACN,OACD,CAAA;AAAA,KACH;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AACF;;;;"}
|
|
1
|
+
{"version":3,"file":"transformer.esm.js","sources":["../../../../src/reader/transformers/html/transformer.ts"],"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 DOMPurify from 'dompurify';\nimport { useCallback, useMemo } from 'react';\n\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { Transformer } from '../transformer';\nimport { removeUnsafeIframes, removeUnsafeLinks } from './hooks';\n\n/**\n * Returns html sanitizer configuration\n */\nconst useSanitizerConfig = () => {\n const configApi = useApi(configApiRef);\n\n return useMemo(() => {\n return configApi.getOptionalConfig('techdocs.sanitizer');\n }, [configApi]);\n};\n\n/**\n * Returns a transformer that sanitizes the dom\n */\nexport const useSanitizerTransformer = (): Transformer => {\n const config = useSanitizerConfig();\n\n return useCallback(\n async (dom: Element) => {\n const hosts = config?.getOptionalStringArray('allowedIframeHosts');\n\n DOMPurify.addHook('beforeSanitizeElements', removeUnsafeLinks);\n const tags = ['link', 'meta'];\n\n if (hosts) {\n tags.push('iframe');\n DOMPurify.addHook('beforeSanitizeElements', removeUnsafeIframes(hosts));\n }\n\n // Only allow meta tags if they are used for refreshing the page. They are required for the redirect feature.\n DOMPurify.addHook('uponSanitizeElement', (currNode, data) => {\n if (data.tagName === 'meta') {\n const isMetaRefreshTag =\n currNode.getAttribute('http-equiv') === 'refresh' &&\n currNode.getAttribute('content')?.includes('url=');\n if (!isMetaRefreshTag) {\n currNode.parentNode?.removeChild(currNode);\n }\n }\n });\n\n // Only allow http-equiv and content attributes on meta tags. They are required for the redirect feature.\n DOMPurify.addHook('uponSanitizeAttribute', (currNode, data) => {\n if (currNode.tagName !== 'meta') {\n if (data.attrName === 'http-equiv' || data.attrName === 'content') {\n currNode.removeAttribute(data.attrName);\n }\n }\n });\n\n const tagNameCheck = config?.getOptionalString(\n 'allowedCustomElementTagNameRegExp',\n );\n const attributeNameCheck = config?.getOptionalString(\n 'allowedCustomElementAttributeNameRegExp',\n );\n const additionalAllowedURIProtocols =\n config?.getOptionalStringArray('additionalAllowedURIProtocols') || [];\n\n // Define allowed URI protocols, including any additional ones from the config.\n // The default protocols are based on the DOMPurify defaults.\n const allowedURIProtocols = [\n 'callto',\n 'cid',\n 'ftp',\n 'ftps',\n 'http',\n 'https',\n 'mailto',\n 'matrix',\n 'sms',\n 'tel',\n 'xmpp',\n ...additionalAllowedURIProtocols,\n ].filter(Boolean);\n\n const allowedURIRegExp = new RegExp(\n // This regex is not exposed by DOMPurify, so we need to define it ourselves.\n // It is possible for this to drift from the default in future versions of DOMPurify.\n // See: https://raw.githubusercontent.com/cure53/DOMPurify/master/src/regexp.ts\n `^(?:${allowedURIProtocols.join(\n '|',\n )}:|[^a-z]|[a-z+.-]+(?:[^a-z+.\\\\-:]|$))`,\n 'i',\n );\n\n // using outerHTML as we want to preserve the html tag attributes (lang)\n return DOMPurify.sanitize(dom.outerHTML, {\n ADD_TAGS: tags,\n FORBID_TAGS: ['style'],\n ADD_ATTR: ['http-equiv', 'content', 'dominant-baseline'],\n WHOLE_DOCUMENT: true,\n RETURN_DOM: true,\n ALLOWED_URI_REGEXP: allowedURIRegExp,\n CUSTOM_ELEMENT_HANDLING: {\n tagNameCheck: tagNameCheck ? new RegExp(tagNameCheck) : undefined,\n attributeNameCheck: attributeNameCheck\n ? new RegExp(attributeNameCheck)\n : undefined,\n },\n });\n },\n [config],\n );\n};\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-techdocs",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.14.0-next.2",
|
|
4
4
|
"description": "The Backstage plugin that renders technical documentation for your components",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "frontend-plugin",
|
|
@@ -71,23 +71,23 @@
|
|
|
71
71
|
"test": "backstage-cli package test"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
|
-
"@backstage/catalog-client": "1.
|
|
74
|
+
"@backstage/catalog-client": "1.11.0-next.0",
|
|
75
75
|
"@backstage/catalog-model": "1.7.5",
|
|
76
76
|
"@backstage/config": "1.3.3",
|
|
77
|
-
"@backstage/core-compat-api": "0.
|
|
78
|
-
"@backstage/core-components": "0.17.
|
|
77
|
+
"@backstage/core-compat-api": "0.5.0-next.2",
|
|
78
|
+
"@backstage/core-components": "0.17.5-next.1",
|
|
79
79
|
"@backstage/core-plugin-api": "1.10.9",
|
|
80
80
|
"@backstage/errors": "1.2.7",
|
|
81
|
-
"@backstage/frontend-plugin-api": "0.
|
|
81
|
+
"@backstage/frontend-plugin-api": "0.11.0-next.1",
|
|
82
82
|
"@backstage/integration": "1.17.1",
|
|
83
83
|
"@backstage/integration-react": "1.2.9",
|
|
84
|
-
"@backstage/plugin-auth-react": "0.1.
|
|
85
|
-
"@backstage/plugin-catalog-react": "1.
|
|
84
|
+
"@backstage/plugin-auth-react": "0.1.18-next.0",
|
|
85
|
+
"@backstage/plugin-catalog-react": "1.20.0-next.2",
|
|
86
86
|
"@backstage/plugin-search-common": "1.2.19",
|
|
87
|
-
"@backstage/plugin-search-react": "1.9.
|
|
87
|
+
"@backstage/plugin-search-react": "1.9.3-next.1",
|
|
88
88
|
"@backstage/plugin-techdocs-common": "0.1.1",
|
|
89
|
-
"@backstage/plugin-techdocs-react": "1.3.
|
|
90
|
-
"@backstage/theme": "0.6.
|
|
89
|
+
"@backstage/plugin-techdocs-react": "1.3.2-next.0",
|
|
90
|
+
"@backstage/theme": "0.6.8-next.0",
|
|
91
91
|
"@material-ui/core": "^4.12.2",
|
|
92
92
|
"@material-ui/icons": "^4.9.1",
|
|
93
93
|
"@material-ui/lab": "4.0.0-alpha.61",
|
|
@@ -101,12 +101,12 @@
|
|
|
101
101
|
"react-use": "^17.2.4"
|
|
102
102
|
},
|
|
103
103
|
"devDependencies": {
|
|
104
|
-
"@backstage/cli": "0.
|
|
104
|
+
"@backstage/cli": "0.34.0-next.1",
|
|
105
105
|
"@backstage/core-app-api": "1.18.0",
|
|
106
|
-
"@backstage/dev-utils": "1.1.13-next.
|
|
107
|
-
"@backstage/plugin-catalog": "1.31.2-next.
|
|
108
|
-
"@backstage/plugin-techdocs-module-addons-contrib": "1.1.
|
|
109
|
-
"@backstage/test-utils": "1.7.
|
|
106
|
+
"@backstage/dev-utils": "1.1.13-next.1",
|
|
107
|
+
"@backstage/plugin-catalog": "1.31.2-next.2",
|
|
108
|
+
"@backstage/plugin-techdocs-module-addons-contrib": "1.1.27-next.0",
|
|
109
|
+
"@backstage/test-utils": "1.7.11-next.0",
|
|
110
110
|
"@testing-library/dom": "^10.0.0",
|
|
111
111
|
"@testing-library/jest-dom": "^6.0.0",
|
|
112
112
|
"@testing-library/react": "^16.0.0",
|