@backstage/plugin-techdocs 0.0.0-nightly-20260909022715 → 0.0.0-nightly-20260919022921

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.
Files changed (31) hide show
  1. package/CHANGELOG.md +42 -17
  2. package/dist/EntityPageDocs.esm.js +3 -1
  3. package/dist/EntityPageDocs.esm.js.map +1 -1
  4. package/dist/Router.esm.js +9 -2
  5. package/dist/Router.esm.js.map +1 -1
  6. package/dist/alpha/components/TechDocsReaderContent.esm.js +2 -1
  7. package/dist/alpha/components/TechDocsReaderContent.esm.js.map +1 -1
  8. package/dist/alpha/components/TechDocsReaderLayout.esm.js +2 -2
  9. package/dist/alpha/components/TechDocsReaderLayout.esm.js.map +1 -1
  10. package/dist/alpha/components/TechDocsReaderPage.esm.js +10 -2
  11. package/dist/alpha/components/TechDocsReaderPage.esm.js.map +1 -1
  12. package/dist/alpha.d.ts +4 -0
  13. package/dist/alpha.esm.js +9 -3
  14. package/dist/alpha.esm.js.map +1 -1
  15. package/dist/helpers.esm.js +1 -1
  16. package/dist/helpers.esm.js.map +1 -1
  17. package/dist/home/components/Grids/EntityListDocsGrid.esm.js +2 -2
  18. package/dist/home/components/Grids/EntityListDocsGrid.esm.js.map +1 -1
  19. package/dist/home/components/Tables/columns.esm.js +3 -9
  20. package/dist/home/components/Tables/columns.esm.js.map +1 -1
  21. package/dist/hooks/useTechDocsReaderContentData.esm.js +5 -2
  22. package/dist/hooks/useTechDocsReaderContentData.esm.js.map +1 -1
  23. package/dist/index.d.ts +4 -0
  24. package/dist/plugins/techdocs/package.json.esm.js +1 -1
  25. package/dist/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.esm.js +2 -1
  26. package/dist/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.esm.js.map +1 -1
  27. package/dist/reader/components/TechDocsReaderPageContent/dom.esm.js +5 -3
  28. package/dist/reader/components/TechDocsReaderPageContent/dom.esm.js.map +1 -1
  29. package/dist/search/hooks/useTechDocsLocation.esm.js +1 -1
  30. package/dist/search/hooks/useTechDocsLocation.esm.js.map +1 -1
  31. package/package.json +21 -21
package/CHANGELOG.md CHANGED
@@ -1,30 +1,55 @@
1
1
  # @backstage/plugin-techdocs
2
2
 
3
- ## 0.0.0-nightly-20260909022715
3
+ ## 0.0.0-nightly-20260919022921
4
+
5
+ ### Minor Changes
6
+
7
+ - 80a0da9: Added `withoutFeedbackLink` prop to `page:techdocs/reader` and `entity-content:techdocs` extensions, which can be set to `true` to disable the feedback button in the rendered documentation.
4
8
 
5
9
  ### Patch Changes
6
10
 
7
- - d421187: Reduced the initial app bundle size by loading page and optional UI implementations only when their extensions render.
8
- - 9cb79f5: Use the catalog presentation API for TechDocs document titles and owner labels so entity display names are consistent with the rest of Backstage.
9
11
  - Updated dependencies
10
- - @backstage/core-components@0.0.0-nightly-20260909022715
11
- - @backstage/ui@0.0.0-nightly-20260909022715
12
- - @backstage/integration@0.0.0-nightly-20260909022715
13
- - @backstage/config@0.0.0-nightly-20260909022715
14
- - @backstage/frontend-plugin-api@0.0.0-nightly-20260909022715
15
- - @backstage/plugin-catalog-react@0.0.0-nightly-20260909022715
16
- - @backstage/integration-react@0.0.0-nightly-20260909022715
17
- - @backstage/plugin-auth-react@0.0.0-nightly-20260909022715
18
- - @backstage/plugin-search-react@0.0.0-nightly-20260909022715
19
- - @backstage/plugin-techdocs-react@0.0.0-nightly-20260909022715
20
- - @backstage/catalog-client@0.0.0-nightly-20260909022715
21
- - @backstage/catalog-model@1.10.0
22
- - @backstage/core-plugin-api@0.0.0-nightly-20260909022715
12
+ - @backstage/config@0.0.0-nightly-20260919022921
13
+ - @backstage/core-components@0.0.0-nightly-20260919022921
14
+ - @backstage/core-plugin-api@0.0.0-nightly-20260919022921
15
+ - @backstage/frontend-plugin-api@0.0.0-nightly-20260919022921
16
+ - @backstage/integration@0.0.0-nightly-20260919022921
17
+ - @backstage/integration-react@0.0.0-nightly-20260919022921
18
+ - @backstage/plugin-techdocs-react@0.0.0-nightly-20260919022921
19
+ - @backstage/plugin-catalog-react@0.0.0-nightly-20260919022921
20
+ - @backstage/plugin-search-react@0.0.0-nightly-20260919022921
21
+ - @backstage/ui@0.18.0
22
+ - @backstage/plugin-auth-react@0.0.0-nightly-20260919022921
23
+ - @backstage/catalog-client@0.0.0-nightly-20260919022921
24
+ - @backstage/plugin-search-common@0.0.0-nightly-20260919022921
25
+ - @backstage/catalog-model@1.10.1
23
26
  - @backstage/errors@1.3.1
24
27
  - @backstage/theme@0.7.3
25
- - @backstage/plugin-search-common@0.0.0-nightly-20260909022715
26
28
  - @backstage/plugin-techdocs-common@0.1.1
27
29
 
30
+ ## 1.18.1
31
+
32
+ ### Patch Changes
33
+
34
+ - 736d84e: Use locale-insensitive Unicode casing for consistent string handling across environments.
35
+ - d421187: Reduced the initial app bundle size by loading page and optional UI implementations only when their extensions render.
36
+ - 9cb79f5: Use the catalog presentation API for TechDocs document titles and owner labels so entity display names are consistent with the rest of Backstage.
37
+ - Updated dependencies
38
+ - @backstage/core-components@0.18.14
39
+ - @backstage/integration@2.1.2
40
+ - @backstage/ui@0.18.0
41
+ - @backstage/catalog-client@1.16.2
42
+ - @backstage/catalog-model@1.10.1
43
+ - @backstage/plugin-catalog-react@3.2.3
44
+ - @backstage/plugin-techdocs-react@1.3.15
45
+ - @backstage/config@1.3.9
46
+ - @backstage/frontend-plugin-api@0.18.1
47
+ - @backstage/core-plugin-api@1.12.10
48
+ - @backstage/integration-react@1.2.22
49
+ - @backstage/plugin-auth-react@0.1.31
50
+ - @backstage/plugin-search-common@1.2.25
51
+ - @backstage/plugin-search-react@1.11.8
52
+
28
53
  ## 1.18.1-next.2
29
54
 
30
55
  ### Patch Changes
@@ -9,7 +9,8 @@ import { useEntityPageTechDocsRedirect } from './search/hooks/useTechDocsLocatio
9
9
 
10
10
  const EntityPageDocs = ({
11
11
  entity,
12
- withSearch = true
12
+ withSearch = true,
13
+ withFeedbackLink
13
14
  }) => {
14
15
  let entityRef = getCompoundEntityRef(entity);
15
16
  const searchResultUrlMapper = useEntityPageTechDocsRedirect(entityRef);
@@ -28,6 +29,7 @@ const EntityPageDocs = ({
28
29
  TechDocsReaderPageContent,
29
30
  {
30
31
  withSearch,
32
+ withFeedbackLink,
31
33
  searchResultUrlMapper,
32
34
  defaultPath
33
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EntityPageDocs.esm.js","sources":["../src/EntityPageDocs.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 {\n Entity,\n getCompoundEntityRef,\n parseEntityRef,\n} from '@backstage/catalog-model';\nimport { TECHDOCS_EXTERNAL_ANNOTATION } from '@backstage/plugin-techdocs-common';\nimport { getEntityRootTechDocsPath } from '@backstage/plugin-techdocs-react';\n\nimport { TechDocsReaderPage } from './plugin';\nimport { TechDocsReaderPageContent } from './reader/components/TechDocsReaderPageContent';\nimport { TechDocsReaderPageSubheader } from './reader/components/TechDocsReaderPageSubheader';\nimport { useEntityPageTechDocsRedirect } from './search/hooks/useTechDocsLocation';\n\ntype EntityPageDocsProps = {\n entity: Entity;\n /**\n * Show or hide the content search bar, defaults to true.\n */\n withSearch?: boolean;\n};\n\nexport const EntityPageDocs = ({\n entity,\n withSearch = true,\n}: EntityPageDocsProps) => {\n let entityRef = getCompoundEntityRef(entity);\n\n const searchResultUrlMapper = useEntityPageTechDocsRedirect(entityRef);\n\n if (entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]) {\n try {\n entityRef = parseEntityRef(\n entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION],\n );\n } catch {\n // not a fan of this but we don't care if the parseEntityRef fails\n }\n }\n\n const defaultPath = getEntityRootTechDocsPath(entity);\n\n return (\n <TechDocsReaderPage entityRef={entityRef}>\n <TechDocsReaderPageSubheader />\n <TechDocsReaderPageContent\n withSearch={withSearch}\n searchResultUrlMapper={searchResultUrlMapper}\n defaultPath={defaultPath}\n />\n </TechDocsReaderPage>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAqCO,MAAM,iBAAiB,CAAC;AAAA,EAC7B,MAAA;AAAA,EACA,UAAA,GAAa;AACf,CAAA,KAA2B;AACzB,EAAA,IAAI,SAAA,GAAY,qBAAqB,MAAM,CAAA;AAE3C,EAAA,MAAM,qBAAA,GAAwB,8BAA8B,SAAS,CAAA;AAErE,EAAA,IAAI,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,4BAA4B,CAAA,EAAG;AAC/D,IAAA,IAAI;AACF,MAAA,SAAA,GAAY,cAAA;AAAA,QACV,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,4BAA4B;AAAA,OAC5D;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,0BAA0B,MAAM,CAAA;AAEpD,EAAA,uBACE,IAAA,CAAC,sBAAmB,SAAA,EAClB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,2BAAA,EAAA,EAA4B,CAAA;AAAA,oBAC7B,GAAA;AAAA,MAAC,yBAAA;AAAA,MAAA;AAAA,QACC,UAAA;AAAA,QACA,qBAAA;AAAA,QACA;AAAA;AAAA;AACF,GAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"EntityPageDocs.esm.js","sources":["../src/EntityPageDocs.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 {\n Entity,\n getCompoundEntityRef,\n parseEntityRef,\n} from '@backstage/catalog-model';\nimport { TECHDOCS_EXTERNAL_ANNOTATION } from '@backstage/plugin-techdocs-common';\nimport { getEntityRootTechDocsPath } from '@backstage/plugin-techdocs-react';\n\nimport { TechDocsReaderPage } from './plugin';\nimport { TechDocsReaderPageContent } from './reader/components/TechDocsReaderPageContent';\nimport { TechDocsReaderPageSubheader } from './reader/components/TechDocsReaderPageSubheader';\nimport { useEntityPageTechDocsRedirect } from './search/hooks/useTechDocsLocation';\n\ntype EntityPageDocsProps = {\n entity: Entity;\n /**\n * Show or hide the content search bar, defaults to true.\n */\n withSearch?: boolean;\n /**\n * Show or hide the feedback button, defaults to true.\n */\n withFeedbackLink?: boolean;\n};\n\nexport const EntityPageDocs = ({\n entity,\n withSearch = true,\n withFeedbackLink,\n}: EntityPageDocsProps) => {\n let entityRef = getCompoundEntityRef(entity);\n\n const searchResultUrlMapper = useEntityPageTechDocsRedirect(entityRef);\n\n if (entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]) {\n try {\n entityRef = parseEntityRef(\n entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION],\n );\n } catch {\n // not a fan of this but we don't care if the parseEntityRef fails\n }\n }\n\n const defaultPath = getEntityRootTechDocsPath(entity);\n\n return (\n <TechDocsReaderPage entityRef={entityRef}>\n <TechDocsReaderPageSubheader />\n <TechDocsReaderPageContent\n withSearch={withSearch}\n withFeedbackLink={withFeedbackLink}\n searchResultUrlMapper={searchResultUrlMapper}\n defaultPath={defaultPath}\n />\n </TechDocsReaderPage>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;AAyCO,MAAM,iBAAiB,CAAC;AAAA,EAC7B,MAAA;AAAA,EACA,UAAA,GAAa,IAAA;AAAA,EACb;AACF,CAAA,KAA2B;AACzB,EAAA,IAAI,SAAA,GAAY,qBAAqB,MAAM,CAAA;AAE3C,EAAA,MAAM,qBAAA,GAAwB,8BAA8B,SAAS,CAAA;AAErE,EAAA,IAAI,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,4BAA4B,CAAA,EAAG;AAC/D,IAAA,IAAI;AACF,MAAA,SAAA,GAAY,cAAA;AAAA,QACV,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,4BAA4B;AAAA,OAC5D;AAAA,IACF,CAAA,CAAA,MAAQ;AAAA,IAER;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,0BAA0B,MAAM,CAAA;AAEpD,EAAA,uBACE,IAAA,CAAC,sBAAmB,SAAA,EAClB,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,2BAAA,EAAA,EAA4B,CAAA;AAAA,oBAC7B,GAAA;AAAA,MAAC,yBAAA;AAAA,MAAA;AAAA,QACC,UAAA;AAAA,QACA,gBAAA;AAAA,QACA,qBAAA;AAAA,QACA;AAAA;AAAA;AACF,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -36,12 +36,19 @@ const TechDocsReaderRouter = (props) => {
36
36
  return element;
37
37
  };
38
38
  const EmbeddedDocsRouter = (props) => {
39
- const { children, emptyState, withSearch = true } = props;
39
+ const { children, emptyState, withSearch = true, withFeedbackLink } = props;
40
40
  const { entity } = useEntity();
41
41
  const element = useRoutes([
42
42
  {
43
43
  path: "/*",
44
- element: /* @__PURE__ */ jsx(EntityPageDocs, { entity, withSearch }),
44
+ element: /* @__PURE__ */ jsx(
45
+ EntityPageDocs,
46
+ {
47
+ entity,
48
+ withSearch,
49
+ withFeedbackLink
50
+ }
51
+ ),
45
52
  children: [
46
53
  {
47
54
  path: "*",
@@ -1 +1 @@
1
- {"version":3,"file":"Router.esm.js","sources":["../src/Router.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 { ReactElement, PropsWithChildren } from 'react';\nimport { Route, Routes, useRoutes } from 'react-router-dom';\n\nimport { Entity } from '@backstage/catalog-model';\nimport { EntityPageDocs } from './EntityPageDocs';\nimport { TechDocsIndexPage } from './home/components/TechDocsIndexPage';\nimport { TechDocsReaderPage } from './reader/components/TechDocsReaderPage';\nimport {\n useEntity,\n MissingAnnotationEmptyState,\n} from '@backstage/plugin-catalog-react';\nimport {\n TECHDOCS_ANNOTATION,\n TECHDOCS_EXTERNAL_ANNOTATION,\n} from '@backstage/plugin-techdocs-common';\n\n/**\n * Helper that takes in entity and returns true/false if TechDocs is available for the entity\n *\n * @public\n */\nexport const isTechDocsAvailable = (entity: Entity) =>\n Boolean(entity?.metadata?.annotations?.[TECHDOCS_ANNOTATION]) ||\n Boolean(entity?.metadata?.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]);\n\n/**\n * Responsible for registering routes for TechDocs, TechDocs Homepage and separate TechDocs page\n *\n * @public\n */\nexport const Router = () => {\n return (\n <Routes>\n <Route path=\"/\" element={<TechDocsIndexPage />} />\n <Route\n path=\"/:namespace/:kind/:name/*\"\n element={<TechDocsReaderPage />}\n />\n </Routes>\n );\n};\n\nexport const TechDocsReaderRouter = (props: PropsWithChildren) => {\n const { children } = props;\n\n // Using objects instead of <Route> elements, otherwise \"outlet\" will be null on sub-pages and add-ons won't render\n const element = useRoutes([\n {\n path: '*',\n element: <TechDocsReaderPage />,\n children: [\n {\n path: '*',\n element: children,\n },\n ],\n },\n ]);\n\n return element;\n};\n\nexport const EmbeddedDocsRouter = (\n props: PropsWithChildren<{\n emptyState?: ReactElement;\n withSearch?: boolean;\n }>,\n) => {\n const { children, emptyState, withSearch = true } = props;\n const { entity } = useEntity();\n\n // Using objects instead of <Route> elements, otherwise \"outlet\" will be null on sub-pages and add-ons won't render\n const element = useRoutes([\n {\n path: '/*',\n element: <EntityPageDocs entity={entity} withSearch={withSearch} />,\n children: [\n {\n path: '*',\n element: children,\n },\n ],\n },\n ]);\n\n const projectId =\n entity.metadata.annotations?.[TECHDOCS_ANNOTATION] ||\n entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION];\n\n if (!projectId) {\n return (\n emptyState ?? (\n <MissingAnnotationEmptyState annotation={[TECHDOCS_ANNOTATION]} />\n )\n );\n }\n return element;\n};\n\n/**\n * Responsible for registering route to view docs on Entity page\n *\n * @public\n */\nexport const LegacyEmbeddedDocsRouter = ({\n children,\n withSearch = true,\n}: PropsWithChildren<{ withSearch?: boolean }>) => {\n // Wrap the Router to avoid exposing the emptyState prop in the non-alpha\n // public API and make it easier for us to change later.\n return <EmbeddedDocsRouter children={children} withSearch={withSearch} />;\n};\n"],"names":[],"mappings":";;;;;;;;AAqCO,MAAM,mBAAA,GAAsB,CAAC,MAAA,KAClC,OAAA,CAAQ,QAAQ,QAAA,EAAU,WAAA,GAAc,mBAAmB,CAAC,KAC5D,OAAA,CAAQ,MAAA,EAAQ,QAAA,EAAU,WAAA,GAAc,4BAA4B,CAAC;AAOhE,MAAM,SAAS,MAAM;AAC1B,EAAA,4BACG,MAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,SAAM,IAAA,EAAK,GAAA,EAAI,OAAA,kBAAS,GAAA,CAAC,qBAAkB,CAAA,EAAI,CAAA;AAAA,oBAChD,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,2BAAA;AAAA,QACL,OAAA,sBAAU,kBAAA,EAAA,EAAmB;AAAA;AAAA;AAC/B,GAAA,EACF,CAAA;AAEJ;AAEO,MAAM,oBAAA,GAAuB,CAAC,KAAA,KAA6B;AAChE,EAAA,MAAM,EAAE,UAAS,GAAI,KAAA;AAGrB,EAAA,MAAM,UAAU,SAAA,CAAU;AAAA,IACxB;AAAA,MACE,IAAA,EAAM,GAAA;AAAA,MACN,OAAA,sBAAU,kBAAA,EAAA,EAAmB,CAAA;AAAA,MAC7B,QAAA,EAAU;AAAA,QACR;AAAA,UACE,IAAA,EAAM,GAAA;AAAA,UACN,OAAA,EAAS;AAAA;AACX;AACF;AACF,GACD,CAAA;AAED,EAAA,OAAO,OAAA;AACT;AAEO,MAAM,kBAAA,GAAqB,CAChC,KAAA,KAIG;AACH,EAAA,MAAM,EAAE,QAAA,EAAU,UAAA,EAAY,UAAA,GAAa,MAAK,GAAI,KAAA;AACpD,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,SAAA,EAAU;AAG7B,EAAA,MAAM,UAAU,SAAA,CAAU;AAAA,IACxB;AAAA,MACE,IAAA,EAAM,IAAA;AAAA,MACN,OAAA,kBAAS,GAAA,CAAC,cAAA,EAAA,EAAe,MAAA,EAAgB,UAAA,EAAwB,CAAA;AAAA,MACjE,QAAA,EAAU;AAAA,QACR;AAAA,UACE,IAAA,EAAM,GAAA;AAAA,UACN,OAAA,EAAS;AAAA;AACX;AACF;AACF,GACD,CAAA;AAED,EAAA,MAAM,SAAA,GACJ,OAAO,QAAA,CAAS,WAAA,GAAc,mBAAmB,CAAA,IACjD,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,4BAA4B,CAAA;AAE5D,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,OACE,8BACE,GAAA,CAAC,2BAAA,EAAA,EAA4B,UAAA,EAAY,CAAC,mBAAmB,CAAA,EAAG,CAAA;AAAA,EAGtE;AACA,EAAA,OAAO,OAAA;AACT;AAOO,MAAM,2BAA2B,CAAC;AAAA,EACvC,QAAA;AAAA,EACA,UAAA,GAAa;AACf,CAAA,KAAmD;AAGjD,EAAA,uBAAO,GAAA,CAAC,kBAAA,EAAA,EAAmB,QAAA,EAAoB,UAAA,EAAwB,CAAA;AACzE;;;;"}
1
+ {"version":3,"file":"Router.esm.js","sources":["../src/Router.tsx"],"sourcesContent":["/*\n * Copyright 2020 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 { ReactElement, PropsWithChildren } from 'react';\nimport { Route, Routes, useRoutes } from 'react-router-dom';\n\nimport { Entity } from '@backstage/catalog-model';\nimport { EntityPageDocs } from './EntityPageDocs';\nimport { TechDocsIndexPage } from './home/components/TechDocsIndexPage';\nimport { TechDocsReaderPage } from './reader/components/TechDocsReaderPage';\nimport {\n useEntity,\n MissingAnnotationEmptyState,\n} from '@backstage/plugin-catalog-react';\nimport {\n TECHDOCS_ANNOTATION,\n TECHDOCS_EXTERNAL_ANNOTATION,\n} from '@backstage/plugin-techdocs-common';\n\n/**\n * Helper that takes in entity and returns true/false if TechDocs is available for the entity\n *\n * @public\n */\nexport const isTechDocsAvailable = (entity: Entity) =>\n Boolean(entity?.metadata?.annotations?.[TECHDOCS_ANNOTATION]) ||\n Boolean(entity?.metadata?.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]);\n\n/**\n * Responsible for registering routes for TechDocs, TechDocs Homepage and separate TechDocs page\n *\n * @public\n */\nexport const Router = () => {\n return (\n <Routes>\n <Route path=\"/\" element={<TechDocsIndexPage />} />\n <Route\n path=\"/:namespace/:kind/:name/*\"\n element={<TechDocsReaderPage />}\n />\n </Routes>\n );\n};\n\nexport const TechDocsReaderRouter = (props: PropsWithChildren) => {\n const { children } = props;\n\n // Using objects instead of <Route> elements, otherwise \"outlet\" will be null on sub-pages and add-ons won't render\n const element = useRoutes([\n {\n path: '*',\n element: <TechDocsReaderPage />,\n children: [\n {\n path: '*',\n element: children,\n },\n ],\n },\n ]);\n\n return element;\n};\n\nexport const EmbeddedDocsRouter = (\n props: PropsWithChildren<{\n emptyState?: ReactElement;\n withSearch?: boolean;\n withFeedbackLink?: boolean;\n }>,\n) => {\n const { children, emptyState, withSearch = true, withFeedbackLink } = props;\n const { entity } = useEntity();\n\n // Using objects instead of <Route> elements, otherwise \"outlet\" will be null on sub-pages and add-ons won't render\n const element = useRoutes([\n {\n path: '/*',\n element: (\n <EntityPageDocs\n entity={entity}\n withSearch={withSearch}\n withFeedbackLink={withFeedbackLink}\n />\n ),\n children: [\n {\n path: '*',\n element: children,\n },\n ],\n },\n ]);\n\n const projectId =\n entity.metadata.annotations?.[TECHDOCS_ANNOTATION] ||\n entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION];\n\n if (!projectId) {\n return (\n emptyState ?? (\n <MissingAnnotationEmptyState annotation={[TECHDOCS_ANNOTATION]} />\n )\n );\n }\n return element;\n};\n\n/**\n * Responsible for registering route to view docs on Entity page\n *\n * @public\n */\nexport const LegacyEmbeddedDocsRouter = ({\n children,\n withSearch = true,\n}: PropsWithChildren<{ withSearch?: boolean }>) => {\n // Wrap the Router to avoid exposing the emptyState prop in the non-alpha\n // public API and make it easier for us to change later.\n return <EmbeddedDocsRouter children={children} withSearch={withSearch} />;\n};\n"],"names":[],"mappings":";;;;;;;;AAqCO,MAAM,mBAAA,GAAsB,CAAC,MAAA,KAClC,OAAA,CAAQ,QAAQ,QAAA,EAAU,WAAA,GAAc,mBAAmB,CAAC,KAC5D,OAAA,CAAQ,MAAA,EAAQ,QAAA,EAAU,WAAA,GAAc,4BAA4B,CAAC;AAOhE,MAAM,SAAS,MAAM;AAC1B,EAAA,4BACG,MAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,SAAM,IAAA,EAAK,GAAA,EAAI,OAAA,kBAAS,GAAA,CAAC,qBAAkB,CAAA,EAAI,CAAA;AAAA,oBAChD,GAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,2BAAA;AAAA,QACL,OAAA,sBAAU,kBAAA,EAAA,EAAmB;AAAA;AAAA;AAC/B,GAAA,EACF,CAAA;AAEJ;AAEO,MAAM,oBAAA,GAAuB,CAAC,KAAA,KAA6B;AAChE,EAAA,MAAM,EAAE,UAAS,GAAI,KAAA;AAGrB,EAAA,MAAM,UAAU,SAAA,CAAU;AAAA,IACxB;AAAA,MACE,IAAA,EAAM,GAAA;AAAA,MACN,OAAA,sBAAU,kBAAA,EAAA,EAAmB,CAAA;AAAA,MAC7B,QAAA,EAAU;AAAA,QACR;AAAA,UACE,IAAA,EAAM,GAAA;AAAA,UACN,OAAA,EAAS;AAAA;AACX;AACF;AACF,GACD,CAAA;AAED,EAAA,OAAO,OAAA;AACT;AAEO,MAAM,kBAAA,GAAqB,CAChC,KAAA,KAKG;AACH,EAAA,MAAM,EAAE,QAAA,EAAU,UAAA,EAAY,UAAA,GAAa,IAAA,EAAM,kBAAiB,GAAI,KAAA;AACtE,EAAA,MAAM,EAAE,MAAA,EAAO,GAAI,SAAA,EAAU;AAG7B,EAAA,MAAM,UAAU,SAAA,CAAU;AAAA,IACxB;AAAA,MACE,IAAA,EAAM,IAAA;AAAA,MACN,OAAA,kBACE,GAAA;AAAA,QAAC,cAAA;AAAA,QAAA;AAAA,UACC,MAAA;AAAA,UACA,UAAA;AAAA,UACA;AAAA;AAAA,OACF;AAAA,MAEF,QAAA,EAAU;AAAA,QACR;AAAA,UACE,IAAA,EAAM,GAAA;AAAA,UACN,OAAA,EAAS;AAAA;AACX;AACF;AACF,GACD,CAAA;AAED,EAAA,MAAM,SAAA,GACJ,OAAO,QAAA,CAAS,WAAA,GAAc,mBAAmB,CAAA,IACjD,MAAA,CAAO,QAAA,CAAS,WAAA,GAAc,4BAA4B,CAAA;AAE5D,EAAA,IAAI,CAAC,SAAA,EAAW;AACd,IAAA,OACE,8BACE,GAAA,CAAC,2BAAA,EAAA,EAA4B,UAAA,EAAY,CAAC,mBAAmB,CAAA,EAAG,CAAA;AAAA,EAGtE;AACA,EAAA,OAAO,OAAA;AACT;AAOO,MAAM,2BAA2B,CAAC;AAAA,EACvC,QAAA;AAAA,EACA,UAAA,GAAa;AACf,CAAA,KAAmD;AAGjD,EAAA,uBAAO,GAAA,CAAC,kBAAA,EAAA,EAAmB,QAAA,EAAoB,UAAA,EAAwB,CAAA;AACzE;;;;"}
@@ -17,7 +17,8 @@ const TechDocsReaderContent = withTechDocsReaderProvider(
17
17
  NotFoundErrorPage
18
18
  } = useTechDocsReaderContentData({
19
19
  defaultPath: props.defaultPath,
20
- onReady: props.onReady
20
+ onReady: props.onReady,
21
+ withFeedbackLink: props.withFeedbackLink
21
22
  });
22
23
  if (isNotFound) return /* @__PURE__ */ jsx(NotFoundErrorPage, {});
23
24
  if (!isDomReady) {
@@ -1 +1 @@
1
- {"version":3,"file":"TechDocsReaderContent.esm.js","sources":["../../../src/alpha/components/TechDocsReaderContent.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { TechDocsShadowDom } from '@backstage/plugin-techdocs-react';\nimport { Progress } from '@backstage/core-components';\n\nimport { TechDocsStateIndicator } from '../../reader/components/TechDocsStateIndicator';\nimport { withTechDocsReaderProvider } from '../../reader/components/TechDocsReaderProvider';\nimport { TechDocsReaderPageContentAddons } from '../../reader/components/TechDocsReaderPageContent/TechDocsReaderPageContentAddons';\nimport type { TechDocsReaderPageContentProps } from '../../reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent';\nimport { useTechDocsReaderContentData } from '../../hooks/useTechDocsReaderContentData';\n\nexport const TechDocsReaderContent = withTechDocsReaderProvider(\n (props: TechDocsReaderPageContentProps) => {\n const {\n dom,\n handleAppend,\n isNotFound,\n isDomReady,\n showProgress,\n NotFoundErrorPage,\n } = useTechDocsReaderContentData({\n defaultPath: props.defaultPath,\n onReady: props.onReady,\n });\n\n if (isNotFound) return <NotFoundErrorPage />;\n\n if (!isDomReady) {\n return <TechDocsStateIndicator />;\n }\n\n return (\n <>\n <TechDocsStateIndicator />\n {showProgress && <Progress />}\n <TechDocsShadowDom element={dom!} onAppend={handleAppend}>\n <TechDocsReaderPageContentAddons />\n </TechDocsShadowDom>\n </>\n );\n },\n);\n"],"names":[],"mappings":";;;;;;;;AAyBO,MAAM,qBAAA,GAAwB,0BAAA;AAAA,EACnC,CAAC,KAAA,KAA0C;AACzC,IAAA,MAAM;AAAA,MACJ,GAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,QACE,4BAAA,CAA6B;AAAA,MAC/B,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,SAAS,KAAA,CAAM;AAAA,KAChB,CAAA;AAED,IAAA,IAAI,UAAA,EAAY,uBAAO,GAAA,CAAC,iBAAA,EAAA,EAAkB,CAAA;AAE1C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,2BAAQ,sBAAA,EAAA,EAAuB,CAAA;AAAA,IACjC;AAEA,IAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,sBAAA,EAAA,EAAuB,CAAA;AAAA,MACvB,YAAA,wBAAiB,QAAA,EAAA,EAAS,CAAA;AAAA,sBAC3B,GAAA,CAAC,qBAAkB,OAAA,EAAS,GAAA,EAAM,UAAU,YAAA,EAC1C,QAAA,kBAAA,GAAA,CAAC,mCAAgC,CAAA,EACnC;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AACF;;;;"}
1
+ {"version":3,"file":"TechDocsReaderContent.esm.js","sources":["../../../src/alpha/components/TechDocsReaderContent.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { TechDocsShadowDom } from '@backstage/plugin-techdocs-react';\nimport { Progress } from '@backstage/core-components';\n\nimport { TechDocsStateIndicator } from '../../reader/components/TechDocsStateIndicator';\nimport { withTechDocsReaderProvider } from '../../reader/components/TechDocsReaderProvider';\nimport { TechDocsReaderPageContentAddons } from '../../reader/components/TechDocsReaderPageContent/TechDocsReaderPageContentAddons';\nimport type { TechDocsReaderPageContentProps } from '../../reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent';\nimport { useTechDocsReaderContentData } from '../../hooks/useTechDocsReaderContentData';\n\nexport const TechDocsReaderContent = withTechDocsReaderProvider(\n (props: TechDocsReaderPageContentProps) => {\n const {\n dom,\n handleAppend,\n isNotFound,\n isDomReady,\n showProgress,\n NotFoundErrorPage,\n } = useTechDocsReaderContentData({\n defaultPath: props.defaultPath,\n onReady: props.onReady,\n withFeedbackLink: props.withFeedbackLink,\n });\n\n if (isNotFound) return <NotFoundErrorPage />;\n\n if (!isDomReady) {\n return <TechDocsStateIndicator />;\n }\n\n return (\n <>\n <TechDocsStateIndicator />\n {showProgress && <Progress />}\n <TechDocsShadowDom element={dom!} onAppend={handleAppend}>\n <TechDocsReaderPageContentAddons />\n </TechDocsShadowDom>\n </>\n );\n },\n);\n"],"names":[],"mappings":";;;;;;;;AAyBO,MAAM,qBAAA,GAAwB,0BAAA;AAAA,EACnC,CAAC,KAAA,KAA0C;AACzC,IAAA,MAAM;AAAA,MACJ,GAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,QACE,4BAAA,CAA6B;AAAA,MAC/B,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,kBAAkB,KAAA,CAAM;AAAA,KACzB,CAAA;AAED,IAAA,IAAI,UAAA,EAAY,uBAAO,GAAA,CAAC,iBAAA,EAAA,EAAkB,CAAA;AAE1C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,2BAAQ,sBAAA,EAAA,EAAuB,CAAA;AAAA,IACjC;AAEA,IAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,sBAAA,EAAA,EAAuB,CAAA;AAAA,MACvB,YAAA,wBAAiB,QAAA,EAAA,EAAS,CAAA;AAAA,sBAC3B,GAAA,CAAC,qBAAkB,OAAA,EAAS,GAAA,EAAM,UAAU,YAAA,EAC1C,QAAA,kBAAA,GAAA,CAAC,mCAAgC,CAAA,EACnC;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AACF;;;;"}
@@ -6,13 +6,13 @@ import { TechDocsReaderPageSubheader } from '../../reader/components/TechDocsRea
6
6
  import { TechDocsReaderContent } from './TechDocsReaderContent.esm.js';
7
7
 
8
8
  const TechDocsReaderLayout = (props) => {
9
- const { withSearch, withHeader = true } = props;
9
+ const { withSearch, withHeader = true, withFeedbackLink } = props;
10
10
  return /* @__PURE__ */ jsxs(Fragment, { children: [
11
11
  withHeader && /* @__PURE__ */ jsx(TechDocsReaderHeader, { withSearch }),
12
12
  /* @__PURE__ */ jsxs(Container, { mt: "6", children: [
13
13
  /* @__PURE__ */ jsx(TechDocsReaderEntityCard, { withSearch: !withHeader && withSearch }),
14
14
  /* @__PURE__ */ jsx(TechDocsReaderPageSubheader, {}),
15
- /* @__PURE__ */ jsx(TechDocsReaderContent, {})
15
+ /* @__PURE__ */ jsx(TechDocsReaderContent, { withFeedbackLink })
16
16
  ] })
17
17
  ] });
18
18
  };
@@ -1 +1 @@
1
- {"version":3,"file":"TechDocsReaderLayout.esm.js","sources":["../../../src/alpha/components/TechDocsReaderLayout.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { Container } from '@backstage/ui';\nimport { TechDocsReaderHeader } from './TechDocsReaderHeader';\nimport { TechDocsReaderEntityCard } from './TechDocsReaderEntityCard';\nimport { TechDocsReaderPageSubheader } from '../../reader/components/TechDocsReaderPageSubheader';\nimport { TechDocsReaderContent } from './TechDocsReaderContent';\n\nexport type TechDocsReaderLayoutProps = {\n withHeader?: boolean;\n withSearch?: boolean;\n};\n\nexport const TechDocsReaderLayout = (props: TechDocsReaderLayoutProps) => {\n const { withSearch, withHeader = true } = props;\n return (\n <>\n {withHeader && <TechDocsReaderHeader withSearch={withSearch} />}\n <Container mt=\"6\">\n <TechDocsReaderEntityCard withSearch={!withHeader && withSearch} />\n <TechDocsReaderPageSubheader />\n <TechDocsReaderContent />\n </Container>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;AA2BO,MAAM,oBAAA,GAAuB,CAAC,KAAA,KAAqC;AACxE,EAAA,MAAM,EAAE,UAAA,EAAY,UAAA,GAAa,IAAA,EAAK,GAAI,KAAA;AAC1C,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,UAAA,oBAAc,GAAA,CAAC,wBAAqB,UAAA,EAAwB,CAAA;AAAA,oBAC7D,IAAA,CAAC,SAAA,EAAA,EAAU,EAAA,EAAG,GAAA,EACZ,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,wBAAA,EAAA,EAAyB,UAAA,EAAY,CAAC,UAAA,IAAc,UAAA,EAAY,CAAA;AAAA,0BAChE,2BAAA,EAAA,EAA4B,CAAA;AAAA,0BAC5B,qBAAA,EAAA,EAAsB;AAAA,KAAA,EACzB;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"TechDocsReaderLayout.esm.js","sources":["../../../src/alpha/components/TechDocsReaderLayout.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { Container } from '@backstage/ui';\nimport { TechDocsReaderHeader } from './TechDocsReaderHeader';\nimport { TechDocsReaderEntityCard } from './TechDocsReaderEntityCard';\nimport { TechDocsReaderPageSubheader } from '../../reader/components/TechDocsReaderPageSubheader';\nimport { TechDocsReaderContent } from './TechDocsReaderContent';\n\nexport type TechDocsReaderLayoutProps = {\n withHeader?: boolean;\n withSearch?: boolean;\n withFeedbackLink?: boolean;\n};\n\nexport const TechDocsReaderLayout = (props: TechDocsReaderLayoutProps) => {\n const { withSearch, withHeader = true, withFeedbackLink } = props;\n return (\n <>\n {withHeader && <TechDocsReaderHeader withSearch={withSearch} />}\n <Container mt=\"6\">\n <TechDocsReaderEntityCard withSearch={!withHeader && withSearch} />\n <TechDocsReaderPageSubheader />\n <TechDocsReaderContent withFeedbackLink={withFeedbackLink} />\n </Container>\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;AA4BO,MAAM,oBAAA,GAAuB,CAAC,KAAA,KAAqC;AACxE,EAAA,MAAM,EAAE,UAAA,EAAY,UAAA,GAAa,IAAA,EAAM,kBAAiB,GAAI,KAAA;AAC5D,EAAA,uBACE,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,UAAA,oBAAc,GAAA,CAAC,wBAAqB,UAAA,EAAwB,CAAA;AAAA,oBAC7D,IAAA,CAAC,SAAA,EAAA,EAAU,EAAA,EAAG,GAAA,EACZ,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,wBAAA,EAAA,EAAyB,UAAA,EAAY,CAAC,UAAA,IAAc,UAAA,EAAY,CAAA;AAAA,0BAChE,2BAAA,EAAA,EAA4B,CAAA;AAAA,sBAC7B,GAAA,CAAC,yBAAsB,gBAAA,EAAoC;AAAA,KAAA,EAC7D;AAAA,GAAA,EACF,CAAA;AAEJ;;;;"}
@@ -18,14 +18,22 @@ function TechDocsReaderPage(props) {
18
18
  TechDocsReaderLayout,
19
19
  {
20
20
  withSearch: props.withSearch,
21
- withHeader: props.withHeader
21
+ withHeader: props.withHeader,
22
+ withFeedbackLink: props.withFeedbackLink
22
23
  }
23
24
  ),
24
25
  /* @__PURE__ */ jsx(Addons, { options: props.addonOptions })
25
26
  ] });
26
27
  }
27
28
  function TechDocsEntityContent(props) {
28
- return /* @__PURE__ */ jsx(EmbeddedDocsRouter, { emptyState: props.emptyState, children: /* @__PURE__ */ jsx(Addons, { options: props.addonOptions }) });
29
+ return /* @__PURE__ */ jsx(
30
+ EmbeddedDocsRouter,
31
+ {
32
+ emptyState: props.emptyState,
33
+ withFeedbackLink: props.withFeedbackLink,
34
+ children: /* @__PURE__ */ jsx(Addons, { options: props.addonOptions })
35
+ }
36
+ );
29
37
  }
30
38
 
31
39
  export { TechDocsEntityContent, TechDocsReaderPage };
@@ -1 +1 @@
1
- {"version":3,"file":"TechDocsReaderPage.esm.js","sources":["../../../src/alpha/components/TechDocsReaderPage.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { ReactElement, Suspense } from 'react';\nimport {\n TechDocsAddons,\n type TechDocsAddonOptions,\n} from '@backstage/plugin-techdocs-react';\nimport { attachTechDocsAddonComponentData } from '@backstage/plugin-techdocs-react/alpha';\nimport { EmbeddedDocsRouter, TechDocsReaderRouter } from '../../Router';\nimport { TechDocsReaderLayout } from './TechDocsReaderLayout';\n\nfunction Addons(props: { options: TechDocsAddonOptions[] }) {\n return (\n <TechDocsAddons>\n {props.options.map(options => {\n const Addon = options.component;\n attachTechDocsAddonComponentData(Addon, options);\n return (\n <Suspense key={options.name} fallback={null}>\n <Addon />\n </Suspense>\n );\n })}\n </TechDocsAddons>\n );\n}\n\nexport function TechDocsReaderPage(props: {\n addonOptions: TechDocsAddonOptions[];\n withSearch: boolean;\n withHeader: boolean;\n}) {\n return (\n <TechDocsReaderRouter>\n <TechDocsReaderLayout\n withSearch={props.withSearch}\n withHeader={props.withHeader}\n />\n <Addons options={props.addonOptions} />\n </TechDocsReaderRouter>\n );\n}\n\nexport function TechDocsEntityContent(props: {\n addonOptions: TechDocsAddonOptions[];\n emptyState?: ReactElement;\n}) {\n return (\n <EmbeddedDocsRouter emptyState={props.emptyState}>\n <Addons options={props.addonOptions} />\n </EmbeddedDocsRouter>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAyBA,SAAS,OAAO,KAAA,EAA4C;AAC1D,EAAA,uBACE,GAAA,CAAC,cAAA,EAAA,EACE,QAAA,EAAA,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,OAAA,KAAW;AAC5B,IAAA,MAAM,QAAQ,OAAA,CAAQ,SAAA;AACtB,IAAA,gCAAA,CAAiC,OAAO,OAAO,CAAA;AAC/C,IAAA,uBACE,GAAA,CAAC,YAA4B,QAAA,EAAU,IAAA,EACrC,8BAAC,KAAA,EAAA,EAAM,CAAA,EAAA,EADM,QAAQ,IAEvB,CAAA;AAAA,EAEJ,CAAC,CAAA,EACH,CAAA;AAEJ;AAEO,SAAS,mBAAmB,KAAA,EAIhC;AACD,EAAA,4BACG,oBAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,oBAAA;AAAA,MAAA;AAAA,QACC,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,YAAY,KAAA,CAAM;AAAA;AAAA,KACpB;AAAA,oBACA,GAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAS,KAAA,CAAM,YAAA,EAAc;AAAA,GAAA,EACvC,CAAA;AAEJ;AAEO,SAAS,sBAAsB,KAAA,EAGnC;AACD,EAAA,uBACE,GAAA,CAAC,kBAAA,EAAA,EAAmB,UAAA,EAAY,KAAA,CAAM,UAAA,EACpC,8BAAC,MAAA,EAAA,EAAO,OAAA,EAAS,KAAA,CAAM,YAAA,EAAc,CAAA,EACvC,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"TechDocsReaderPage.esm.js","sources":["../../../src/alpha/components/TechDocsReaderPage.tsx"],"sourcesContent":["/*\n * Copyright 2026 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 { ReactElement, Suspense } from 'react';\nimport {\n TechDocsAddons,\n type TechDocsAddonOptions,\n} from '@backstage/plugin-techdocs-react';\nimport { attachTechDocsAddonComponentData } from '@backstage/plugin-techdocs-react/alpha';\nimport { EmbeddedDocsRouter, TechDocsReaderRouter } from '../../Router';\nimport { TechDocsReaderLayout } from './TechDocsReaderLayout';\n\nfunction Addons(props: { options: TechDocsAddonOptions[] }) {\n return (\n <TechDocsAddons>\n {props.options.map(options => {\n const Addon = options.component;\n attachTechDocsAddonComponentData(Addon, options);\n return (\n <Suspense key={options.name} fallback={null}>\n <Addon />\n </Suspense>\n );\n })}\n </TechDocsAddons>\n );\n}\n\nexport function TechDocsReaderPage(props: {\n addonOptions: TechDocsAddonOptions[];\n withSearch: boolean;\n withHeader: boolean;\n withFeedbackLink: boolean;\n}) {\n return (\n <TechDocsReaderRouter>\n <TechDocsReaderLayout\n withSearch={props.withSearch}\n withHeader={props.withHeader}\n withFeedbackLink={props.withFeedbackLink}\n />\n <Addons options={props.addonOptions} />\n </TechDocsReaderRouter>\n );\n}\n\nexport function TechDocsEntityContent(props: {\n addonOptions: TechDocsAddonOptions[];\n emptyState?: ReactElement;\n withFeedbackLink: boolean;\n}) {\n return (\n <EmbeddedDocsRouter\n emptyState={props.emptyState}\n withFeedbackLink={props.withFeedbackLink}\n >\n <Addons options={props.addonOptions} />\n </EmbeddedDocsRouter>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAyBA,SAAS,OAAO,KAAA,EAA4C;AAC1D,EAAA,uBACE,GAAA,CAAC,cAAA,EAAA,EACE,QAAA,EAAA,KAAA,CAAM,OAAA,CAAQ,IAAI,CAAA,OAAA,KAAW;AAC5B,IAAA,MAAM,QAAQ,OAAA,CAAQ,SAAA;AACtB,IAAA,gCAAA,CAAiC,OAAO,OAAO,CAAA;AAC/C,IAAA,uBACE,GAAA,CAAC,YAA4B,QAAA,EAAU,IAAA,EACrC,8BAAC,KAAA,EAAA,EAAM,CAAA,EAAA,EADM,QAAQ,IAEvB,CAAA;AAAA,EAEJ,CAAC,CAAA,EACH,CAAA;AAEJ;AAEO,SAAS,mBAAmB,KAAA,EAKhC;AACD,EAAA,4BACG,oBAAA,EAAA,EACC,QAAA,EAAA;AAAA,oBAAA,GAAA;AAAA,MAAC,oBAAA;AAAA,MAAA;AAAA,QACC,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,YAAY,KAAA,CAAM,UAAA;AAAA,QAClB,kBAAkB,KAAA,CAAM;AAAA;AAAA,KAC1B;AAAA,oBACA,GAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAS,KAAA,CAAM,YAAA,EAAc;AAAA,GAAA,EACvC,CAAA;AAEJ;AAEO,SAAS,sBAAsB,KAAA,EAInC;AACD,EAAA,uBACE,GAAA;AAAA,IAAC,kBAAA;AAAA,IAAA;AAAA,MACC,YAAY,KAAA,CAAM,UAAA;AAAA,MAClB,kBAAkB,KAAA,CAAM,gBAAA;AAAA,MAExB,QAAA,kBAAA,GAAA,CAAC,MAAA,EAAA,EAAO,OAAA,EAAS,KAAA,CAAM,YAAA,EAAc;AAAA;AAAA,GACvC;AAEJ;;;;"}
package/dist/alpha.d.ts CHANGED
@@ -140,6 +140,7 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
140
140
  }>;
141
141
  "entity-content:techdocs": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
142
142
  config: {
143
+ withoutFeedbackLink: boolean;
143
144
  path: string | undefined;
144
145
  title: string | undefined;
145
146
  filter: _backstage_filter_predicates.FilterPredicate | undefined;
@@ -147,6 +148,7 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
147
148
  icon: string | undefined;
148
149
  };
149
150
  configInput: {
151
+ withoutFeedbackLink?: boolean | undefined;
150
152
  path?: string | undefined;
151
153
  title?: string | undefined;
152
154
  filter?: _backstage_filter_predicates.FilterPredicate | undefined;
@@ -263,12 +265,14 @@ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin
263
265
  config: {
264
266
  withoutSearch: boolean;
265
267
  withoutHeader: boolean;
268
+ withoutFeedbackLink: boolean;
266
269
  path: string | undefined;
267
270
  title: string | undefined;
268
271
  };
269
272
  configInput: {
270
273
  withoutSearch?: boolean | undefined;
271
274
  withoutHeader?: boolean | undefined;
275
+ withoutFeedbackLink?: boolean | undefined;
272
276
  path?: string | undefined;
273
277
  title?: string | undefined;
274
278
  };
package/dist/alpha.esm.js CHANGED
@@ -97,7 +97,8 @@ const techDocsReaderPage = PageBlueprint.makeWithOverrides({
97
97
  },
98
98
  configSchema: {
99
99
  withoutSearch: z.boolean().default(false),
100
- withoutHeader: z.boolean().default(false)
100
+ withoutHeader: z.boolean().default(false),
101
+ withoutFeedbackLink: z.boolean().default(false)
101
102
  },
102
103
  factory(originalFactory, { apis, inputs, config }) {
103
104
  const addonsApi = apis.get(techdocsAddonsApiRef);
@@ -116,7 +117,8 @@ const techDocsReaderPage = PageBlueprint.makeWithOverrides({
116
117
  {
117
118
  addonOptions,
118
119
  withSearch: !config.withoutSearch,
119
- withHeader: !config.withoutHeader
120
+ withHeader: !config.withoutHeader,
121
+ withFeedbackLink: !config.withoutFeedbackLink
120
122
  }
121
123
  );
122
124
  }
@@ -124,6 +126,9 @@ const techDocsReaderPage = PageBlueprint.makeWithOverrides({
124
126
  }
125
127
  });
126
128
  const techDocsEntityContent = EntityContentBlueprint.makeWithOverrides({
129
+ configSchema: {
130
+ withoutFeedbackLink: z.boolean().default(false)
131
+ },
127
132
  inputs: {
128
133
  addons: createExtensionInput([AddonBlueprint.dataRefs.addon]),
129
134
  emptyState: createExtensionInput(
@@ -154,7 +159,8 @@ const techDocsEntityContent = EntityContentBlueprint.makeWithOverrides({
154
159
  addonOptions,
155
160
  emptyState: context.inputs.emptyState?.get(
156
161
  coreExtensionData.reactElement
157
- )
162
+ ),
163
+ withFeedbackLink: !context.config.withoutFeedbackLink
158
164
  }
159
165
  ));
160
166
  }
@@ -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 { z } from 'zod/v4';\nimport { RiArticleLine } from '@remixicon/react';\nimport {\n createFrontendPlugin,\n ApiBlueprint,\n PageBlueprint,\n PluginHeaderActionBlueprint,\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 EntityContentBlueprint,\n EntityIconLinkBlueprint,\n} from '@backstage/plugin-catalog-react/alpha';\nimport {\n SearchFilterResultTypeBlueprint,\n SearchResultListItemBlueprint,\n} from '@backstage/plugin-search-react/alpha';\nimport { AddonBlueprint } from '@backstage/plugin-techdocs-react/alpha';\nimport { TechDocsAddonsApiExtension, techdocsAddonsApiRef } from './addonsApi';\nimport { TechDocsClient, TechDocsStorageClient } from '../client';\nimport {\n rootCatalogDocsRouteRef,\n rootDocsRouteRef,\n rootRouteRef,\n} from '../routes';\nimport {\n techdocsApiRef,\n techdocsStorageApiRef,\n} from '@backstage/plugin-techdocs-react';\n\nimport { useTechdocsReaderIconLinkProps } from './hooks/useTechdocsReaderIconLinkProps';\nimport { DocsIcon } from '@backstage/core-components';\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 configSchema: {\n title: z.string().optional(),\n lineClamp: z.number().default(5),\n asLink: z.boolean().default(true),\n asListItem: z.boolean().default(true),\n },\n factory(originalFactory, { config }) {\n return originalFactory({\n icon: <DocsIcon />,\n predicate: result => result.type === 'techdocs',\n component: async () => {\n const { TechDocsSearchResultListItem } = await import(\n '../search/components/TechDocsSearchResultListItem'\n );\n return props => (\n <TechDocsSearchResultListItem {...props} {...config} />\n );\n },\n });\n },\n });\n\nconst techDocsSearchFilterResultTypeExtension =\n SearchFilterResultTypeBlueprint.make({\n params: {\n value: 'techdocs',\n name: 'Documentation',\n icon: <DocsIcon />,\n },\n });\n\n/**\n * Responsible for rendering the provided router element\n *\n * @alpha\n */\nconst techDocsPage = PageBlueprint.makeWithOverrides({\n configSchema: {\n initialFilter: z.enum(['all', 'owned', 'starred']).default('owned'),\n },\n factory(originalFactory, { config }) {\n return originalFactory({\n path: '/docs',\n routeRef: rootRouteRef,\n title: 'Docs',\n icon: <RiArticleLine />,\n loader: () =>\n import('./components/TechDocsIndexPageContent').then(m => (\n <m.TechDocsIndexPageContent initialFilter={config.initialFilter} />\n )),\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 configSchema: {\n withoutSearch: z.boolean().default(false),\n withoutHeader: z.boolean().default(false),\n },\n factory(originalFactory, { apis, inputs, config }) {\n const addonsApi = apis.get(techdocsAddonsApiRef);\n\n return originalFactory({\n path: '/docs/:namespace/:kind/:name',\n routeRef: rootDocsRouteRef,\n loader: async () => {\n // Merge addons from the API with old-style direct attachments\n const apiAddons = addonsApi?.getAddons() ?? [];\n const directAddons = inputs.addons.map(output =>\n output.get(AddonBlueprint.dataRefs.addon),\n );\n const addonOptions = [...apiAddons, ...directAddons];\n const { TechDocsReaderPage } = await import(\n './components/TechDocsReaderPage'\n );\n return (\n <TechDocsReaderPage\n addonOptions={addonOptions}\n withSearch={!config.withoutSearch}\n withHeader={!config.withoutHeader}\n />\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 const addonsApi = context.apis.get(techdocsAddonsApiRef);\n\n return originalFactory(\n {\n path: 'docs',\n title: 'TechDocs',\n group: 'documentation',\n routeRef: rootCatalogDocsRouteRef,\n loader: () => {\n // Merge addons from the API with old-style direct attachments\n const apiAddons = addonsApi?.getAddons() ?? [];\n const directAddons = context.inputs.addons.map(output =>\n output.get(AddonBlueprint.dataRefs.addon),\n );\n const addonOptions = [...apiAddons, ...directAddons];\n return import('./components/TechDocsReaderPage').then(m => (\n <m.TechDocsEntityContent\n addonOptions={addonOptions}\n emptyState={context.inputs.emptyState?.get(\n coreExtensionData.reactElement,\n )}\n />\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\nconst techDocsSupportAction = PluginHeaderActionBlueprint.make({\n params: defineParams =>\n defineParams({\n loader: () =>\n import('@backstage/core-components').then(({ SupportButton }) => (\n <SupportButton>\n Discover documentation in your ecosystem.\n </SupportButton>\n )),\n }),\n});\n\n/** @alpha */\nexport default createFrontendPlugin({\n pluginId: 'techdocs',\n title: 'Documentation',\n icon: <RiArticleLine />,\n info: { packageJson: () => import('../../package.json') },\n extensions: [\n techDocsClientApi,\n techDocsStorageApi,\n TechDocsAddonsApiExtension,\n techDocsSupportAction,\n techDocsPage,\n techDocsReaderPage,\n techdocsEntityIconLink,\n techDocsEntityContent,\n techDocsEntityContentEmptyState,\n techDocsSearchFilterResultTypeExtension,\n techDocsSearchResultListItemExtension,\n ],\n routes: {\n root: rootRouteRef,\n docRoot: rootDocsRouteRef,\n entityContent: rootCatalogDocsRouteRef,\n },\n});\n\n/** @alpha */\nexport { techdocsTranslationRef } from '../translation';\n"],"names":[],"mappings":"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"}
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 { z } from 'zod/v4';\nimport { RiArticleLine } from '@remixicon/react';\nimport {\n createFrontendPlugin,\n ApiBlueprint,\n PageBlueprint,\n PluginHeaderActionBlueprint,\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 EntityContentBlueprint,\n EntityIconLinkBlueprint,\n} from '@backstage/plugin-catalog-react/alpha';\nimport {\n SearchFilterResultTypeBlueprint,\n SearchResultListItemBlueprint,\n} from '@backstage/plugin-search-react/alpha';\nimport { AddonBlueprint } from '@backstage/plugin-techdocs-react/alpha';\nimport { TechDocsAddonsApiExtension, techdocsAddonsApiRef } from './addonsApi';\nimport { TechDocsClient, TechDocsStorageClient } from '../client';\nimport {\n rootCatalogDocsRouteRef,\n rootDocsRouteRef,\n rootRouteRef,\n} from '../routes';\nimport {\n techdocsApiRef,\n techdocsStorageApiRef,\n} from '@backstage/plugin-techdocs-react';\n\nimport { useTechdocsReaderIconLinkProps } from './hooks/useTechdocsReaderIconLinkProps';\nimport { DocsIcon } from '@backstage/core-components';\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 configSchema: {\n title: z.string().optional(),\n lineClamp: z.number().default(5),\n asLink: z.boolean().default(true),\n asListItem: z.boolean().default(true),\n },\n factory(originalFactory, { config }) {\n return originalFactory({\n icon: <DocsIcon />,\n predicate: result => result.type === 'techdocs',\n component: async () => {\n const { TechDocsSearchResultListItem } = await import(\n '../search/components/TechDocsSearchResultListItem'\n );\n return props => (\n <TechDocsSearchResultListItem {...props} {...config} />\n );\n },\n });\n },\n });\n\nconst techDocsSearchFilterResultTypeExtension =\n SearchFilterResultTypeBlueprint.make({\n params: {\n value: 'techdocs',\n name: 'Documentation',\n icon: <DocsIcon />,\n },\n });\n\n/**\n * Responsible for rendering the provided router element\n *\n * @alpha\n */\nconst techDocsPage = PageBlueprint.makeWithOverrides({\n configSchema: {\n initialFilter: z.enum(['all', 'owned', 'starred']).default('owned'),\n },\n factory(originalFactory, { config }) {\n return originalFactory({\n path: '/docs',\n routeRef: rootRouteRef,\n title: 'Docs',\n icon: <RiArticleLine />,\n loader: () =>\n import('./components/TechDocsIndexPageContent').then(m => (\n <m.TechDocsIndexPageContent initialFilter={config.initialFilter} />\n )),\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 configSchema: {\n withoutSearch: z.boolean().default(false),\n withoutHeader: z.boolean().default(false),\n withoutFeedbackLink: z.boolean().default(false),\n },\n factory(originalFactory, { apis, inputs, config }) {\n const addonsApi = apis.get(techdocsAddonsApiRef);\n\n return originalFactory({\n path: '/docs/:namespace/:kind/:name',\n routeRef: rootDocsRouteRef,\n loader: async () => {\n // Merge addons from the API with old-style direct attachments\n const apiAddons = addonsApi?.getAddons() ?? [];\n const directAddons = inputs.addons.map(output =>\n output.get(AddonBlueprint.dataRefs.addon),\n );\n const addonOptions = [...apiAddons, ...directAddons];\n const { TechDocsReaderPage } = await import(\n './components/TechDocsReaderPage'\n );\n return (\n <TechDocsReaderPage\n addonOptions={addonOptions}\n withSearch={!config.withoutSearch}\n withHeader={!config.withoutHeader}\n withFeedbackLink={!config.withoutFeedbackLink}\n />\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 configSchema: {\n withoutFeedbackLink: z.boolean().default(false),\n },\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 const addonsApi = context.apis.get(techdocsAddonsApiRef);\n\n return originalFactory(\n {\n path: 'docs',\n title: 'TechDocs',\n group: 'documentation',\n routeRef: rootCatalogDocsRouteRef,\n loader: () => {\n // Merge addons from the API with old-style direct attachments\n const apiAddons = addonsApi?.getAddons() ?? [];\n const directAddons = context.inputs.addons.map(output =>\n output.get(AddonBlueprint.dataRefs.addon),\n );\n const addonOptions = [...apiAddons, ...directAddons];\n return import('./components/TechDocsReaderPage').then(m => (\n <m.TechDocsEntityContent\n addonOptions={addonOptions}\n emptyState={context.inputs.emptyState?.get(\n coreExtensionData.reactElement,\n )}\n withFeedbackLink={!context.config.withoutFeedbackLink}\n />\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\nconst techDocsSupportAction = PluginHeaderActionBlueprint.make({\n params: defineParams =>\n defineParams({\n loader: () =>\n import('@backstage/core-components').then(({ SupportButton }) => (\n <SupportButton>\n Discover documentation in your ecosystem.\n </SupportButton>\n )),\n }),\n});\n\n/** @alpha */\nexport default createFrontendPlugin({\n pluginId: 'techdocs',\n title: 'Documentation',\n icon: <RiArticleLine />,\n info: { packageJson: () => import('../../package.json') },\n extensions: [\n techDocsClientApi,\n techDocsStorageApi,\n TechDocsAddonsApiExtension,\n techDocsSupportAction,\n techDocsPage,\n techDocsReaderPage,\n techdocsEntityIconLink,\n techDocsEntityContent,\n techDocsEntityContentEmptyState,\n techDocsSearchFilterResultTypeExtension,\n techDocsSearchResultListItemExtension,\n ],\n routes: {\n root: rootRouteRef,\n docRoot: rootDocsRouteRef,\n entityContent: rootCatalogDocsRouteRef,\n },\n});\n\n/** @alpha */\nexport { techdocsTranslationRef } from '../translation';\n"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  function toLowerMaybe(str, config) {
2
2
  return config.getOptionalBoolean(
3
3
  "techdocs.legacyUseCaseSensitiveTripletPaths"
4
- ) ? str : str.toLocaleLowerCase("en-US");
4
+ ) ? str : str.toLowerCase();
5
5
  }
6
6
 
7
7
  export { toLowerMaybe };
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.esm.js","sources":["../src/helpers.ts"],"sourcesContent":["/*\n * Copyright 2021 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 { Config } from '@backstage/config';\n\n// Lower-case entity triplets by default, but allow override.\nexport function toLowerMaybe(str: string, config: Config) {\n return config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n )\n ? str\n : str.toLocaleLowerCase('en-US');\n}\n"],"names":[],"mappings":"AAmBO,SAAS,YAAA,CAAa,KAAa,MAAA,EAAgB;AACxD,EAAA,OAAO,MAAA,CAAO,kBAAA;AAAA,IACZ;AAAA,GACF,GACI,GAAA,GACA,GAAA,CAAI,iBAAA,CAAkB,OAAO,CAAA;AACnC;;;;"}
1
+ {"version":3,"file":"helpers.esm.js","sources":["../src/helpers.ts"],"sourcesContent":["/*\n * Copyright 2021 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 { Config } from '@backstage/config';\n\n// Lower-case entity triplets by default, but allow override.\nexport function toLowerMaybe(str: string, config: Config) {\n return config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n )\n ? str\n : str.toLowerCase();\n}\n"],"names":[],"mappings":"AAmBO,SAAS,YAAA,CAAa,KAAa,MAAA,EAAgB;AACxD,EAAA,OAAO,MAAA,CAAO,kBAAA;AAAA,IACZ;AAAA,GACF,GACI,GAAA,GACA,GAAA,CAAI,WAAA,EAAY;AACtB;;;;"}
@@ -62,12 +62,12 @@ const EntityListDocsGrid = (props) => {
62
62
  a,
63
63
  void 0,
64
64
  presentationApi
65
- ).primaryTitle.toLocaleLowerCase();
65
+ ).primaryTitle.toLowerCase();
66
66
  const titleB = entityPresentationSnapshot(
67
67
  b,
68
68
  void 0,
69
69
  presentationApi
70
- ).primaryTitle.toLocaleLowerCase();
70
+ ).primaryTitle.toLowerCase();
71
71
  return titleA.localeCompare(titleB);
72
72
  });
73
73
  return /* @__PURE__ */ jsx(Content, { children: (props.groups || [allEntitiesGroup]).map((group, index) => /* @__PURE__ */ jsx(
@@ -1 +1 @@
1
- {"version":3,"file":"EntityListDocsGrid.esm.js","sources":["../../../../src/home/components/Grids/EntityListDocsGrid.tsx"],"sourcesContent":["/*\n * Copyright 2021 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 { DocsCardGrid } from './DocsCardGrid';\nimport { Entity } from '@backstage/catalog-model';\nimport {\n CodeSnippet,\n Content,\n ContentHeader,\n Link,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport {\n entityPresentationApiRef,\n entityPresentationSnapshot,\n useEntityList,\n useEntityOwnership,\n} from '@backstage/plugin-catalog-react';\nimport { useApiHolder } from '@backstage/core-plugin-api';\nimport Typography from '@material-ui/core/Typography';\nimport { ReactNode } from 'react';\n\n/**\n * Props for {@link EntityListDocsGrid}\n *\n * @public\n */\nexport type DocsGroupConfig = {\n title: ReactNode;\n filterPredicate: ((entity: Entity) => boolean) | string;\n};\n\n/**\n * Props for {@link EntityListDocsGrid}\n *\n * @public\n */\nexport type EntityListDocsGridPageProps = {\n groups?: DocsGroupConfig[];\n};\n\nconst allEntitiesGroup: DocsGroupConfig = {\n title: 'All Documentation',\n filterPredicate: () => true,\n};\n\nconst EntityListDocsGridGroup = (props: {\n group: DocsGroupConfig;\n entities: Entity[];\n}) => {\n const { entities, group } = props;\n const { loading: loadingOwnership, isOwnedEntity } = useEntityOwnership();\n\n const shownEntities = entities.filter(entity => {\n if (group.filterPredicate === 'ownedByUser') {\n if (loadingOwnership) {\n return false;\n }\n return isOwnedEntity(entity);\n }\n\n return (\n typeof group.filterPredicate === 'function' &&\n group.filterPredicate(entity)\n );\n });\n\n const titleComponent: ReactNode = (() => {\n return typeof group.title === 'string' ? (\n <ContentHeader title={group.title} />\n ) : (\n group.title\n );\n })();\n\n if (shownEntities.length === 0) {\n return null;\n }\n\n return (\n <Content>\n {titleComponent}\n <DocsCardGrid entities={shownEntities} />\n </Content>\n );\n};\n\n/**\n * Component responsible to get entities from entity list context and pass down to DocsCardGrid\n *\n * @public\n */\nexport const EntityListDocsGrid = (props: EntityListDocsGridPageProps) => {\n const { loading, error, entities } = useEntityList();\n const apiHolder = useApiHolder();\n const presentationApi = apiHolder.get(entityPresentationApiRef);\n\n if (error) {\n return (\n <WarningPanel\n severity=\"error\"\n title=\"Could not load available documentation.\"\n >\n <CodeSnippet language=\"text\" text={error.toString()} />\n </WarningPanel>\n );\n }\n\n if (loading) {\n return <Progress />;\n }\n\n if (entities.length === 0) {\n return (\n <div data-testid=\"doc-not-found\">\n <Typography variant=\"body2\">\n No documentation found that match your filter. Learn more about{' '}\n <Link to=\"https://backstage.io/docs/features/techdocs/creating-and-publishing\">\n publishing documentation\n </Link>\n .\n </Typography>\n </div>\n );\n }\n\n const sortedEntities = [...entities].sort((a, b) => {\n const titleA = entityPresentationSnapshot(\n a,\n undefined,\n presentationApi,\n ).primaryTitle.toLocaleLowerCase();\n const titleB = entityPresentationSnapshot(\n b,\n undefined,\n presentationApi,\n ).primaryTitle.toLocaleLowerCase();\n return titleA.localeCompare(titleB);\n });\n\n return (\n <Content>\n {(props.groups || [allEntitiesGroup]).map((group, index: number) => (\n <EntityListDocsGridGroup\n entities={sortedEntities}\n group={group}\n key={`${group.title}-${index}`}\n />\n ))}\n </Content>\n );\n};\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EntityListDocsGrid.esm.js","sources":["../../../../src/home/components/Grids/EntityListDocsGrid.tsx"],"sourcesContent":["/*\n * Copyright 2021 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 { DocsCardGrid } from './DocsCardGrid';\nimport { Entity } from '@backstage/catalog-model';\nimport {\n CodeSnippet,\n Content,\n ContentHeader,\n Link,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport {\n entityPresentationApiRef,\n entityPresentationSnapshot,\n useEntityList,\n useEntityOwnership,\n} from '@backstage/plugin-catalog-react';\nimport { useApiHolder } from '@backstage/core-plugin-api';\nimport Typography from '@material-ui/core/Typography';\nimport { ReactNode } from 'react';\n\n/**\n * Props for {@link EntityListDocsGrid}\n *\n * @public\n */\nexport type DocsGroupConfig = {\n title: ReactNode;\n filterPredicate: ((entity: Entity) => boolean) | string;\n};\n\n/**\n * Props for {@link EntityListDocsGrid}\n *\n * @public\n */\nexport type EntityListDocsGridPageProps = {\n groups?: DocsGroupConfig[];\n};\n\nconst allEntitiesGroup: DocsGroupConfig = {\n title: 'All Documentation',\n filterPredicate: () => true,\n};\n\nconst EntityListDocsGridGroup = (props: {\n group: DocsGroupConfig;\n entities: Entity[];\n}) => {\n const { entities, group } = props;\n const { loading: loadingOwnership, isOwnedEntity } = useEntityOwnership();\n\n const shownEntities = entities.filter(entity => {\n if (group.filterPredicate === 'ownedByUser') {\n if (loadingOwnership) {\n return false;\n }\n return isOwnedEntity(entity);\n }\n\n return (\n typeof group.filterPredicate === 'function' &&\n group.filterPredicate(entity)\n );\n });\n\n const titleComponent: ReactNode = (() => {\n return typeof group.title === 'string' ? (\n <ContentHeader title={group.title} />\n ) : (\n group.title\n );\n })();\n\n if (shownEntities.length === 0) {\n return null;\n }\n\n return (\n <Content>\n {titleComponent}\n <DocsCardGrid entities={shownEntities} />\n </Content>\n );\n};\n\n/**\n * Component responsible to get entities from entity list context and pass down to DocsCardGrid\n *\n * @public\n */\nexport const EntityListDocsGrid = (props: EntityListDocsGridPageProps) => {\n const { loading, error, entities } = useEntityList();\n const apiHolder = useApiHolder();\n const presentationApi = apiHolder.get(entityPresentationApiRef);\n\n if (error) {\n return (\n <WarningPanel\n severity=\"error\"\n title=\"Could not load available documentation.\"\n >\n <CodeSnippet language=\"text\" text={error.toString()} />\n </WarningPanel>\n );\n }\n\n if (loading) {\n return <Progress />;\n }\n\n if (entities.length === 0) {\n return (\n <div data-testid=\"doc-not-found\">\n <Typography variant=\"body2\">\n No documentation found that match your filter. Learn more about{' '}\n <Link to=\"https://backstage.io/docs/features/techdocs/creating-and-publishing\">\n publishing documentation\n </Link>\n .\n </Typography>\n </div>\n );\n }\n\n const sortedEntities = [...entities].sort((a, b) => {\n const titleA = entityPresentationSnapshot(\n a,\n undefined,\n presentationApi,\n ).primaryTitle.toLowerCase();\n const titleB = entityPresentationSnapshot(\n b,\n undefined,\n presentationApi,\n ).primaryTitle.toLowerCase();\n return titleA.localeCompare(titleB);\n });\n\n return (\n <Content>\n {(props.groups || [allEntitiesGroup]).map((group, index: number) => (\n <EntityListDocsGridGroup\n entities={sortedEntities}\n group={group}\n key={`${group.title}-${index}`}\n />\n ))}\n </Content>\n );\n};\n"],"names":[],"mappings":"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"}
@@ -33,17 +33,11 @@ const columnFactories = {
33
33
  searchable: true,
34
34
  defaultSort: "asc",
35
35
  customSort: (row1, row2) => {
36
- const title1 = customTitle(
37
- row1.entity,
38
- presentationApi
39
- ).toLocaleLowerCase();
40
- const title2 = customTitle(
41
- row2.entity,
42
- presentationApi
43
- ).toLocaleLowerCase();
36
+ const title1 = customTitle(row1.entity, presentationApi).toLowerCase();
37
+ const title2 = customTitle(row2.entity, presentationApi).toLowerCase();
44
38
  return title1.localeCompare(title2);
45
39
  },
46
- customFilterAndSearch: (filter, row) => customTitle(row.entity, presentationApi).toLocaleLowerCase().includes(filter.toLocaleLowerCase()),
40
+ customFilterAndSearch: (filter, row) => customTitle(row.entity, presentationApi).toLowerCase().includes(filter.toLowerCase()),
47
41
  render: (row) => /* @__PURE__ */ jsx(
48
42
  SubvalueCell,
49
43
  {
@@ -1 +1 @@
1
- {"version":3,"file":"columns.esm.js","sources":["../../../../src/home/components/Tables/columns.tsx"],"sourcesContent":["/*\n * Copyright 2021 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 {\n Link,\n SubvalueCell,\n type TableColumn,\n} from '@backstage/core-components';\nimport {\n EntityDisplayName,\n type EntityPresentationApi,\n entityPresentationSnapshot,\n EntityRefLinks,\n} from '@backstage/plugin-catalog-react';\nimport { Entity } from '@backstage/catalog-model';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { techdocsTranslationRef } from '../../../translation';\nimport { DocsTableRow } from './types';\n\nfunction customTitle(\n entity: Entity,\n presentationApi?: EntityPresentationApi,\n): string {\n return entityPresentationSnapshot(entity, undefined, presentationApi)\n .primaryTitle;\n}\n\n/**\n * Component for translating table column titles\n * @alpha\n */\nconst TableColumnTitle = ({\n translationKey,\n}: {\n translationKey: 'document' | 'owner' | 'kind' | 'type';\n}) => {\n const { t } = useTranslationRef(techdocsTranslationRef);\n return <>{t(`table.columns.${translationKey}`)}</>;\n};\n\n/**\n * Not directly exported, but through DocsTable.columns and EntityListDocsTable.columns\n *\n * @public\n */\nexport const columnFactories = {\n createTitleColumn(options?: {\n hidden?: boolean;\n entityPresentationApi?: EntityPresentationApi;\n }): TableColumn<DocsTableRow> {\n const nameCol = columnFactories.createNameColumn({\n entityPresentationApi: options?.entityPresentationApi,\n });\n return {\n ...nameCol,\n field: 'entity.metadata.title',\n hidden: options?.hidden,\n };\n },\n\n createNameColumn(options?: {\n entityPresentationApi?: EntityPresentationApi;\n }): TableColumn<DocsTableRow> {\n const presentationApi = options?.entityPresentationApi;\n return {\n title: <TableColumnTitle translationKey=\"document\" />,\n field: 'entity.metadata.name',\n highlight: true,\n searchable: true,\n defaultSort: 'asc',\n customSort: (row1, row2) => {\n const title1 = customTitle(\n row1.entity,\n presentationApi,\n ).toLocaleLowerCase();\n const title2 = customTitle(\n row2.entity,\n presentationApi,\n ).toLocaleLowerCase();\n return title1.localeCompare(title2);\n },\n customFilterAndSearch: (filter, row) =>\n customTitle(row.entity, presentationApi)\n .toLocaleLowerCase()\n .includes(filter.toLocaleLowerCase()),\n render: (row: DocsTableRow) => (\n <SubvalueCell\n value={\n <Link to={row.resolved.docsUrl}>\n {presentationApi ? (\n <EntityDisplayName entityRef={row.entity} />\n ) : (\n customTitle(row.entity)\n )}\n </Link>\n }\n subvalue={row.entity.metadata.description}\n />\n ),\n };\n },\n createOwnerColumn(): TableColumn<DocsTableRow> {\n return {\n title: <TableColumnTitle translationKey=\"owner\" />,\n field: 'resolved.ownedByRelationsTitle',\n render: ({ resolved }) => (\n <EntityRefLinks\n entityRefs={resolved.ownedByRelations}\n defaultKind=\"group\"\n />\n ),\n };\n },\n createKindColumn(): TableColumn<DocsTableRow> {\n return {\n title: <TableColumnTitle translationKey=\"kind\" />,\n field: 'entity.kind',\n };\n },\n createTypeColumn(): TableColumn<DocsTableRow> {\n return {\n title: <TableColumnTitle translationKey=\"type\" />,\n field: 'entity.spec.type',\n };\n },\n};\n\nexport const defaultColumns: TableColumn<DocsTableRow>[] = [\n columnFactories.createTitleColumn({ hidden: true }),\n columnFactories.createNameColumn(),\n columnFactories.createOwnerColumn(),\n columnFactories.createKindColumn(),\n columnFactories.createTypeColumn(),\n];\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"columns.esm.js","sources":["../../../../src/home/components/Tables/columns.tsx"],"sourcesContent":["/*\n * Copyright 2021 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 {\n Link,\n SubvalueCell,\n type TableColumn,\n} from '@backstage/core-components';\nimport {\n EntityDisplayName,\n type EntityPresentationApi,\n entityPresentationSnapshot,\n EntityRefLinks,\n} from '@backstage/plugin-catalog-react';\nimport { Entity } from '@backstage/catalog-model';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { techdocsTranslationRef } from '../../../translation';\nimport { DocsTableRow } from './types';\n\nfunction customTitle(\n entity: Entity,\n presentationApi?: EntityPresentationApi,\n): string {\n return entityPresentationSnapshot(entity, undefined, presentationApi)\n .primaryTitle;\n}\n\n/**\n * Component for translating table column titles\n * @alpha\n */\nconst TableColumnTitle = ({\n translationKey,\n}: {\n translationKey: 'document' | 'owner' | 'kind' | 'type';\n}) => {\n const { t } = useTranslationRef(techdocsTranslationRef);\n return <>{t(`table.columns.${translationKey}`)}</>;\n};\n\n/**\n * Not directly exported, but through DocsTable.columns and EntityListDocsTable.columns\n *\n * @public\n */\nexport const columnFactories = {\n createTitleColumn(options?: {\n hidden?: boolean;\n entityPresentationApi?: EntityPresentationApi;\n }): TableColumn<DocsTableRow> {\n const nameCol = columnFactories.createNameColumn({\n entityPresentationApi: options?.entityPresentationApi,\n });\n return {\n ...nameCol,\n field: 'entity.metadata.title',\n hidden: options?.hidden,\n };\n },\n\n createNameColumn(options?: {\n entityPresentationApi?: EntityPresentationApi;\n }): TableColumn<DocsTableRow> {\n const presentationApi = options?.entityPresentationApi;\n return {\n title: <TableColumnTitle translationKey=\"document\" />,\n field: 'entity.metadata.name',\n highlight: true,\n searchable: true,\n defaultSort: 'asc',\n customSort: (row1, row2) => {\n const title1 = customTitle(row1.entity, presentationApi).toLowerCase();\n const title2 = customTitle(row2.entity, presentationApi).toLowerCase();\n return title1.localeCompare(title2);\n },\n customFilterAndSearch: (filter, row) =>\n customTitle(row.entity, presentationApi)\n .toLowerCase()\n .includes(filter.toLowerCase()),\n render: (row: DocsTableRow) => (\n <SubvalueCell\n value={\n <Link to={row.resolved.docsUrl}>\n {presentationApi ? (\n <EntityDisplayName entityRef={row.entity} />\n ) : (\n customTitle(row.entity)\n )}\n </Link>\n }\n subvalue={row.entity.metadata.description}\n />\n ),\n };\n },\n createOwnerColumn(): TableColumn<DocsTableRow> {\n return {\n title: <TableColumnTitle translationKey=\"owner\" />,\n field: 'resolved.ownedByRelationsTitle',\n render: ({ resolved }) => (\n <EntityRefLinks\n entityRefs={resolved.ownedByRelations}\n defaultKind=\"group\"\n />\n ),\n };\n },\n createKindColumn(): TableColumn<DocsTableRow> {\n return {\n title: <TableColumnTitle translationKey=\"kind\" />,\n field: 'entity.kind',\n };\n },\n createTypeColumn(): TableColumn<DocsTableRow> {\n return {\n title: <TableColumnTitle translationKey=\"type\" />,\n field: 'entity.spec.type',\n };\n },\n};\n\nexport const defaultColumns: TableColumn<DocsTableRow>[] = [\n columnFactories.createTitleColumn({ hidden: true }),\n columnFactories.createNameColumn(),\n columnFactories.createOwnerColumn(),\n columnFactories.createKindColumn(),\n columnFactories.createTypeColumn(),\n];\n"],"names":[],"mappings":"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"}
@@ -6,14 +6,17 @@ import { useTechDocsReaderDom } from '../reader/components/TechDocsReaderPageCon
6
6
  import { useTechDocsReader } from '../reader/components/TechDocsReaderProvider.esm.js';
7
7
 
8
8
  function useTechDocsReaderContentData(options) {
9
- const { defaultPath, onReady } = options;
9
+ const { defaultPath, onReady, withFeedbackLink } = options;
10
10
  const {
11
11
  entityMetadata: { value: entityMetadata, loading: entityMetadataLoading },
12
12
  entityRef,
13
13
  setShadowRoot
14
14
  } = useTechDocsReaderPage();
15
15
  const { state } = useTechDocsReader();
16
- const dom = useTechDocsReaderDom(entityRef, defaultPath);
16
+ const dom = useTechDocsReaderDom(entityRef, {
17
+ defaultPath,
18
+ withFeedbackLink
19
+ });
17
20
  const location = useLocation();
18
21
  const path = location.pathname;
19
22
  const hash = location.hash;
@@ -1 +1 @@
1
- {"version":3,"file":"useTechDocsReaderContentData.esm.js","sources":["../../src/hooks/useTechDocsReaderContentData.ts"],"sourcesContent":["/*\n * Copyright 2026 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 } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport {\n useShadowDomStylesLoading,\n useShadowRootElements,\n useTechDocsReaderPage,\n} from '@backstage/plugin-techdocs-react';\nimport { useApp } from '@backstage/core-plugin-api';\nimport { useTechDocsReaderDom } from '../reader/components/TechDocsReaderPageContent/dom';\nimport { useTechDocsReader } from '../reader/components/TechDocsReaderProvider';\n\n/**\n * Shared hook for TechDocs reader content data.\n * Encapsulates DOM setup, hash scrolling, shadow root handling,\n * 404 detection, and loading state.\n */\nexport function useTechDocsReaderContentData(options: {\n defaultPath?: string;\n onReady?: () => void;\n}) {\n const { defaultPath, onReady } = options;\n\n const {\n entityMetadata: { value: entityMetadata, loading: entityMetadataLoading },\n entityRef,\n setShadowRoot,\n } = useTechDocsReaderPage();\n const { state } = useTechDocsReader();\n const dom = useTechDocsReaderDom(entityRef, defaultPath);\n const location = useLocation();\n const path = location.pathname;\n const hash = location.hash;\n const isStyleLoading = useShadowDomStylesLoading(dom);\n const [hashElement] = useShadowRootElements([`[id=\"${hash.slice(1)}\"]`]);\n const app = useApp();\n const { NotFoundErrorPage } = app.getComponents();\n\n useEffect(() => {\n if (isStyleLoading) return;\n\n if (hash) {\n if (hashElement) {\n hashElement.scrollIntoView();\n const link = hashElement.querySelector<HTMLElement>('a.headerlink');\n if (link) {\n link.focus();\n }\n }\n } else {\n document?.querySelector('header')?.scrollIntoView();\n }\n }, [path, hash, hashElement, isStyleLoading]);\n\n const handleAppend = useCallback(\n (newShadowRoot: ShadowRoot) => {\n setShadowRoot(newShadowRoot);\n if (onReady instanceof Function) {\n onReady();\n }\n },\n [setShadowRoot, onReady],\n );\n\n const isNotFound = entityMetadataLoading === false && !entityMetadata;\n const isDomReady = !!dom;\n const showProgress = state === 'CHECKING' || isStyleLoading;\n\n return {\n entityRef,\n entityMetadata,\n dom,\n handleAppend,\n isNotFound,\n isDomReady,\n showProgress,\n NotFoundErrorPage,\n };\n}\n"],"names":[],"mappings":";;;;;;;AAgCO,SAAS,6BAA6B,OAAA,EAG1C;AACD,EAAA,MAAM,EAAE,WAAA,EAAa,OAAA,EAAQ,GAAI,OAAA;AAEjC,EAAA,MAAM;AAAA,IACJ,cAAA,EAAgB,EAAE,KAAA,EAAO,cAAA,EAAgB,SAAS,qBAAA,EAAsB;AAAA,IACxE,SAAA;AAAA,IACA;AAAA,MACE,qBAAA,EAAsB;AAC1B,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,iBAAA,EAAkB;AACpC,EAAA,MAAM,GAAA,GAAM,oBAAA,CAAqB,SAAA,EAAW,WAAW,CAAA;AACvD,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,OAAO,QAAA,CAAS,QAAA;AACtB,EAAA,MAAM,OAAO,QAAA,CAAS,IAAA;AACtB,EAAA,MAAM,cAAA,GAAiB,0BAA0B,GAAG,CAAA;AACpD,EAAA,MAAM,CAAC,WAAW,CAAA,GAAI,qBAAA,CAAsB,CAAC,CAAA,KAAA,EAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA,EAAA,CAAI,CAAC,CAAA;AACvE,EAAA,MAAM,MAAM,MAAA,EAAO;AACnB,EAAA,MAAM,EAAE,iBAAA,EAAkB,GAAI,GAAA,CAAI,aAAA,EAAc;AAEhD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,cAAA,EAAgB;AAEpB,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,WAAA,CAAY,cAAA,EAAe;AAC3B,QAAA,MAAM,IAAA,GAAO,WAAA,CAAY,aAAA,CAA2B,cAAc,CAAA;AAClE,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,IAAA,CAAK,KAAA,EAAM;AAAA,QACb;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AACL,MAAA,QAAA,EAAU,aAAA,CAAc,QAAQ,CAAA,EAAG,cAAA,EAAe;AAAA,IACpD;AAAA,EACF,GAAG,CAAC,IAAA,EAAM,IAAA,EAAM,WAAA,EAAa,cAAc,CAAC,CAAA;AAE5C,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,aAAA,KAA8B;AAC7B,MAAA,aAAA,CAAc,aAAa,CAAA;AAC3B,MAAA,IAAI,mBAAmB,QAAA,EAAU;AAC/B,QAAA,OAAA,EAAQ;AAAA,MACV;AAAA,IACF,CAAA;AAAA,IACA,CAAC,eAAe,OAAO;AAAA,GACzB;AAEA,EAAA,MAAM,UAAA,GAAa,qBAAA,KAA0B,KAAA,IAAS,CAAC,cAAA;AACvD,EAAA,MAAM,UAAA,GAAa,CAAC,CAAC,GAAA;AACrB,EAAA,MAAM,YAAA,GAAe,UAAU,UAAA,IAAc,cAAA;AAE7C,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,cAAA;AAAA,IACA,GAAA;AAAA,IACA,YAAA;AAAA,IACA,UAAA;AAAA,IACA,UAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
1
+ {"version":3,"file":"useTechDocsReaderContentData.esm.js","sources":["../../src/hooks/useTechDocsReaderContentData.ts"],"sourcesContent":["/*\n * Copyright 2026 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 } from 'react';\nimport { useLocation } from 'react-router-dom';\nimport {\n useShadowDomStylesLoading,\n useShadowRootElements,\n useTechDocsReaderPage,\n} from '@backstage/plugin-techdocs-react';\nimport { useApp } from '@backstage/core-plugin-api';\nimport { useTechDocsReaderDom } from '../reader/components/TechDocsReaderPageContent/dom';\nimport { useTechDocsReader } from '../reader/components/TechDocsReaderProvider';\n\n/**\n * Shared hook for TechDocs reader content data.\n * Encapsulates DOM setup, hash scrolling, shadow root handling,\n * 404 detection, and loading state.\n */\nexport function useTechDocsReaderContentData(options: {\n defaultPath?: string;\n onReady?: () => void;\n withFeedbackLink?: boolean;\n}) {\n const { defaultPath, onReady, withFeedbackLink } = options;\n\n const {\n entityMetadata: { value: entityMetadata, loading: entityMetadataLoading },\n entityRef,\n setShadowRoot,\n } = useTechDocsReaderPage();\n const { state } = useTechDocsReader();\n const dom = useTechDocsReaderDom(entityRef, {\n defaultPath,\n withFeedbackLink,\n });\n const location = useLocation();\n const path = location.pathname;\n const hash = location.hash;\n const isStyleLoading = useShadowDomStylesLoading(dom);\n const [hashElement] = useShadowRootElements([`[id=\"${hash.slice(1)}\"]`]);\n const app = useApp();\n const { NotFoundErrorPage } = app.getComponents();\n\n useEffect(() => {\n if (isStyleLoading) return;\n\n if (hash) {\n if (hashElement) {\n hashElement.scrollIntoView();\n const link = hashElement.querySelector<HTMLElement>('a.headerlink');\n if (link) {\n link.focus();\n }\n }\n } else {\n document?.querySelector('header')?.scrollIntoView();\n }\n }, [path, hash, hashElement, isStyleLoading]);\n\n const handleAppend = useCallback(\n (newShadowRoot: ShadowRoot) => {\n setShadowRoot(newShadowRoot);\n if (onReady instanceof Function) {\n onReady();\n }\n },\n [setShadowRoot, onReady],\n );\n\n const isNotFound = entityMetadataLoading === false && !entityMetadata;\n const isDomReady = !!dom;\n const showProgress = state === 'CHECKING' || isStyleLoading;\n\n return {\n entityRef,\n entityMetadata,\n dom,\n handleAppend,\n isNotFound,\n isDomReady,\n showProgress,\n NotFoundErrorPage,\n };\n}\n"],"names":[],"mappings":";;;;;;;AAgCO,SAAS,6BAA6B,OAAA,EAI1C;AACD,EAAA,MAAM,EAAE,WAAA,EAAa,OAAA,EAAS,gBAAA,EAAiB,GAAI,OAAA;AAEnD,EAAA,MAAM;AAAA,IACJ,cAAA,EAAgB,EAAE,KAAA,EAAO,cAAA,EAAgB,SAAS,qBAAA,EAAsB;AAAA,IACxE,SAAA;AAAA,IACA;AAAA,MACE,qBAAA,EAAsB;AAC1B,EAAA,MAAM,EAAE,KAAA,EAAM,GAAI,iBAAA,EAAkB;AACpC,EAAA,MAAM,GAAA,GAAM,qBAAqB,SAAA,EAAW;AAAA,IAC1C,WAAA;AAAA,IACA;AAAA,GACD,CAAA;AACD,EAAA,MAAM,WAAW,WAAA,EAAY;AAC7B,EAAA,MAAM,OAAO,QAAA,CAAS,QAAA;AACtB,EAAA,MAAM,OAAO,QAAA,CAAS,IAAA;AACtB,EAAA,MAAM,cAAA,GAAiB,0BAA0B,GAAG,CAAA;AACpD,EAAA,MAAM,CAAC,WAAW,CAAA,GAAI,qBAAA,CAAsB,CAAC,CAAA,KAAA,EAAQ,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA,EAAA,CAAI,CAAC,CAAA;AACvE,EAAA,MAAM,MAAM,MAAA,EAAO;AACnB,EAAA,MAAM,EAAE,iBAAA,EAAkB,GAAI,GAAA,CAAI,aAAA,EAAc;AAEhD,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,cAAA,EAAgB;AAEpB,IAAA,IAAI,IAAA,EAAM;AACR,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,WAAA,CAAY,cAAA,EAAe;AAC3B,QAAA,MAAM,IAAA,GAAO,WAAA,CAAY,aAAA,CAA2B,cAAc,CAAA;AAClE,QAAA,IAAI,IAAA,EAAM;AACR,UAAA,IAAA,CAAK,KAAA,EAAM;AAAA,QACb;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AACL,MAAA,QAAA,EAAU,aAAA,CAAc,QAAQ,CAAA,EAAG,cAAA,EAAe;AAAA,IACpD;AAAA,EACF,GAAG,CAAC,IAAA,EAAM,IAAA,EAAM,WAAA,EAAa,cAAc,CAAC,CAAA;AAE5C,EAAA,MAAM,YAAA,GAAe,WAAA;AAAA,IACnB,CAAC,aAAA,KAA8B;AAC7B,MAAA,aAAA,CAAc,aAAa,CAAA;AAC3B,MAAA,IAAI,mBAAmB,QAAA,EAAU;AAC/B,QAAA,OAAA,EAAQ;AAAA,MACV;AAAA,IACF,CAAA;AAAA,IACA,CAAC,eAAe,OAAO;AAAA,GACzB;AAEA,EAAA,MAAM,UAAA,GAAa,qBAAA,KAA0B,KAAA,IAAS,CAAC,cAAA;AACvD,EAAA,MAAM,UAAA,GAAa,CAAC,CAAC,GAAA;AACrB,EAAA,MAAM,YAAA,GAAe,UAAU,UAAA,IAAc,cAAA;AAE7C,EAAA,OAAO;AAAA,IACL,SAAA;AAAA,IACA,cAAA;AAAA,IACA,GAAA;AAAA,IACA,YAAA;AAAA,IACA,UAAA;AAAA,IACA,UAAA;AAAA,IACA,YAAA;AAAA,IACA;AAAA,GACF;AACF;;;;"}
package/dist/index.d.ts CHANGED
@@ -272,6 +272,10 @@ type TechDocsReaderPageContentProps = {
272
272
  * Show or hide the search bar, defaults to true.
273
273
  */
274
274
  withSearch?: boolean;
275
+ /**
276
+ * Show or hide the feedback button, defaults to true.
277
+ */
278
+ withFeedbackLink?: boolean;
275
279
  /**
276
280
  * If {@link TechDocsReaderPageContentProps.withSearch | withSearch} is true,
277
281
  * this will redirect the search result urls, e.g. turn search results into
@@ -1,5 +1,5 @@
1
1
  var name = "@backstage/plugin-techdocs";
2
- var version = "0.0.0-nightly-20260909022715";
2
+ var version = "0.0.0-nightly-20260919022921";
3
3
  var description = "The Backstage plugin that renders technical documentation for your components";
4
4
  var backstage = {
5
5
  role: "frontend-plugin",
@@ -36,7 +36,8 @@ const TechDocsReaderPageContent = withTechDocsReaderProvider(
36
36
  NotFoundErrorPage
37
37
  } = useTechDocsReaderContentData({
38
38
  defaultPath: props.defaultPath,
39
- onReady: props.onReady
39
+ onReady: props.onReady,
40
+ withFeedbackLink: props.withFeedbackLink
40
41
  });
41
42
  if (isNotFound) return /* @__PURE__ */ jsx(NotFoundErrorPage, {});
42
43
  if (!isDomReady) {
@@ -1 +1 @@
1
- {"version":3,"file":"TechDocsReaderPageContent.esm.js","sources":["../../../../src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.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 Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\n\nimport { TechDocsShadowDom } from '@backstage/plugin-techdocs-react';\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { Content, Progress } from '@backstage/core-components';\n\nimport { TechDocsSearch } from '../../../search';\nimport { TechDocsStateIndicator } from '../TechDocsStateIndicator';\n\nimport { withTechDocsReaderProvider } from '../TechDocsReaderProvider';\nimport { TechDocsReaderPageContentAddons } from './TechDocsReaderPageContentAddons';\nimport { useTechDocsReaderContentData } from '../../../hooks/useTechDocsReaderContentData';\n\nconst useStyles = makeStyles({\n search: {\n width: '100%',\n '@media (min-width: 76.1875em)': {\n width: 'calc(100% - 34.4rem)',\n margin: '0 auto',\n },\n '@media print': {\n display: 'none',\n },\n },\n});\n\n/**\n * Props for {@link TechDocsReaderPageContent}\n * @public\n */\nexport type TechDocsReaderPageContentProps = {\n /**\n * @deprecated No need to pass down entityRef as property anymore. Consumes the entityName from `TechDocsReaderPageContext`. Use the {@link @backstage/plugin-techdocs-react#useTechDocsReaderPage} hook for custom reader page content.\n */\n entityRef?: CompoundEntityRef;\n /**\n * Path in the docs to render by default. This should be used when rendering docs for an entity that specifies the\n * \"backstage.io/techdocs-entity-path\" annotation for deep linking into another entities docs.\n */\n defaultPath?: string;\n /**\n * Show or hide the search bar, defaults to true.\n */\n withSearch?: boolean;\n /**\n * If {@link TechDocsReaderPageContentProps.withSearch | withSearch} is true,\n * this will redirect the search result urls, e.g. turn search results into\n * links within the \"Docs\" tab of the entity page, instead of the global docs\n * page.\n */\n searchResultUrlMapper?: (url: string) => string;\n /**\n * Callback called when the content is rendered.\n */\n onReady?: () => void;\n};\n\n/**\n * Renders the reader page content\n * @public\n */\nexport const TechDocsReaderPageContent = withTechDocsReaderProvider(\n (props: TechDocsReaderPageContentProps) => {\n const { withSearch = true, searchResultUrlMapper } = props;\n const classes = useStyles();\n\n const {\n entityRef,\n entityMetadata,\n dom,\n handleAppend,\n isNotFound,\n isDomReady,\n showProgress,\n NotFoundErrorPage,\n } = useTechDocsReaderContentData({\n defaultPath: props.defaultPath,\n onReady: props.onReady,\n });\n\n if (isNotFound) return <NotFoundErrorPage />;\n\n if (!isDomReady) {\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n </Grid>\n </Content>\n );\n }\n\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n {withSearch && (\n <Grid className={classes.search} xs=\"auto\" item>\n <TechDocsSearch\n entityId={entityRef}\n entityTitle={entityMetadata?.metadata?.title}\n searchResultUrlMapper={searchResultUrlMapper}\n />\n </Grid>\n )}\n <Grid xs={12} item>\n {showProgress && <Progress />}\n\n <TechDocsShadowDom element={dom!} onAppend={handleAppend}>\n <TechDocsReaderPageContentAddons />\n </TechDocsShadowDom>\n </Grid>\n </Grid>\n </Content>\n );\n },\n);\n\n/**\n * Props for {@link Reader}\n *\n * @public\n * @deprecated use `TechDocsReaderPageContentProps` instead.\n */\nexport type ReaderProps = TechDocsReaderPageContentProps;\n\n/**\n * Component responsible for rendering TechDocs documentation\n * @public\n * @deprecated use `TechDocsReaderPageContent` component instead.\n */\nexport const Reader = TechDocsReaderPageContent;\n"],"names":[],"mappings":";;;;;;;;;;;AA8BA,MAAM,YAAY,UAAA,CAAW;AAAA,EAC3B,MAAA,EAAQ;AAAA,IACN,KAAA,EAAO,MAAA;AAAA,IACP,+BAAA,EAAiC;AAAA,MAC/B,KAAA,EAAO,sBAAA;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,cAAA,EAAgB;AAAA,MACd,OAAA,EAAS;AAAA;AACX;AAEJ,CAAC,CAAA;AAqCM,MAAM,yBAAA,GAA4B,0BAAA;AAAA,EACvC,CAAC,KAAA,KAA0C;AACzC,IAAA,MAAM,EAAE,UAAA,GAAa,IAAA,EAAM,qBAAA,EAAsB,GAAI,KAAA;AACrD,IAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,IAAA,MAAM;AAAA,MACJ,SAAA;AAAA,MACA,cAAA;AAAA,MACA,GAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,QACE,4BAAA,CAA6B;AAAA,MAC/B,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,SAAS,KAAA,CAAM;AAAA,KAChB,CAAA;AAED,IAAA,IAAI,UAAA,EAAY,uBAAO,GAAA,CAAC,iBAAA,EAAA,EAAkB,CAAA;AAE1C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,2BACG,OAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAS,MACb,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,EAAA,EAAI,EAAA,EAAI,MAAI,IAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,sBAAA,EAAA,EAAuB,CAAA,EAC1B,GACF,CAAA,EACF,CAAA;AAAA,IAEJ;AAEA,IAAA,uBACE,GAAA,CAAC,OAAA,EAAA,EACC,QAAA,kBAAA,IAAA,CAAC,IAAA,EAAA,EAAK,WAAS,IAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAK,EAAA,EAAI,EAAA,EAAI,MAAI,IAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,0BAAuB,CAAA,EAC1B,CAAA;AAAA,MACC,UAAA,wBACE,IAAA,EAAA,EAAK,SAAA,EAAW,QAAQ,MAAA,EAAQ,EAAA,EAAG,MAAA,EAAO,IAAA,EAAI,IAAA,EAC7C,QAAA,kBAAA,GAAA;AAAA,QAAC,cAAA;AAAA,QAAA;AAAA,UACC,QAAA,EAAU,SAAA;AAAA,UACV,WAAA,EAAa,gBAAgB,QAAA,EAAU,KAAA;AAAA,UACvC;AAAA;AAAA,OACF,EACF,CAAA;AAAA,sBAEF,IAAA,CAAC,IAAA,EAAA,EAAK,EAAA,EAAI,EAAA,EAAI,MAAI,IAAA,EACf,QAAA,EAAA;AAAA,QAAA,YAAA,wBAAiB,QAAA,EAAA,EAAS,CAAA;AAAA,wBAE3B,GAAA,CAAC,qBAAkB,OAAA,EAAS,GAAA,EAAM,UAAU,YAAA,EAC1C,QAAA,kBAAA,GAAA,CAAC,mCAAgC,CAAA,EACnC;AAAA,OAAA,EACF;AAAA,KAAA,EACF,CAAA,EACF,CAAA;AAAA,EAEJ;AACF;AAeO,MAAM,MAAA,GAAS;;;;"}
1
+ {"version":3,"file":"TechDocsReaderPageContent.esm.js","sources":["../../../../src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.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 Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\n\nimport { TechDocsShadowDom } from '@backstage/plugin-techdocs-react';\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { Content, Progress } from '@backstage/core-components';\n\nimport { TechDocsSearch } from '../../../search';\nimport { TechDocsStateIndicator } from '../TechDocsStateIndicator';\n\nimport { withTechDocsReaderProvider } from '../TechDocsReaderProvider';\nimport { TechDocsReaderPageContentAddons } from './TechDocsReaderPageContentAddons';\nimport { useTechDocsReaderContentData } from '../../../hooks/useTechDocsReaderContentData';\n\nconst useStyles = makeStyles({\n search: {\n width: '100%',\n '@media (min-width: 76.1875em)': {\n width: 'calc(100% - 34.4rem)',\n margin: '0 auto',\n },\n '@media print': {\n display: 'none',\n },\n },\n});\n\n/**\n * Props for {@link TechDocsReaderPageContent}\n * @public\n */\nexport type TechDocsReaderPageContentProps = {\n /**\n * @deprecated No need to pass down entityRef as property anymore. Consumes the entityName from `TechDocsReaderPageContext`. Use the {@link @backstage/plugin-techdocs-react#useTechDocsReaderPage} hook for custom reader page content.\n */\n entityRef?: CompoundEntityRef;\n /**\n * Path in the docs to render by default. This should be used when rendering docs for an entity that specifies the\n * \"backstage.io/techdocs-entity-path\" annotation for deep linking into another entities docs.\n */\n defaultPath?: string;\n /**\n * Show or hide the search bar, defaults to true.\n */\n withSearch?: boolean;\n /**\n * Show or hide the feedback button, defaults to true.\n */\n withFeedbackLink?: boolean;\n /**\n * If {@link TechDocsReaderPageContentProps.withSearch | withSearch} is true,\n * this will redirect the search result urls, e.g. turn search results into\n * links within the \"Docs\" tab of the entity page, instead of the global docs\n * page.\n */\n searchResultUrlMapper?: (url: string) => string;\n /**\n * Callback called when the content is rendered.\n */\n onReady?: () => void;\n};\n\n/**\n * Renders the reader page content\n * @public\n */\nexport const TechDocsReaderPageContent = withTechDocsReaderProvider(\n (props: TechDocsReaderPageContentProps) => {\n const { withSearch = true, searchResultUrlMapper } = props;\n const classes = useStyles();\n\n const {\n entityRef,\n entityMetadata,\n dom,\n handleAppend,\n isNotFound,\n isDomReady,\n showProgress,\n NotFoundErrorPage,\n } = useTechDocsReaderContentData({\n defaultPath: props.defaultPath,\n onReady: props.onReady,\n withFeedbackLink: props.withFeedbackLink,\n });\n\n if (isNotFound) return <NotFoundErrorPage />;\n\n if (!isDomReady) {\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n </Grid>\n </Content>\n );\n }\n\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n {withSearch && (\n <Grid className={classes.search} xs=\"auto\" item>\n <TechDocsSearch\n entityId={entityRef}\n entityTitle={entityMetadata?.metadata?.title}\n searchResultUrlMapper={searchResultUrlMapper}\n />\n </Grid>\n )}\n <Grid xs={12} item>\n {showProgress && <Progress />}\n\n <TechDocsShadowDom element={dom!} onAppend={handleAppend}>\n <TechDocsReaderPageContentAddons />\n </TechDocsShadowDom>\n </Grid>\n </Grid>\n </Content>\n );\n },\n);\n\n/**\n * Props for {@link Reader}\n *\n * @public\n * @deprecated use `TechDocsReaderPageContentProps` instead.\n */\nexport type ReaderProps = TechDocsReaderPageContentProps;\n\n/**\n * Component responsible for rendering TechDocs documentation\n * @public\n * @deprecated use `TechDocsReaderPageContent` component instead.\n */\nexport const Reader = TechDocsReaderPageContent;\n"],"names":[],"mappings":";;;;;;;;;;;AA8BA,MAAM,YAAY,UAAA,CAAW;AAAA,EAC3B,MAAA,EAAQ;AAAA,IACN,KAAA,EAAO,MAAA;AAAA,IACP,+BAAA,EAAiC;AAAA,MAC/B,KAAA,EAAO,sBAAA;AAAA,MACP,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,cAAA,EAAgB;AAAA,MACd,OAAA,EAAS;AAAA;AACX;AAEJ,CAAC,CAAA;AAyCM,MAAM,yBAAA,GAA4B,0BAAA;AAAA,EACvC,CAAC,KAAA,KAA0C;AACzC,IAAA,MAAM,EAAE,UAAA,GAAa,IAAA,EAAM,qBAAA,EAAsB,GAAI,KAAA;AACrD,IAAA,MAAM,UAAU,SAAA,EAAU;AAE1B,IAAA,MAAM;AAAA,MACJ,SAAA;AAAA,MACA,cAAA;AAAA,MACA,GAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,UAAA;AAAA,MACA,YAAA;AAAA,MACA;AAAA,QACE,4BAAA,CAA6B;AAAA,MAC/B,aAAa,KAAA,CAAM,WAAA;AAAA,MACnB,SAAS,KAAA,CAAM,OAAA;AAAA,MACf,kBAAkB,KAAA,CAAM;AAAA,KACzB,CAAA;AAED,IAAA,IAAI,UAAA,EAAY,uBAAO,GAAA,CAAC,iBAAA,EAAA,EAAkB,CAAA;AAE1C,IAAA,IAAI,CAAC,UAAA,EAAY;AACf,MAAA,2BACG,OAAA,EAAA,EACC,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAS,MACb,QAAA,kBAAA,GAAA,CAAC,IAAA,EAAA,EAAK,EAAA,EAAI,EAAA,EAAI,MAAI,IAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,sBAAA,EAAA,EAAuB,CAAA,EAC1B,GACF,CAAA,EACF,CAAA;AAAA,IAEJ;AAEA,IAAA,uBACE,GAAA,CAAC,OAAA,EAAA,EACC,QAAA,kBAAA,IAAA,CAAC,IAAA,EAAA,EAAK,WAAS,IAAA,EACb,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,QAAK,EAAA,EAAI,EAAA,EAAI,MAAI,IAAA,EAChB,QAAA,kBAAA,GAAA,CAAC,0BAAuB,CAAA,EAC1B,CAAA;AAAA,MACC,UAAA,wBACE,IAAA,EAAA,EAAK,SAAA,EAAW,QAAQ,MAAA,EAAQ,EAAA,EAAG,MAAA,EAAO,IAAA,EAAI,IAAA,EAC7C,QAAA,kBAAA,GAAA;AAAA,QAAC,cAAA;AAAA,QAAA;AAAA,UACC,QAAA,EAAU,SAAA;AAAA,UACV,WAAA,EAAa,gBAAgB,QAAA,EAAU,KAAA;AAAA,UACvC;AAAA;AAAA,OACF,EACF,CAAA;AAAA,sBAEF,IAAA,CAAC,IAAA,EAAA,EAAK,EAAA,EAAI,EAAA,EAAI,MAAI,IAAA,EACf,QAAA,EAAA;AAAA,QAAA,YAAA,wBAAiB,QAAA,EAAA,EAAS,CAAA;AAAA,wBAE3B,GAAA,CAAC,qBAAkB,OAAA,EAAS,GAAA,EAAM,UAAU,YAAA,EAC1C,QAAA,kBAAA,GAAA,CAAC,mCAAgC,CAAA,EACnC;AAAA,OAAA,EACF;AAAA,KAAA,EACF,CAAA,EACF,CAAA;AAAA,EAEJ;AACF;AAeO,MAAM,MAAA,GAAS;;;;"}
@@ -34,7 +34,8 @@ const useInitialRedirect = (defaultPath) => {
34
34
  }
35
35
  }, []);
36
36
  };
37
- const useTechDocsReaderDom = (entityRef, defaultPath) => {
37
+ const useTechDocsReaderDom = (entityRef, options) => {
38
+ const { defaultPath, withFeedbackLink = true } = options ?? {};
38
39
  const navigate = useNavigateUrl();
39
40
  const theme = useTheme();
40
41
  const isMobileMedia = useMediaQuery(MOBILE_MEDIA_QUERY);
@@ -121,7 +122,7 @@ const useTechDocsReaderDom = (entityRef, defaultPath) => {
121
122
  addSidebarToggle(),
122
123
  removeMkdocsHeader(),
123
124
  simplifyMkdocsFooter(),
124
- addGitFeedbackLink(scmIntegrationsApi),
125
+ ...withFeedbackLink ? [addGitFeedbackLink(scmIntegrationsApi)] : [],
125
126
  stylesTransformer
126
127
  ]),
127
128
  [
@@ -130,7 +131,8 @@ const useTechDocsReaderDom = (entityRef, defaultPath) => {
130
131
  scmIntegrationsApi,
131
132
  techdocsStorageApi,
132
133
  sanitizerTransformer,
133
- stylesTransformer
134
+ stylesTransformer,
135
+ withFeedbackLink
134
136
  ]
135
137
  );
136
138
  const postRender = useCallback(
@@ -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 {\n useCallback,\n useEffect,\n useLayoutEffect,\n // useRef,\n useState,\n} 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 { configApiRef, 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 addNavLinkKeyboardToggle,\n} from '../../transformers';\nimport { useNavigateUrl } from './useNavigateUrl';\nimport { useLocation, useNavigate, useParams } from 'react-router-dom';\n\nconst MOBILE_MEDIA_QUERY = 'screen and (max-width: 76.1875em)';\n\n// If a defaultPath is specified then we should navigate to that path replacing the\n// current location in the history. This should only happen on the initial load so\n// navigating to the root of the docs doesn't also redirect.\nexport const useInitialRedirect = (defaultPath?: string) => {\n const location = useLocation();\n const navigate = useNavigate();\n const { '*': currPath = '' } = useParams();\n\n useLayoutEffect(() => {\n if (currPath === '' && defaultPath) {\n navigate(`${location.pathname}${defaultPath}`, { replace: true });\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n};\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 defaultPath?: string,\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 const configApi = useApi(configApiRef);\n\n const { state, path, content: rawPage } = useTechDocsReader();\n const { '*': currPath = '' } = useParams();\n\n const [dom, setDom] = useState<HTMLElement | null>(null);\n const isStyleLoading = useShadowDomStylesLoading(dom);\n\n useInitialRedirect(defaultPath);\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:\n configApi.getOptionalString('app.baseUrl') ||\n 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 // If it's in a different page, we navigate to it\n if (window.location.pathname !== parsedUrl.pathname) {\n navigate(url);\n } else {\n // If it's in the same page we avoid using navigate that causes\n // the page to rerender.\n window.history.pushState(\n null,\n document.title,\n parsedUrl.hash,\n );\n }\n // Scroll to hash if it's on the current page\n transformedElement\n ?.querySelector(`[id=\"${parsedUrl.hash.slice(1)}\"]`)\n ?.scrollIntoView();\n\n // Focus first focusable element in the target section\n (\n transformedElement\n ?.querySelector(`[id=\"${parsedUrl.hash.slice(1)}\"]`)\n ?.querySelector('a, button, [tabindex]') as HTMLElement\n )?.focus();\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 addNavLinkKeyboardToggle(),\n ]),\n [theme, navigate, analytics, entityRef.name, configApi],\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 // Skip this update if the location's path has changed but the state\n // contains a page that isn't loaded yet.\n if (currPath !== path) {\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\n setDom(postTransformedDomElement as HTMLElement);\n });\n\n // cancel this execution\n return () => {\n shouldReplaceContent = false;\n };\n }, [rawPage, currPath, 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 {\n useCallback,\n useEffect,\n useLayoutEffect,\n // useRef,\n useState,\n} 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 { configApiRef, 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 addNavLinkKeyboardToggle,\n} from '../../transformers';\nimport { useNavigateUrl } from './useNavigateUrl';\nimport { useLocation, useNavigate, useParams } from 'react-router-dom';\n\nconst MOBILE_MEDIA_QUERY = 'screen and (max-width: 76.1875em)';\n\n// If a defaultPath is specified then we should navigate to that path replacing the\n// current location in the history. This should only happen on the initial load so\n// navigating to the root of the docs doesn't also redirect.\nexport const useInitialRedirect = (defaultPath?: string) => {\n const location = useLocation();\n const navigate = useNavigate();\n const { '*': currPath = '' } = useParams();\n\n useLayoutEffect(() => {\n if (currPath === '' && defaultPath) {\n navigate(`${location.pathname}${defaultPath}`, { replace: true });\n }\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n};\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 options?: { defaultPath?: string; withFeedbackLink?: boolean },\n): Element | null => {\n const { defaultPath, withFeedbackLink = true } = options ?? {};\n\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 const configApi = useApi(configApiRef);\n\n const { state, path, content: rawPage } = useTechDocsReader();\n const { '*': currPath = '' } = useParams();\n\n const [dom, setDom] = useState<HTMLElement | null>(null);\n const isStyleLoading = useShadowDomStylesLoading(dom);\n\n useInitialRedirect(defaultPath);\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 ...(withFeedbackLink ? [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 withFeedbackLink,\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:\n configApi.getOptionalString('app.baseUrl') ||\n 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 // If it's in a different page, we navigate to it\n if (window.location.pathname !== parsedUrl.pathname) {\n navigate(url);\n } else {\n // If it's in the same page we avoid using navigate that causes\n // the page to rerender.\n window.history.pushState(\n null,\n document.title,\n parsedUrl.hash,\n );\n }\n // Scroll to hash if it's on the current page\n transformedElement\n ?.querySelector(`[id=\"${parsedUrl.hash.slice(1)}\"]`)\n ?.scrollIntoView();\n\n // Focus first focusable element in the target section\n (\n transformedElement\n ?.querySelector(`[id=\"${parsedUrl.hash.slice(1)}\"]`)\n ?.querySelector('a, button, [tabindex]') as HTMLElement\n )?.focus();\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 addNavLinkKeyboardToggle(),\n ]),\n [theme, navigate, analytics, entityRef.name, configApi],\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 // Skip this update if the location's path has changed but the state\n // contains a page that isn't loaded yet.\n if (currPath !== path) {\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\n setDom(postTransformedDomElement as HTMLElement);\n });\n\n // cancel this execution\n return () => {\n shouldReplaceContent = false;\n };\n }, [rawPage, currPath, path, preRender, postRender]);\n\n return dom;\n};\n"],"names":["transformer"],"mappings":"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"}
@@ -12,7 +12,7 @@ function useEntityPageTechDocsRedirect(entityRef) {
12
12
  const rootDocsPath = trimEndSlash(routeDocsRoot({ kind, namespace, name }));
13
13
  const catalogDocsPath = trimEndSlash(routeDocsCatalog());
14
14
  return (url) => {
15
- if (url.toLocaleLowerCase("en-US").startsWith(rootDocsPath.toLocaleLowerCase("en-US"))) {
15
+ if (url.toLowerCase().startsWith(rootDocsPath.toLowerCase())) {
16
16
  const suffix = trimStartSlash(url.slice(rootDocsPath.length));
17
17
  return suffix.length === 0 || suffix.startsWith("#") ? `${catalogDocsPath}${suffix}` : `${catalogDocsPath}/${suffix}`;
18
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"useTechDocsLocation.esm.js","sources":["../../../src/search/hooks/useTechDocsLocation.ts"],"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 */\nimport { useMemo } from 'react';\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport { rootCatalogDocsRouteRef, rootDocsRouteRef } from '../../routes';\n\nconst trimStartSlash = (path: string) => path.replace(/^\\/+/, '');\nconst trimEndSlash = (path: string) => path.replace(/\\/+$/, '');\n\n/**\n * Returns a function that takes a location to a Tech Docs entry, and returns a\n * new location, re-routed to the catalog page tab.\n *\n * @internal\n */\nexport function useEntityPageTechDocsRedirect(entityRef: CompoundEntityRef) {\n const { kind, name, namespace } = entityRef;\n\n const routeDocsRoot = useRouteRef(rootDocsRouteRef);\n const routeDocsCatalog = useRouteRef(rootCatalogDocsRouteRef);\n\n // Re-routes a /docs/:namespace/:kind/:name/* location into\n // /catalog/:namespace/:kind/:name/docs/*, while handling situations where\n // these defaults are changed.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const reRouteLocationToCatalog = useMemo(() => {\n const rootDocsPath = trimEndSlash(routeDocsRoot({ kind, namespace, name }));\n const catalogDocsPath = trimEndSlash(routeDocsCatalog());\n\n return (url: string): string => {\n if (\n url\n .toLocaleLowerCase('en-US')\n .startsWith(rootDocsPath.toLocaleLowerCase('en-US'))\n ) {\n const suffix = trimStartSlash(url.slice(rootDocsPath.length));\n return suffix.length === 0 || suffix.startsWith('#')\n ? `${catalogDocsPath}${suffix}`\n : `${catalogDocsPath}/${suffix}`;\n }\n return url;\n };\n }, [routeDocsRoot, routeDocsCatalog, kind, name, namespace]);\n\n return reRouteLocationToCatalog;\n}\n"],"names":[],"mappings":";;;;AAsBA,MAAM,iBAAiB,CAAC,IAAA,KAAiB,IAAA,CAAK,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAChE,MAAM,eAAe,CAAC,IAAA,KAAiB,IAAA,CAAK,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAQvD,SAAS,8BAA8B,SAAA,EAA8B;AAC1E,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAM,SAAA,EAAU,GAAI,SAAA;AAElC,EAAA,MAAM,aAAA,GAAgB,YAAY,gBAAgB,CAAA;AAClD,EAAA,MAAM,gBAAA,GAAmB,YAAY,uBAAuB,CAAA;AAM5D,EAAA,MAAM,wBAAA,GAA2B,QAAQ,MAAM;AAC7C,IAAA,MAAM,YAAA,GAAe,aAAa,aAAA,CAAc,EAAE,MAAM,SAAA,EAAW,IAAA,EAAM,CAAC,CAAA;AAC1E,IAAA,MAAM,eAAA,GAAkB,YAAA,CAAa,gBAAA,EAAkB,CAAA;AAEvD,IAAA,OAAO,CAAC,GAAA,KAAwB;AAC9B,MAAA,IACE,GAAA,CACG,kBAAkB,OAAO,CAAA,CACzB,WAAW,YAAA,CAAa,iBAAA,CAAkB,OAAO,CAAC,CAAA,EACrD;AACA,QAAA,MAAM,SAAS,cAAA,CAAe,GAAA,CAAI,KAAA,CAAM,YAAA,CAAa,MAAM,CAAC,CAAA;AAC5D,QAAA,OAAO,MAAA,CAAO,MAAA,KAAW,CAAA,IAAK,MAAA,CAAO,WAAW,GAAG,CAAA,GAC/C,CAAA,EAAG,eAAe,GAAG,MAAM,CAAA,CAAA,GAC3B,CAAA,EAAG,eAAe,IAAI,MAAM,CAAA,CAAA;AAAA,MAClC;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,EACF,GAAG,CAAC,aAAA,EAAe,kBAAkB,IAAA,EAAM,IAAA,EAAM,SAAS,CAAC,CAAA;AAE3D,EAAA,OAAO,wBAAA;AACT;;;;"}
1
+ {"version":3,"file":"useTechDocsLocation.esm.js","sources":["../../../src/search/hooks/useTechDocsLocation.ts"],"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 */\nimport { useMemo } from 'react';\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport { rootCatalogDocsRouteRef, rootDocsRouteRef } from '../../routes';\n\nconst trimStartSlash = (path: string) => path.replace(/^\\/+/, '');\nconst trimEndSlash = (path: string) => path.replace(/\\/+$/, '');\n\n/**\n * Returns a function that takes a location to a Tech Docs entry, and returns a\n * new location, re-routed to the catalog page tab.\n *\n * @internal\n */\nexport function useEntityPageTechDocsRedirect(entityRef: CompoundEntityRef) {\n const { kind, name, namespace } = entityRef;\n\n const routeDocsRoot = useRouteRef(rootDocsRouteRef);\n const routeDocsCatalog = useRouteRef(rootCatalogDocsRouteRef);\n\n // Re-routes a /docs/:namespace/:kind/:name/* location into\n // /catalog/:namespace/:kind/:name/docs/*, while handling situations where\n // these defaults are changed.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const reRouteLocationToCatalog = useMemo(() => {\n const rootDocsPath = trimEndSlash(routeDocsRoot({ kind, namespace, name }));\n const catalogDocsPath = trimEndSlash(routeDocsCatalog());\n\n return (url: string): string => {\n if (url.toLowerCase().startsWith(rootDocsPath.toLowerCase())) {\n const suffix = trimStartSlash(url.slice(rootDocsPath.length));\n return suffix.length === 0 || suffix.startsWith('#')\n ? `${catalogDocsPath}${suffix}`\n : `${catalogDocsPath}/${suffix}`;\n }\n return url;\n };\n }, [routeDocsRoot, routeDocsCatalog, kind, name, namespace]);\n\n return reRouteLocationToCatalog;\n}\n"],"names":[],"mappings":";;;;AAsBA,MAAM,iBAAiB,CAAC,IAAA,KAAiB,IAAA,CAAK,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAChE,MAAM,eAAe,CAAC,IAAA,KAAiB,IAAA,CAAK,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAQvD,SAAS,8BAA8B,SAAA,EAA8B;AAC1E,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,EAAM,SAAA,EAAU,GAAI,SAAA;AAElC,EAAA,MAAM,aAAA,GAAgB,YAAY,gBAAgB,CAAA;AAClD,EAAA,MAAM,gBAAA,GAAmB,YAAY,uBAAuB,CAAA;AAM5D,EAAA,MAAM,wBAAA,GAA2B,QAAQ,MAAM;AAC7C,IAAA,MAAM,YAAA,GAAe,aAAa,aAAA,CAAc,EAAE,MAAM,SAAA,EAAW,IAAA,EAAM,CAAC,CAAA;AAC1E,IAAA,MAAM,eAAA,GAAkB,YAAA,CAAa,gBAAA,EAAkB,CAAA;AAEvD,IAAA,OAAO,CAAC,GAAA,KAAwB;AAC9B,MAAA,IAAI,IAAI,WAAA,EAAY,CAAE,WAAW,YAAA,CAAa,WAAA,EAAa,CAAA,EAAG;AAC5D,QAAA,MAAM,SAAS,cAAA,CAAe,GAAA,CAAI,KAAA,CAAM,YAAA,CAAa,MAAM,CAAC,CAAA;AAC5D,QAAA,OAAO,MAAA,CAAO,MAAA,KAAW,CAAA,IAAK,MAAA,CAAO,WAAW,GAAG,CAAA,GAC/C,CAAA,EAAG,eAAe,GAAG,MAAM,CAAA,CAAA,GAC3B,CAAA,EAAG,eAAe,IAAI,MAAM,CAAA,CAAA;AAAA,MAClC;AACA,MAAA,OAAO,GAAA;AAAA,IACT,CAAA;AAAA,EACF,GAAG,CAAC,aAAA,EAAe,kBAAkB,IAAA,EAAM,IAAA,EAAM,SAAS,CAAC,CAAA;AAE3D,EAAA,OAAO,wBAAA;AACT;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-techdocs",
3
- "version": "0.0.0-nightly-20260909022715",
3
+ "version": "0.0.0-nightly-20260919022921",
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": "0.0.0-nightly-20260909022715",
75
- "@backstage/catalog-model": "1.10.0",
76
- "@backstage/config": "0.0.0-nightly-20260909022715",
77
- "@backstage/core-components": "0.0.0-nightly-20260909022715",
78
- "@backstage/core-plugin-api": "0.0.0-nightly-20260909022715",
74
+ "@backstage/catalog-client": "0.0.0-nightly-20260919022921",
75
+ "@backstage/catalog-model": "1.10.1",
76
+ "@backstage/config": "0.0.0-nightly-20260919022921",
77
+ "@backstage/core-components": "0.0.0-nightly-20260919022921",
78
+ "@backstage/core-plugin-api": "0.0.0-nightly-20260919022921",
79
79
  "@backstage/errors": "1.3.1",
80
- "@backstage/frontend-plugin-api": "0.0.0-nightly-20260909022715",
81
- "@backstage/integration": "0.0.0-nightly-20260909022715",
82
- "@backstage/integration-react": "0.0.0-nightly-20260909022715",
83
- "@backstage/plugin-auth-react": "0.0.0-nightly-20260909022715",
84
- "@backstage/plugin-catalog-react": "0.0.0-nightly-20260909022715",
85
- "@backstage/plugin-search-common": "0.0.0-nightly-20260909022715",
86
- "@backstage/plugin-search-react": "0.0.0-nightly-20260909022715",
80
+ "@backstage/frontend-plugin-api": "0.0.0-nightly-20260919022921",
81
+ "@backstage/integration": "0.0.0-nightly-20260919022921",
82
+ "@backstage/integration-react": "0.0.0-nightly-20260919022921",
83
+ "@backstage/plugin-auth-react": "0.0.0-nightly-20260919022921",
84
+ "@backstage/plugin-catalog-react": "0.0.0-nightly-20260919022921",
85
+ "@backstage/plugin-search-common": "0.0.0-nightly-20260919022921",
86
+ "@backstage/plugin-search-react": "0.0.0-nightly-20260919022921",
87
87
  "@backstage/plugin-techdocs-common": "0.1.1",
88
- "@backstage/plugin-techdocs-react": "0.0.0-nightly-20260909022715",
88
+ "@backstage/plugin-techdocs-react": "0.0.0-nightly-20260919022921",
89
89
  "@backstage/theme": "0.7.3",
90
- "@backstage/ui": "0.0.0-nightly-20260909022715",
90
+ "@backstage/ui": "0.18.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",
@@ -102,12 +102,12 @@
102
102
  "zod": "^4.0.0"
103
103
  },
104
104
  "devDependencies": {
105
- "@backstage/cli": "0.0.0-nightly-20260909022715",
106
- "@backstage/core-app-api": "0.0.0-nightly-20260909022715",
107
- "@backstage/dev-utils": "0.0.0-nightly-20260909022715",
108
- "@backstage/plugin-catalog": "0.0.0-nightly-20260909022715",
109
- "@backstage/plugin-techdocs-module-addons-contrib": "0.0.0-nightly-20260909022715",
110
- "@backstage/test-utils": "0.0.0-nightly-20260909022715",
105
+ "@backstage/cli": "0.0.0-nightly-20260919022921",
106
+ "@backstage/core-app-api": "0.0.0-nightly-20260919022921",
107
+ "@backstage/dev-utils": "0.0.0-nightly-20260919022921",
108
+ "@backstage/plugin-catalog": "0.0.0-nightly-20260919022921",
109
+ "@backstage/plugin-techdocs-module-addons-contrib": "0.0.0-nightly-20260919022921",
110
+ "@backstage/test-utils": "0.0.0-nightly-20260919022921",
111
111
  "@testing-library/dom": "^10.0.0",
112
112
  "@testing-library/jest-dom": "^6.0.0",
113
113
  "@testing-library/react": "^16.0.0",