@backstage/plugin-techdocs 1.10.4-next.1 → 1.10.5-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/README.md +1 -1
- package/alpha/package.json +1 -1
- package/dist/EntityPageDocs.esm.js +23 -0
- package/dist/EntityPageDocs.esm.js.map +1 -0
- package/dist/Router.esm.js +47 -0
- package/dist/Router.esm.js.map +1 -0
- package/dist/alpha.esm.js +6 -7
- package/dist/alpha.esm.js.map +1 -1
- package/dist/api.esm.js +11 -0
- package/dist/api.esm.js.map +1 -0
- package/dist/{esm/routes-VopnMGN0.esm.js → client.esm.js} +2 -14
- package/dist/client.esm.js.map +1 -0
- package/dist/helpers.esm.js +8 -0
- package/dist/helpers.esm.js.map +1 -0
- package/dist/home/components/DefaultTechDocsHome.esm.js +15 -0
- package/dist/home/components/DefaultTechDocsHome.esm.js.map +1 -0
- package/dist/{esm/DocsCardGrid-AWTYz1vR.esm.js → home/components/Grids/DocsCardGrid.esm.js} +4 -4
- package/dist/home/components/Grids/DocsCardGrid.esm.js.map +1 -0
- package/dist/home/components/Grids/EntityListDocsGrid.esm.js +68 -0
- package/dist/home/components/Grids/EntityListDocsGrid.esm.js.map +1 -0
- package/dist/home/components/Tables/DocsTable.esm.js +87 -0
- package/dist/home/components/Tables/DocsTable.esm.js.map +1 -0
- package/dist/home/components/Tables/EntityListDocsTable.esm.js +50 -0
- package/dist/home/components/Tables/EntityListDocsTable.esm.js.map +1 -0
- package/dist/home/components/Tables/actions.esm.js +37 -0
- package/dist/home/components/Tables/actions.esm.js.map +1 -0
- package/dist/home/components/Tables/columns.esm.js +51 -0
- package/dist/home/components/Tables/columns.esm.js.map +1 -0
- package/dist/{esm/TechDocsCustomHome-CTmEWYTg.esm.js → home/components/TechDocsCustomHome.esm.js} +5 -17
- package/dist/home/components/TechDocsCustomHome.esm.js.map +1 -0
- package/dist/home/components/TechDocsIndexPage.esm.js +11 -0
- package/dist/home/components/TechDocsIndexPage.esm.js.map +1 -0
- package/dist/home/components/TechDocsPageWrapper.esm.js +22 -0
- package/dist/home/components/TechDocsPageWrapper.esm.js.map +1 -0
- package/dist/home/components/TechDocsPicker.esm.js +22 -0
- package/dist/home/components/TechDocsPicker.esm.js.map +1 -0
- package/dist/index.esm.js +17 -125
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +97 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/reader/components/TechDocsBuildLogs.esm.js +94 -0
- package/dist/reader/components/TechDocsBuildLogs.esm.js.map +1 -0
- package/dist/reader/components/TechDocsNotFound.esm.js +33 -0
- package/dist/reader/components/TechDocsNotFound.esm.js.map +1 -0
- package/dist/reader/components/TechDocsReaderPage/TechDocsReaderPage.esm.js +42 -0
- package/dist/reader/components/TechDocsReaderPage/TechDocsReaderPage.esm.js.map +1 -0
- package/dist/reader/components/TechDocsReaderPage/index.esm.js +2 -0
- package/dist/reader/components/TechDocsReaderPage/index.esm.js.map +1 -0
- package/dist/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.esm.js +77 -0
- package/dist/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.esm.js.map +1 -0
- package/dist/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContentAddons.esm.js +43 -0
- package/dist/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContentAddons.esm.js.map +1 -0
- package/dist/reader/components/TechDocsReaderPageContent/dom.esm.js +203 -0
- package/dist/reader/components/TechDocsReaderPageContent/dom.esm.js.map +1 -0
- package/dist/reader/components/TechDocsReaderPageContent/useNavigateUrl.esm.js +36 -0
- package/dist/reader/components/TechDocsReaderPageContent/useNavigateUrl.esm.js.map +1 -0
- package/dist/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.esm.js +101 -0
- package/dist/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.esm.js.map +1 -0
- package/dist/reader/components/TechDocsReaderPageSubheader/TechDocsReaderPageSubheader.esm.js +77 -0
- package/dist/reader/components/TechDocsReaderPageSubheader/TechDocsReaderPageSubheader.esm.js.map +1 -0
- package/dist/reader/components/TechDocsReaderProvider.esm.js +19 -0
- package/dist/reader/components/TechDocsReaderProvider.esm.js.map +1 -0
- package/dist/reader/components/TechDocsStateIndicator.esm.js +101 -0
- package/dist/reader/components/TechDocsStateIndicator.esm.js.map +1 -0
- package/dist/reader/components/useReaderState.esm.js +163 -0
- package/dist/reader/components/useReaderState.esm.js.map +1 -0
- package/dist/reader/transformers/addBaseUrl.esm.js +56 -0
- package/dist/reader/transformers/addBaseUrl.esm.js.map +1 -0
- package/dist/reader/transformers/addGitFeedbackLink.esm.js +53 -0
- package/dist/reader/transformers/addGitFeedbackLink.esm.js.map +1 -0
- package/dist/reader/transformers/addLinkClickListener.esm.js +23 -0
- package/dist/reader/transformers/addLinkClickListener.esm.js.map +1 -0
- package/dist/reader/transformers/addSidebarToggle.esm.js +27 -0
- package/dist/reader/transformers/addSidebarToggle.esm.js.map +1 -0
- package/dist/reader/transformers/copyToClipboard.esm.js +68 -0
- package/dist/reader/transformers/copyToClipboard.esm.js.map +1 -0
- package/dist/reader/transformers/html/hooks/iframes.esm.js +19 -0
- package/dist/reader/transformers/html/hooks/iframes.esm.js.map +1 -0
- package/dist/reader/transformers/html/hooks/links.esm.js +20 -0
- package/dist/reader/transformers/html/hooks/links.esm.js.map +1 -0
- package/dist/reader/transformers/html/transformer.esm.js +36 -0
- package/dist/reader/transformers/html/transformer.esm.js.map +1 -0
- package/dist/reader/transformers/onCssReady.esm.js +24 -0
- package/dist/reader/transformers/onCssReady.esm.js.map +1 -0
- package/dist/reader/transformers/removeMkdocsHeader.esm.js +10 -0
- package/dist/reader/transformers/removeMkdocsHeader.esm.js.map +1 -0
- package/dist/reader/transformers/renderReactElement.esm.js +18 -0
- package/dist/reader/transformers/renderReactElement.esm.js.map +1 -0
- package/dist/reader/transformers/rewriteDocLinks.esm.js +37 -0
- package/dist/reader/transformers/rewriteDocLinks.esm.js.map +1 -0
- package/dist/reader/transformers/scrollIntoNavigation.esm.js +21 -0
- package/dist/reader/transformers/scrollIntoNavigation.esm.js.map +1 -0
- package/dist/reader/transformers/simplifyMkdocsFooter.esm.js +11 -0
- package/dist/reader/transformers/simplifyMkdocsFooter.esm.js.map +1 -0
- package/dist/reader/transformers/styles/rules/animations.esm.js +13 -0
- package/dist/reader/transformers/styles/rules/animations.esm.js.map +1 -0
- package/dist/reader/transformers/styles/rules/extensions.esm.js +72 -0
- package/dist/reader/transformers/styles/rules/extensions.esm.js.map +1 -0
- package/dist/reader/transformers/styles/rules/layout.esm.js +224 -0
- package/dist/reader/transformers/styles/rules/layout.esm.js.map +1 -0
- package/dist/reader/transformers/styles/rules/reset.esm.js +14 -0
- package/dist/reader/transformers/styles/rules/reset.esm.js.map +1 -0
- package/dist/reader/transformers/styles/rules/rules.esm.js +18 -0
- package/dist/reader/transformers/styles/rules/rules.esm.js.map +1 -0
- package/dist/reader/transformers/styles/rules/typeset.esm.js +91 -0
- package/dist/reader/transformers/styles/rules/typeset.esm.js.map +1 -0
- package/dist/reader/transformers/styles/rules/variables.esm.js +126 -0
- package/dist/reader/transformers/styles/rules/variables.esm.js.map +1 -0
- package/dist/reader/transformers/styles/transformer.esm.js +27 -0
- package/dist/reader/transformers/styles/transformer.esm.js.map +1 -0
- package/dist/reader/transformers/transformer.esm.js +17 -0
- package/dist/reader/transformers/transformer.esm.js.map +1 -0
- package/dist/routes.esm.js +15 -0
- package/dist/routes.esm.js.map +1 -0
- package/dist/search/components/TechDocsSearch.esm.js +95 -0
- package/dist/search/components/TechDocsSearch.esm.js.map +1 -0
- package/dist/{esm/TechDocsSearchResultListItem-4Qzh5-3s.esm.js → search/components/TechDocsSearchResultListItem.esm.js} +1 -1
- package/dist/search/components/TechDocsSearchResultListItem.esm.js.map +1 -0
- package/package.json +20 -20
- package/dist/esm/DocsCardGrid-AWTYz1vR.esm.js.map +0 -1
- package/dist/esm/Router-jrzAl2lO.esm.js +0 -162
- package/dist/esm/Router-jrzAl2lO.esm.js.map +0 -1
- package/dist/esm/TechDocsCustomHome-CTmEWYTg.esm.js.map +0 -1
- package/dist/esm/TechDocsIndexPage-BCP1ggek.esm.js +0 -257
- package/dist/esm/TechDocsIndexPage-BCP1ggek.esm.js.map +0 -1
- package/dist/esm/TechDocsReaderPage-jsKVX28r.esm.js +0 -1925
- package/dist/esm/TechDocsReaderPage-jsKVX28r.esm.js.map +0 -1
- package/dist/esm/TechDocsSearchResultListItem-4Qzh5-3s.esm.js.map +0 -1
- package/dist/esm/index-up5BptkF.esm.js +0 -47
- package/dist/esm/index-up5BptkF.esm.js.map +0 -1
- package/dist/esm/routes-VopnMGN0.esm.js.map +0 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const isSvgNeedingInlining = (attrName, attrVal, apiOrigin) => {
|
|
2
|
+
const isSrcToSvg = attrName === "src" && attrVal.endsWith(".svg");
|
|
3
|
+
const isRelativeUrl = !attrVal.match(/^([a-z]*:)?\/\//i);
|
|
4
|
+
const pointsToOurBackend = attrVal.startsWith(apiOrigin);
|
|
5
|
+
return isSrcToSvg && (isRelativeUrl || pointsToOurBackend);
|
|
6
|
+
};
|
|
7
|
+
const addBaseUrl = ({
|
|
8
|
+
techdocsStorageApi,
|
|
9
|
+
entityId,
|
|
10
|
+
path
|
|
11
|
+
}) => {
|
|
12
|
+
return async (dom) => {
|
|
13
|
+
const apiOrigin = await techdocsStorageApi.getApiOrigin();
|
|
14
|
+
const updateDom = async (list, attributeName) => {
|
|
15
|
+
for (const elem of list) {
|
|
16
|
+
if (elem.hasAttribute(attributeName)) {
|
|
17
|
+
const elemAttribute = elem.getAttribute(attributeName);
|
|
18
|
+
if (!elemAttribute)
|
|
19
|
+
return;
|
|
20
|
+
const newValue = await techdocsStorageApi.getBaseUrl(
|
|
21
|
+
elemAttribute,
|
|
22
|
+
entityId,
|
|
23
|
+
path
|
|
24
|
+
);
|
|
25
|
+
if (isSvgNeedingInlining(attributeName, elemAttribute, apiOrigin)) {
|
|
26
|
+
try {
|
|
27
|
+
const svg = await fetch(newValue, { credentials: "include" });
|
|
28
|
+
const svgContent = await svg.text();
|
|
29
|
+
elem.setAttribute(
|
|
30
|
+
attributeName,
|
|
31
|
+
`data:image/svg+xml;base64,${btoa(
|
|
32
|
+
unescape(encodeURIComponent(svgContent))
|
|
33
|
+
)}`
|
|
34
|
+
);
|
|
35
|
+
} catch (e) {
|
|
36
|
+
elem.setAttribute("alt", `Error: ${elemAttribute}`);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
elem.setAttribute(attributeName, newValue);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
await Promise.all([
|
|
45
|
+
updateDom(dom.querySelectorAll("img"), "src"),
|
|
46
|
+
updateDom(dom.querySelectorAll("script"), "src"),
|
|
47
|
+
updateDom(dom.querySelectorAll("source"), "src"),
|
|
48
|
+
updateDom(dom.querySelectorAll("link"), "href"),
|
|
49
|
+
updateDom(dom.querySelectorAll("a[download]"), "href")
|
|
50
|
+
]);
|
|
51
|
+
return dom;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export { addBaseUrl };
|
|
56
|
+
//# sourceMappingURL=addBaseUrl.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addBaseUrl.esm.js","sources":["../../../src/reader/transformers/addBaseUrl.ts"],"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 */\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { TechDocsStorageApi } from '../../api';\nimport type { Transformer } from './transformer';\n\ntype AddBaseUrlOptions = {\n techdocsStorageApi: TechDocsStorageApi;\n entityId: CompoundEntityRef;\n path: string;\n};\n\n/**\n * TechDocs backend serves SVGs with text/plain content-type for security. This\n * helper determines if an SVG is being loaded from the backend, and thus needs\n * inlining to be displayed properly.\n */\nconst isSvgNeedingInlining = (\n attrName: string,\n attrVal: string,\n apiOrigin: string,\n) => {\n const isSrcToSvg = attrName === 'src' && attrVal.endsWith('.svg');\n const isRelativeUrl = !attrVal.match(/^([a-z]*:)?\\/\\//i);\n const pointsToOurBackend = attrVal.startsWith(apiOrigin);\n return isSrcToSvg && (isRelativeUrl || pointsToOurBackend);\n};\n\nexport const addBaseUrl = ({\n techdocsStorageApi,\n entityId,\n path,\n}: AddBaseUrlOptions): Transformer => {\n return async dom => {\n const apiOrigin = await techdocsStorageApi.getApiOrigin();\n\n const updateDom = async <T extends Element>(\n list: HTMLCollectionOf<T> | NodeListOf<T>,\n attributeName: string,\n ) => {\n for (const elem of list) {\n if (elem.hasAttribute(attributeName)) {\n const elemAttribute = elem.getAttribute(attributeName);\n if (!elemAttribute) return;\n\n // Special handling for SVG images.\n const newValue = await techdocsStorageApi.getBaseUrl(\n elemAttribute,\n entityId,\n path,\n );\n\n if (isSvgNeedingInlining(attributeName, elemAttribute, apiOrigin)) {\n try {\n const svg = await fetch(newValue, { credentials: 'include' });\n const svgContent = await svg.text();\n elem.setAttribute(\n attributeName,\n `data:image/svg+xml;base64,${btoa(\n unescape(encodeURIComponent(svgContent)),\n )}`,\n );\n } catch (e) {\n elem.setAttribute('alt', `Error: ${elemAttribute}`);\n }\n } else {\n elem.setAttribute(attributeName, newValue);\n }\n }\n }\n };\n\n await Promise.all([\n updateDom<HTMLImageElement>(dom.querySelectorAll('img'), 'src'),\n updateDom<HTMLScriptElement>(dom.querySelectorAll('script'), 'src'),\n updateDom<HTMLSourceElement>(dom.querySelectorAll('source'), 'src'),\n updateDom<HTMLLinkElement>(dom.querySelectorAll('link'), 'href'),\n updateDom<HTMLAnchorElement>(dom.querySelectorAll('a[download]'), 'href'),\n ]);\n\n return dom;\n };\n};\n"],"names":[],"mappings":"AA8BA,MAAM,oBAAuB,GAAA,CAC3B,QACA,EAAA,OAAA,EACA,SACG,KAAA;AACH,EAAA,MAAM,UAAa,GAAA,QAAA,KAAa,KAAS,IAAA,OAAA,CAAQ,SAAS,MAAM,CAAA,CAAA;AAChE,EAAA,MAAM,aAAgB,GAAA,CAAC,OAAQ,CAAA,KAAA,CAAM,kBAAkB,CAAA,CAAA;AACvD,EAAM,MAAA,kBAAA,GAAqB,OAAQ,CAAA,UAAA,CAAW,SAAS,CAAA,CAAA;AACvD,EAAA,OAAO,eAAe,aAAiB,IAAA,kBAAA,CAAA,CAAA;AACzC,CAAA,CAAA;AAEO,MAAM,aAAa,CAAC;AAAA,EACzB,kBAAA;AAAA,EACA,QAAA;AAAA,EACA,IAAA;AACF,CAAsC,KAAA;AACpC,EAAA,OAAO,OAAM,GAAO,KAAA;AAClB,IAAM,MAAA,SAAA,GAAY,MAAM,kBAAA,CAAmB,YAAa,EAAA,CAAA;AAExD,IAAM,MAAA,SAAA,GAAY,OAChB,IAAA,EACA,aACG,KAAA;AACH,MAAA,KAAA,MAAW,QAAQ,IAAM,EAAA;AACvB,QAAI,IAAA,IAAA,CAAK,YAAa,CAAA,aAAa,CAAG,EAAA;AACpC,UAAM,MAAA,aAAA,GAAgB,IAAK,CAAA,YAAA,CAAa,aAAa,CAAA,CAAA;AACrD,UAAA,IAAI,CAAC,aAAA;AAAe,YAAA,OAAA;AAGpB,UAAM,MAAA,QAAA,GAAW,MAAM,kBAAmB,CAAA,UAAA;AAAA,YACxC,aAAA;AAAA,YACA,QAAA;AAAA,YACA,IAAA;AAAA,WACF,CAAA;AAEA,UAAA,IAAI,oBAAqB,CAAA,aAAA,EAAe,aAAe,EAAA,SAAS,CAAG,EAAA;AACjE,YAAI,IAAA;AACF,cAAA,MAAM,MAAM,MAAM,KAAA,CAAM,UAAU,EAAE,WAAA,EAAa,WAAW,CAAA,CAAA;AAC5D,cAAM,MAAA,UAAA,GAAa,MAAM,GAAA,CAAI,IAAK,EAAA,CAAA;AAClC,cAAK,IAAA,CAAA,YAAA;AAAA,gBACH,aAAA;AAAA,gBACA,CAA6B,0BAAA,EAAA,IAAA;AAAA,kBAC3B,QAAA,CAAS,kBAAmB,CAAA,UAAU,CAAC,CAAA;AAAA,iBACxC,CAAA,CAAA;AAAA,eACH,CAAA;AAAA,qBACO,CAAG,EAAA;AACV,cAAA,IAAA,CAAK,YAAa,CAAA,KAAA,EAAO,CAAU,OAAA,EAAA,aAAa,CAAE,CAAA,CAAA,CAAA;AAAA,aACpD;AAAA,WACK,MAAA;AACL,YAAK,IAAA,CAAA,YAAA,CAAa,eAAe,QAAQ,CAAA,CAAA;AAAA,WAC3C;AAAA,SACF;AAAA,OACF;AAAA,KACF,CAAA;AAEA,IAAA,MAAM,QAAQ,GAAI,CAAA;AAAA,MAChB,SAA4B,CAAA,GAAA,CAAI,gBAAiB,CAAA,KAAK,GAAG,KAAK,CAAA;AAAA,MAC9D,SAA6B,CAAA,GAAA,CAAI,gBAAiB,CAAA,QAAQ,GAAG,KAAK,CAAA;AAAA,MAClE,SAA6B,CAAA,GAAA,CAAI,gBAAiB,CAAA,QAAQ,GAAG,KAAK,CAAA;AAAA,MAClE,SAA2B,CAAA,GAAA,CAAI,gBAAiB,CAAA,MAAM,GAAG,MAAM,CAAA;AAAA,MAC/D,SAA6B,CAAA,GAAA,CAAI,gBAAiB,CAAA,aAAa,GAAG,MAAM,CAAA;AAAA,KACzE,CAAA,CAAA;AAED,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { replaceGithubUrlType } from '@backstage/integration';
|
|
2
|
+
import FeedbackOutlinedIcon from '@material-ui/icons/FeedbackOutlined';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import parseGitUrl from 'git-url-parse';
|
|
5
|
+
import { renderReactElement } from './renderReactElement.esm.js';
|
|
6
|
+
|
|
7
|
+
const addGitFeedbackLink = (scmIntegrationsApi) => {
|
|
8
|
+
return (dom) => {
|
|
9
|
+
var _a;
|
|
10
|
+
const sourceAnchor = dom.querySelector(
|
|
11
|
+
'[title="Edit this page"]'
|
|
12
|
+
);
|
|
13
|
+
if (!sourceAnchor || !sourceAnchor.href) {
|
|
14
|
+
return dom;
|
|
15
|
+
}
|
|
16
|
+
const sourceURL = new URL(sourceAnchor.href);
|
|
17
|
+
const integration = scmIntegrationsApi.byUrl(sourceURL);
|
|
18
|
+
if ((integration == null ? void 0 : integration.type) !== "github" && (integration == null ? void 0 : integration.type) !== "gitlab") {
|
|
19
|
+
return dom;
|
|
20
|
+
}
|
|
21
|
+
const title = ((_a = dom.querySelector("article>h1")) == null ? void 0 : _a.childNodes[0].textContent) || "";
|
|
22
|
+
const issueTitle = encodeURIComponent(`Documentation Feedback: ${title}`);
|
|
23
|
+
const issueDesc = encodeURIComponent(
|
|
24
|
+
`Page source:
|
|
25
|
+
${sourceAnchor.href}
|
|
26
|
+
|
|
27
|
+
Feedback:`
|
|
28
|
+
);
|
|
29
|
+
const gitUrl = (integration == null ? void 0 : integration.type) === "github" ? replaceGithubUrlType(sourceURL.href, "blob") : sourceURL.href;
|
|
30
|
+
const gitInfo = parseGitUrl(gitUrl);
|
|
31
|
+
const repoPath = `/${gitInfo.organization}/${gitInfo.name}`;
|
|
32
|
+
const feedbackLink = sourceAnchor.cloneNode();
|
|
33
|
+
switch (integration == null ? void 0 : integration.type) {
|
|
34
|
+
case "gitlab":
|
|
35
|
+
feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?issue[title]=${issueTitle}&issue[description]=${issueDesc}`;
|
|
36
|
+
break;
|
|
37
|
+
case "github":
|
|
38
|
+
feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?title=${issueTitle}&body=${issueDesc}`;
|
|
39
|
+
break;
|
|
40
|
+
default:
|
|
41
|
+
return dom;
|
|
42
|
+
}
|
|
43
|
+
renderReactElement(React.createElement(FeedbackOutlinedIcon), feedbackLink);
|
|
44
|
+
feedbackLink.style.paddingLeft = "5px";
|
|
45
|
+
feedbackLink.title = "Leave feedback for this page";
|
|
46
|
+
feedbackLink.id = "git-feedback-link";
|
|
47
|
+
sourceAnchor == null ? void 0 : sourceAnchor.insertAdjacentElement("beforebegin", feedbackLink);
|
|
48
|
+
return dom;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export { addGitFeedbackLink };
|
|
53
|
+
//# sourceMappingURL=addGitFeedbackLink.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addGitFeedbackLink.esm.js","sources":["../../../src/reader/transformers/addGitFeedbackLink.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 type { Transformer } from './transformer';\nimport {\n replaceGithubUrlType,\n ScmIntegrationRegistry,\n} from '@backstage/integration';\nimport FeedbackOutlinedIcon from '@material-ui/icons/FeedbackOutlined';\nimport React from 'react';\nimport parseGitUrl from 'git-url-parse';\nimport { renderReactElement } from './renderReactElement';\n\n// requires repo\nexport const addGitFeedbackLink = (\n scmIntegrationsApi: ScmIntegrationRegistry,\n): Transformer => {\n return dom => {\n // attempting to use selectors that are more likely to be static as MkDocs updates over time\n const sourceAnchor = dom.querySelector(\n '[title=\"Edit this page\"]',\n ) as HTMLAnchorElement;\n\n // don't show if edit link not available in raw page\n if (!sourceAnchor || !sourceAnchor.href) {\n return dom;\n }\n\n const sourceURL = new URL(sourceAnchor.href);\n const integration = scmIntegrationsApi.byUrl(sourceURL);\n\n // don't show if can't identify edit link hostname as a gitlab/github hosting\n if (integration?.type !== 'github' && integration?.type !== 'gitlab') {\n return dom;\n }\n\n // topmost h1 only contains title for whole page\n const title =\n (dom.querySelector('article>h1') as HTMLElement)?.childNodes[0]\n .textContent || '';\n const issueTitle = encodeURIComponent(`Documentation Feedback: ${title}`);\n const issueDesc = encodeURIComponent(\n `Page source:\\n${sourceAnchor.href}\\n\\nFeedback:`,\n );\n\n // Convert GitHub edit url to blob type so it can be parsed by git-url-parse correctly\n const gitUrl =\n integration?.type === 'github'\n ? replaceGithubUrlType(sourceURL.href, 'blob')\n : sourceURL.href;\n const gitInfo = parseGitUrl(gitUrl);\n const repoPath = `/${gitInfo.organization}/${gitInfo.name}`;\n\n const feedbackLink = sourceAnchor.cloneNode() as HTMLAnchorElement;\n switch (integration?.type) {\n case 'gitlab':\n feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?issue[title]=${issueTitle}&issue[description]=${issueDesc}`;\n break;\n case 'github':\n feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?title=${issueTitle}&body=${issueDesc}`;\n break;\n default:\n return dom;\n }\n renderReactElement(React.createElement(FeedbackOutlinedIcon), feedbackLink);\n feedbackLink.style.paddingLeft = '5px';\n feedbackLink.title = 'Leave feedback for this page';\n feedbackLink.id = 'git-feedback-link';\n sourceAnchor?.insertAdjacentElement('beforebegin', feedbackLink);\n return dom;\n };\n};\n"],"names":[],"mappings":";;;;;;AA2Ba,MAAA,kBAAA,GAAqB,CAChC,kBACgB,KAAA;AAChB,EAAA,OAAO,CAAO,GAAA,KAAA;AA9BhB,IAAA,IAAA,EAAA,CAAA;AAgCI,IAAA,MAAM,eAAe,GAAI,CAAA,aAAA;AAAA,MACvB,0BAAA;AAAA,KACF,CAAA;AAGA,IAAA,IAAI,CAAC,YAAA,IAAgB,CAAC,YAAA,CAAa,IAAM,EAAA;AACvC,MAAO,OAAA,GAAA,CAAA;AAAA,KACT;AAEA,IAAA,MAAM,SAAY,GAAA,IAAI,GAAI,CAAA,YAAA,CAAa,IAAI,CAAA,CAAA;AAC3C,IAAM,MAAA,WAAA,GAAc,kBAAmB,CAAA,KAAA,CAAM,SAAS,CAAA,CAAA;AAGtD,IAAA,IAAA,CAAI,WAAa,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,WAAA,CAAA,IAAA,MAAS,QAAY,IAAA,CAAA,WAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,WAAA,CAAa,UAAS,QAAU,EAAA;AACpE,MAAO,OAAA,GAAA,CAAA;AAAA,KACT;AAGA,IAAM,MAAA,KAAA,GAAA,CAAA,CACH,SAAI,aAAc,CAAA,YAAY,MAA9B,IAAiD,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,UAAA,CAAW,GAC1D,WAAe,KAAA,EAAA,CAAA;AACpB,IAAA,MAAM,UAAa,GAAA,kBAAA,CAAmB,CAA2B,wBAAA,EAAA,KAAK,CAAE,CAAA,CAAA,CAAA;AACxE,IAAA,MAAM,SAAY,GAAA,kBAAA;AAAA,MAChB,CAAA;AAAA,EAAiB,aAAa,IAAI,CAAA;AAAA;AAAA,SAAA,CAAA;AAAA,KACpC,CAAA;AAGA,IAAM,MAAA,MAAA,GAAA,CACJ,2CAAa,IAAS,MAAA,QAAA,GAClB,qBAAqB,SAAU,CAAA,IAAA,EAAM,MAAM,CAAA,GAC3C,SAAU,CAAA,IAAA,CAAA;AAChB,IAAM,MAAA,OAAA,GAAU,YAAY,MAAM,CAAA,CAAA;AAClC,IAAA,MAAM,WAAW,CAAI,CAAA,EAAA,OAAA,CAAQ,YAAY,CAAA,CAAA,EAAI,QAAQ,IAAI,CAAA,CAAA,CAAA;AAEzD,IAAM,MAAA,YAAA,GAAe,aAAa,SAAU,EAAA,CAAA;AAC5C,IAAA,QAAQ,2CAAa,IAAM;AAAA,MACzB,KAAK,QAAA;AACH,QAAa,YAAA,CAAA,IAAA,GAAO,GAAG,SAAU,CAAA,MAAM,GAAG,QAAQ,CAAA,yBAAA,EAA4B,UAAU,CAAA,oBAAA,EAAuB,SAAS,CAAA,CAAA,CAAA;AACxH,QAAA,MAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAa,YAAA,CAAA,IAAA,GAAO,GAAG,SAAU,CAAA,MAAM,GAAG,QAAQ,CAAA,kBAAA,EAAqB,UAAU,CAAA,MAAA,EAAS,SAAS,CAAA,CAAA,CAAA;AACnG,QAAA,MAAA;AAAA,MACF;AACE,QAAO,OAAA,GAAA,CAAA;AAAA,KACX;AACA,IAAA,kBAAA,CAAmB,KAAM,CAAA,aAAA,CAAc,oBAAoB,CAAA,EAAG,YAAY,CAAA,CAAA;AAC1E,IAAA,YAAA,CAAa,MAAM,WAAc,GAAA,KAAA,CAAA;AACjC,IAAA,YAAA,CAAa,KAAQ,GAAA,8BAAA,CAAA;AACrB,IAAA,YAAA,CAAa,EAAK,GAAA,mBAAA,CAAA;AAClB,IAAA,YAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,YAAA,CAAc,sBAAsB,aAAe,EAAA,YAAA,CAAA,CAAA;AACnD,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const addLinkClickListener = ({
|
|
2
|
+
baseUrl,
|
|
3
|
+
onClick
|
|
4
|
+
}) => {
|
|
5
|
+
return (dom) => {
|
|
6
|
+
Array.from(dom.getElementsByTagName("a")).forEach((elem) => {
|
|
7
|
+
elem.addEventListener("click", (e) => {
|
|
8
|
+
const target = elem;
|
|
9
|
+
const href = target.getAttribute("href");
|
|
10
|
+
if (!href)
|
|
11
|
+
return;
|
|
12
|
+
if (href.startsWith(baseUrl) && !elem.hasAttribute("download")) {
|
|
13
|
+
e.preventDefault();
|
|
14
|
+
onClick(e, href);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
return dom;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export { addLinkClickListener };
|
|
23
|
+
//# sourceMappingURL=addLinkClickListener.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addLinkClickListener.esm.js","sources":["../../../src/reader/transformers/addLinkClickListener.ts"],"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 type { Transformer } from './transformer';\n\ntype AddLinkClickListenerOptions = {\n baseUrl: string;\n onClick: (e: MouseEvent, newUrl: string) => void;\n};\n\nexport const addLinkClickListener = ({\n baseUrl,\n onClick,\n}: AddLinkClickListenerOptions): Transformer => {\n return dom => {\n Array.from(dom.getElementsByTagName('a')).forEach(elem => {\n elem.addEventListener('click', (e: MouseEvent) => {\n const target = elem as HTMLAnchorElement;\n const href = target.getAttribute('href');\n\n if (!href) return;\n if (href.startsWith(baseUrl) && !elem.hasAttribute('download')) {\n e.preventDefault();\n onClick(e, href);\n }\n });\n });\n\n return dom;\n };\n};\n"],"names":[],"mappings":"AAuBO,MAAM,uBAAuB,CAAC;AAAA,EACnC,OAAA;AAAA,EACA,OAAA;AACF,CAAgD,KAAA;AAC9C,EAAA,OAAO,CAAO,GAAA,KAAA;AACZ,IAAA,KAAA,CAAM,KAAK,GAAI,CAAA,oBAAA,CAAqB,GAAG,CAAC,CAAA,CAAE,QAAQ,CAAQ,IAAA,KAAA;AACxD,MAAK,IAAA,CAAA,gBAAA,CAAiB,OAAS,EAAA,CAAC,CAAkB,KAAA;AAChD,QAAA,MAAM,MAAS,GAAA,IAAA,CAAA;AACf,QAAM,MAAA,IAAA,GAAO,MAAO,CAAA,YAAA,CAAa,MAAM,CAAA,CAAA;AAEvC,QAAA,IAAI,CAAC,IAAA;AAAM,UAAA,OAAA;AACX,QAAI,IAAA,IAAA,CAAK,WAAW,OAAO,CAAA,IAAK,CAAC,IAAK,CAAA,YAAA,CAAa,UAAU,CAAG,EAAA;AAC9D,UAAA,CAAA,CAAE,cAAe,EAAA,CAAA;AACjB,UAAA,OAAA,CAAQ,GAAG,IAAI,CAAA,CAAA;AAAA,SACjB;AAAA,OACD,CAAA,CAAA;AAAA,KACF,CAAA,CAAA;AAED,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import MenuIcon from '@material-ui/icons/Menu';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { renderReactElement } from './renderReactElement.esm.js';
|
|
4
|
+
|
|
5
|
+
const addSidebarToggle = () => {
|
|
6
|
+
return (dom) => {
|
|
7
|
+
const mkdocsToggleSidebar = dom.querySelector(
|
|
8
|
+
'.md-header label[for="__drawer"]'
|
|
9
|
+
);
|
|
10
|
+
const article = dom.querySelector("article");
|
|
11
|
+
if (!mkdocsToggleSidebar || !article) {
|
|
12
|
+
return dom;
|
|
13
|
+
}
|
|
14
|
+
const toggleSidebar = mkdocsToggleSidebar.cloneNode();
|
|
15
|
+
renderReactElement(React.createElement(MenuIcon), toggleSidebar);
|
|
16
|
+
toggleSidebar.id = "toggle-sidebar";
|
|
17
|
+
toggleSidebar.title = "Toggle Sidebar";
|
|
18
|
+
toggleSidebar.classList.add("md-content__button");
|
|
19
|
+
toggleSidebar.style.setProperty("padding", "0 0 0 5px");
|
|
20
|
+
toggleSidebar.style.setProperty("margin", "0.4rem 0 0.4rem 0.4rem");
|
|
21
|
+
article == null ? void 0 : article.prepend(toggleSidebar);
|
|
22
|
+
return dom;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export { addSidebarToggle };
|
|
27
|
+
//# sourceMappingURL=addSidebarToggle.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addSidebarToggle.esm.js","sources":["../../../src/reader/transformers/addSidebarToggle.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 type { Transformer } from './transformer';\nimport MenuIcon from '@material-ui/icons/Menu';\nimport React from 'react';\nimport { renderReactElement } from './renderReactElement';\n\nexport const addSidebarToggle = (): Transformer => {\n return dom => {\n // attempting to use selectors that are more likely to be static as MkDocs updates over time\n const mkdocsToggleSidebar = dom.querySelector(\n '.md-header label[for=\"__drawer\"]',\n ) as HTMLLabelElement;\n const article = dom.querySelector('article') as HTMLElement;\n\n // Fail gracefully\n if (!mkdocsToggleSidebar || !article) {\n return dom;\n }\n\n const toggleSidebar = mkdocsToggleSidebar.cloneNode() as HTMLLabelElement;\n renderReactElement(React.createElement(MenuIcon), toggleSidebar);\n toggleSidebar.id = 'toggle-sidebar';\n toggleSidebar.title = 'Toggle Sidebar';\n toggleSidebar.classList.add('md-content__button');\n toggleSidebar.style.setProperty('padding', '0 0 0 5px');\n toggleSidebar.style.setProperty('margin', '0.4rem 0 0.4rem 0.4rem');\n article?.prepend(toggleSidebar);\n return dom;\n };\n};\n"],"names":[],"mappings":";;;;AAqBO,MAAM,mBAAmB,MAAmB;AACjD,EAAA,OAAO,CAAO,GAAA,KAAA;AAEZ,IAAA,MAAM,sBAAsB,GAAI,CAAA,aAAA;AAAA,MAC9B,kCAAA;AAAA,KACF,CAAA;AACA,IAAM,MAAA,OAAA,GAAU,GAAI,CAAA,aAAA,CAAc,SAAS,CAAA,CAAA;AAG3C,IAAI,IAAA,CAAC,mBAAuB,IAAA,CAAC,OAAS,EAAA;AACpC,MAAO,OAAA,GAAA,CAAA;AAAA,KACT;AAEA,IAAM,MAAA,aAAA,GAAgB,oBAAoB,SAAU,EAAA,CAAA;AACpD,IAAA,kBAAA,CAAmB,KAAM,CAAA,aAAA,CAAc,QAAQ,CAAA,EAAG,aAAa,CAAA,CAAA;AAC/D,IAAA,aAAA,CAAc,EAAK,GAAA,gBAAA,CAAA;AACnB,IAAA,aAAA,CAAc,KAAQ,GAAA,gBAAA,CAAA;AACtB,IAAc,aAAA,CAAA,SAAA,CAAU,IAAI,oBAAoB,CAAA,CAAA;AAChD,IAAc,aAAA,CAAA,KAAA,CAAM,WAAY,CAAA,SAAA,EAAW,WAAW,CAAA,CAAA;AACtD,IAAc,aAAA,CAAA,KAAA,CAAM,WAAY,CAAA,QAAA,EAAU,wBAAwB,CAAA,CAAA;AAClE,IAAA,OAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,OAAA,CAAS,OAAQ,CAAA,aAAA,CAAA,CAAA;AACjB,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React, { useState, useCallback } from 'react';
|
|
2
|
+
import { renderReactElement } from './renderReactElement.esm.js';
|
|
3
|
+
import { withStyles, ThemeProvider } from '@material-ui/core/styles';
|
|
4
|
+
import SvgIcon from '@material-ui/core/SvgIcon';
|
|
5
|
+
import Tooltip from '@material-ui/core/Tooltip';
|
|
6
|
+
import IconButton from '@material-ui/core/IconButton';
|
|
7
|
+
import useCopyToClipboard from 'react-use/esm/useCopyToClipboard';
|
|
8
|
+
|
|
9
|
+
const CopyToClipboardTooltip = withStyles((theme) => ({
|
|
10
|
+
tooltip: {
|
|
11
|
+
fontSize: "inherit",
|
|
12
|
+
color: theme.palette.text.primary,
|
|
13
|
+
margin: 0,
|
|
14
|
+
padding: theme.spacing(0.5),
|
|
15
|
+
backgroundColor: "transparent",
|
|
16
|
+
boxShadow: "none"
|
|
17
|
+
}
|
|
18
|
+
}))(Tooltip);
|
|
19
|
+
const CopyToClipboardIcon = () => /* @__PURE__ */ React.createElement(SvgIcon, null, /* @__PURE__ */ React.createElement("path", { d: "M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z" }));
|
|
20
|
+
const CopyToClipboardButton = ({ text }) => {
|
|
21
|
+
const [open, setOpen] = useState(false);
|
|
22
|
+
const [, copyToClipboard2] = useCopyToClipboard();
|
|
23
|
+
const handleClick = useCallback(() => {
|
|
24
|
+
copyToClipboard2(text);
|
|
25
|
+
setOpen(true);
|
|
26
|
+
}, [text, copyToClipboard2]);
|
|
27
|
+
const handleClose = useCallback(() => {
|
|
28
|
+
setOpen(false);
|
|
29
|
+
}, [setOpen]);
|
|
30
|
+
return /* @__PURE__ */ React.createElement(
|
|
31
|
+
CopyToClipboardTooltip,
|
|
32
|
+
{
|
|
33
|
+
title: "Copied to clipboard",
|
|
34
|
+
placement: "left",
|
|
35
|
+
open,
|
|
36
|
+
onClose: handleClose,
|
|
37
|
+
leaveDelay: 1e3
|
|
38
|
+
},
|
|
39
|
+
/* @__PURE__ */ React.createElement(
|
|
40
|
+
IconButton,
|
|
41
|
+
{
|
|
42
|
+
style: { color: "inherit" },
|
|
43
|
+
className: "md-clipboard md-icon",
|
|
44
|
+
onClick: handleClick
|
|
45
|
+
},
|
|
46
|
+
/* @__PURE__ */ React.createElement(CopyToClipboardIcon, null)
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
const copyToClipboard = (theme) => {
|
|
51
|
+
return (dom) => {
|
|
52
|
+
var _a;
|
|
53
|
+
const codes = dom.querySelectorAll("pre > code");
|
|
54
|
+
for (const code of codes) {
|
|
55
|
+
const text = code.textContent || "";
|
|
56
|
+
const container = document.createElement("div");
|
|
57
|
+
(_a = code == null ? void 0 : code.parentElement) == null ? void 0 : _a.prepend(container);
|
|
58
|
+
renderReactElement(
|
|
59
|
+
/* @__PURE__ */ React.createElement(ThemeProvider, { theme }, /* @__PURE__ */ React.createElement(CopyToClipboardButton, { text })),
|
|
60
|
+
container
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return dom;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export { copyToClipboard };
|
|
68
|
+
//# sourceMappingURL=copyToClipboard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copyToClipboard.esm.js","sources":["../../../src/reader/transformers/copyToClipboard.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 React, { useState, useCallback } from 'react';\nimport { renderReactElement } from './renderReactElement';\nimport { ThemeProvider } from '@material-ui/core/styles';\nimport SvgIcon from '@material-ui/core/SvgIcon';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { withStyles, Theme } from '@material-ui/core/styles';\nimport IconButton from '@material-ui/core/IconButton';\nimport type { Transformer } from './transformer';\nimport useCopyToClipboard from 'react-use/esm/useCopyToClipboard';\n\nconst CopyToClipboardTooltip = withStyles(theme => ({\n tooltip: {\n fontSize: 'inherit',\n color: theme.palette.text.primary,\n margin: 0,\n padding: theme.spacing(0.5),\n backgroundColor: 'transparent',\n boxShadow: 'none',\n },\n}))(Tooltip);\n\nconst CopyToClipboardIcon = () => (\n <SvgIcon>\n <path d=\"M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z\" />\n </SvgIcon>\n);\n\ntype CopyToClipboardButtonProps = {\n text: string;\n};\n\nconst CopyToClipboardButton = ({ text }: CopyToClipboardButtonProps) => {\n const [open, setOpen] = useState(false);\n const [, copyToClipboard] = useCopyToClipboard();\n\n const handleClick = useCallback(() => {\n copyToClipboard(text);\n setOpen(true);\n }, [text, copyToClipboard]);\n\n const handleClose = useCallback(() => {\n setOpen(false);\n }, [setOpen]);\n\n return (\n <CopyToClipboardTooltip\n title=\"Copied to clipboard\"\n placement=\"left\"\n open={open}\n onClose={handleClose}\n leaveDelay={1000}\n >\n <IconButton\n style={{ color: 'inherit' }}\n className=\"md-clipboard md-icon\"\n onClick={handleClick}\n >\n <CopyToClipboardIcon />\n </IconButton>\n </CopyToClipboardTooltip>\n );\n};\n\n/**\n * Recreates copy-to-clipboard functionality attached to <code> snippets that\n * is native to mkdocs-material theme.\n */\nexport const copyToClipboard = (theme: Theme): Transformer => {\n return dom => {\n const codes = dom.querySelectorAll('pre > code');\n for (const code of codes) {\n const text = code.textContent || '';\n const container = document.createElement('div');\n code?.parentElement?.prepend(container);\n renderReactElement(\n <ThemeProvider theme={theme}>\n <CopyToClipboardButton text={text} />\n </ThemeProvider>,\n container,\n );\n }\n return dom;\n };\n};\n"],"names":["copyToClipboard"],"mappings":";;;;;;;;AA0BA,MAAM,sBAAA,GAAyB,WAAW,CAAU,KAAA,MAAA;AAAA,EAClD,OAAS,EAAA;AAAA,IACP,QAAU,EAAA,SAAA;AAAA,IACV,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,IAAK,CAAA,OAAA;AAAA,IAC1B,MAAQ,EAAA,CAAA;AAAA,IACR,OAAA,EAAS,KAAM,CAAA,OAAA,CAAQ,GAAG,CAAA;AAAA,IAC1B,eAAiB,EAAA,aAAA;AAAA,IACjB,SAAW,EAAA,MAAA;AAAA,GACb;AACF,CAAA,CAAE,EAAE,OAAO,CAAA,CAAA;AAEX,MAAM,mBAAA,GAAsB,sBACzB,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,IAAA,sCACE,MAAK,EAAA,EAAA,CAAA,EAAE,mIAAkI,CAC5I,CAAA,CAAA;AAOF,MAAM,qBAAwB,GAAA,CAAC,EAAE,IAAA,EAAuC,KAAA;AACtE,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAS,KAAK,CAAA,CAAA;AACtC,EAAA,MAAM,GAAGA,gBAAe,CAAA,GAAI,kBAAmB,EAAA,CAAA;AAE/C,EAAM,MAAA,WAAA,GAAc,YAAY,MAAM;AACpC,IAAAA,iBAAgB,IAAI,CAAA,CAAA;AACpB,IAAA,OAAA,CAAQ,IAAI,CAAA,CAAA;AAAA,GACX,EAAA,CAAC,IAAMA,EAAAA,gBAAe,CAAC,CAAA,CAAA;AAE1B,EAAM,MAAA,WAAA,GAAc,YAAY,MAAM;AACpC,IAAA,OAAA,CAAQ,KAAK,CAAA,CAAA;AAAA,GACf,EAAG,CAAC,OAAO,CAAC,CAAA,CAAA;AAEZ,EACE,uBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,sBAAA;AAAA,IAAA;AAAA,MACC,KAAM,EAAA,qBAAA;AAAA,MACN,SAAU,EAAA,MAAA;AAAA,MACV,IAAA;AAAA,MACA,OAAS,EAAA,WAAA;AAAA,MACT,UAAY,EAAA,GAAA;AAAA,KAAA;AAAA,oBAEZ,KAAA,CAAA,aAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,EAAE,KAAA,EAAO,SAAU,EAAA;AAAA,QAC1B,SAAU,EAAA,sBAAA;AAAA,QACV,OAAS,EAAA,WAAA;AAAA,OAAA;AAAA,0CAER,mBAAoB,EAAA,IAAA,CAAA;AAAA,KACvB;AAAA,GACF,CAAA;AAEJ,CAAA,CAAA;AAMa,MAAA,eAAA,GAAkB,CAAC,KAA8B,KAAA;AAC5D,EAAA,OAAO,CAAO,GAAA,KAAA;AApFhB,IAAA,IAAA,EAAA,CAAA;AAqFI,IAAM,MAAA,KAAA,GAAQ,GAAI,CAAA,gBAAA,CAAiB,YAAY,CAAA,CAAA;AAC/C,IAAA,KAAA,MAAW,QAAQ,KAAO,EAAA;AACxB,MAAM,MAAA,IAAA,GAAO,KAAK,WAAe,IAAA,EAAA,CAAA;AACjC,MAAM,MAAA,SAAA,GAAY,QAAS,CAAA,aAAA,CAAc,KAAK,CAAA,CAAA;AAC9C,MAAM,CAAA,EAAA,GAAA,IAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,IAAA,CAAA,aAAA,KAAN,mBAAqB,OAAQ,CAAA,SAAA,CAAA,CAAA;AAC7B,MAAA,kBAAA;AAAA,4CACG,aAAc,EAAA,EAAA,KAAA,EAAA,kBACZ,KAAA,CAAA,aAAA,CAAA,qBAAA,EAAA,EAAsB,MAAY,CACrC,CAAA;AAAA,QACA,SAAA;AAAA,OACF,CAAA;AAAA,KACF;AACA,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const isIframe = (node) => node.nodeName === "IFRAME";
|
|
2
|
+
const isSafe = (node, hosts) => {
|
|
3
|
+
const src = node.getAttribute("src") || "";
|
|
4
|
+
try {
|
|
5
|
+
const { host } = new URL(src);
|
|
6
|
+
return hosts.includes(host);
|
|
7
|
+
} catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
const removeUnsafeIframes = (hosts) => (node) => {
|
|
12
|
+
if (isIframe(node) && !isSafe(node, hosts)) {
|
|
13
|
+
node.remove();
|
|
14
|
+
}
|
|
15
|
+
return node;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export { removeUnsafeIframes };
|
|
19
|
+
//# sourceMappingURL=iframes.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"iframes.esm.js","sources":["../../../../../src/reader/transformers/html/hooks/iframes.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Checks whether a node is iframe or not.\n * @param node - can be any element.\n * @returns true when node is iframe.\n */\nconst isIframe = (node: Element) => node.nodeName === 'IFRAME';\n\n/**\n * Checks whether a iframe is safe or not.\n * @param node - is an iframe element.\n * @param hosts - list of allowed hosts.\n * @returns true when iframe is included in hosts.\n */\nconst isSafe = (node: Element, hosts: string[]) => {\n const src = node.getAttribute('src') || '';\n try {\n const { host } = new URL(src);\n return hosts.includes(host);\n } catch {\n return false;\n }\n};\n\n/**\n * Returns a function that removes unsafe iframe nodes.\n * @param node - can be any element.\n * @param hosts - list of allowed hosts.\n */\nexport const removeUnsafeIframes = (hosts: string[]) => (node: Element) => {\n if (isIframe(node) && !isSafe(node, hosts)) {\n node.remove();\n }\n return node;\n};\n"],"names":[],"mappings":"AAqBA,MAAM,QAAW,GAAA,CAAC,IAAkB,KAAA,IAAA,CAAK,QAAa,KAAA,QAAA,CAAA;AAQtD,MAAM,MAAA,GAAS,CAAC,IAAA,EAAe,KAAoB,KAAA;AACjD,EAAA,MAAM,GAAM,GAAA,IAAA,CAAK,YAAa,CAAA,KAAK,CAAK,IAAA,EAAA,CAAA;AACxC,EAAI,IAAA;AACF,IAAA,MAAM,EAAE,IAAA,EAAS,GAAA,IAAI,IAAI,GAAG,CAAA,CAAA;AAC5B,IAAO,OAAA,KAAA,CAAM,SAAS,IAAI,CAAA,CAAA;AAAA,GACpB,CAAA,MAAA;AACN,IAAO,OAAA,KAAA,CAAA;AAAA,GACT;AACF,CAAA,CAAA;AAOO,MAAM,mBAAsB,GAAA,CAAC,KAAoB,KAAA,CAAC,IAAkB,KAAA;AACzE,EAAA,IAAI,SAAS,IAAI,CAAA,IAAK,CAAC,MAAO,CAAA,IAAA,EAAM,KAAK,CAAG,EAAA;AAC1C,IAAA,IAAA,CAAK,MAAO,EAAA,CAAA;AAAA,GACd;AACA,EAAO,OAAA,IAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const MKDOCS_CSS = /main\.[A-Fa-f0-9]{8}\.min\.css$/;
|
|
2
|
+
const GOOGLE_FONTS = /^https:\/\/fonts\.googleapis\.com/;
|
|
3
|
+
const GSTATIC_FONTS = /^https:\/\/fonts\.gstatic\.com/;
|
|
4
|
+
const isLink = (node) => node.nodeName === "LINK";
|
|
5
|
+
const isSafe = (node) => {
|
|
6
|
+
const href = (node == null ? void 0 : node.getAttribute("href")) || "";
|
|
7
|
+
const isMkdocsCss = href.match(MKDOCS_CSS);
|
|
8
|
+
const isGoogleFonts = href.match(GOOGLE_FONTS);
|
|
9
|
+
const isGstaticFonts = href.match(GSTATIC_FONTS);
|
|
10
|
+
return isMkdocsCss || isGoogleFonts || isGstaticFonts;
|
|
11
|
+
};
|
|
12
|
+
const removeUnsafeLinks = (node) => {
|
|
13
|
+
if (isLink(node) && !isSafe(node)) {
|
|
14
|
+
node.remove();
|
|
15
|
+
}
|
|
16
|
+
return node;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { removeUnsafeLinks };
|
|
20
|
+
//# sourceMappingURL=links.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"links.esm.js","sources":["../../../../../src/reader/transformers/html/hooks/links.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nconst MKDOCS_CSS = /main\\.[A-Fa-f0-9]{8}\\.min\\.css$/;\nconst GOOGLE_FONTS = /^https:\\/\\/fonts\\.googleapis\\.com/;\nconst GSTATIC_FONTS = /^https:\\/\\/fonts\\.gstatic\\.com/;\n\n/**\n * Checks whether a node is link or not.\n * @param node - can be any element.\n * @returns true when node is link.\n */\nconst isLink = (node: Element) => node.nodeName === 'LINK';\n\n/**\n * Checks whether a link is safe or not.\n * @param node - is an link element.\n * @returns true when link is mkdocs css, google fonts or gstatic fonts.\n */\nconst isSafe = (node: Element) => {\n const href = node?.getAttribute('href') || '';\n const isMkdocsCss = href.match(MKDOCS_CSS);\n const isGoogleFonts = href.match(GOOGLE_FONTS);\n const isGstaticFonts = href.match(GSTATIC_FONTS);\n return isMkdocsCss || isGoogleFonts || isGstaticFonts;\n};\n\n/**\n * Function that removes unsafe link nodes.\n * @param node - can be any element.\n * @param hosts - list of allowed hosts.\n */\nexport const removeUnsafeLinks = (node: Element) => {\n if (isLink(node) && !isSafe(node)) {\n node.remove();\n }\n return node;\n};\n"],"names":[],"mappings":"AAgBA,MAAM,UAAa,GAAA,iCAAA,CAAA;AACnB,MAAM,YAAe,GAAA,mCAAA,CAAA;AACrB,MAAM,aAAgB,GAAA,gCAAA,CAAA;AAOtB,MAAM,MAAS,GAAA,CAAC,IAAkB,KAAA,IAAA,CAAK,QAAa,KAAA,MAAA,CAAA;AAOpD,MAAM,MAAA,GAAS,CAAC,IAAkB,KAAA;AAChC,EAAM,MAAA,IAAA,GAAA,CAAO,IAAM,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,IAAA,CAAA,YAAA,CAAa,MAAW,CAAA,KAAA,EAAA,CAAA;AAC3C,EAAM,MAAA,WAAA,GAAc,IAAK,CAAA,KAAA,CAAM,UAAU,CAAA,CAAA;AACzC,EAAM,MAAA,aAAA,GAAgB,IAAK,CAAA,KAAA,CAAM,YAAY,CAAA,CAAA;AAC7C,EAAM,MAAA,cAAA,GAAiB,IAAK,CAAA,KAAA,CAAM,aAAa,CAAA,CAAA;AAC/C,EAAA,OAAO,eAAe,aAAiB,IAAA,cAAA,CAAA;AACzC,CAAA,CAAA;AAOa,MAAA,iBAAA,GAAoB,CAAC,IAAkB,KAAA;AAClD,EAAA,IAAI,OAAO,IAAI,CAAA,IAAK,CAAC,MAAA,CAAO,IAAI,CAAG,EAAA;AACjC,IAAA,IAAA,CAAK,MAAO,EAAA,CAAA;AAAA,GACd;AACA,EAAO,OAAA,IAAA,CAAA;AACT;;;;"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import DOMPurify from 'dompurify';
|
|
2
|
+
import { useCallback, useMemo } from 'react';
|
|
3
|
+
import { useApi, configApiRef } from '@backstage/core-plugin-api';
|
|
4
|
+
import { removeUnsafeLinks } from './hooks/links.esm.js';
|
|
5
|
+
import { removeUnsafeIframes } from './hooks/iframes.esm.js';
|
|
6
|
+
|
|
7
|
+
const useSanitizerConfig = () => {
|
|
8
|
+
const configApi = useApi(configApiRef);
|
|
9
|
+
return useMemo(() => {
|
|
10
|
+
return configApi.getOptionalConfig("techdocs.sanitizer");
|
|
11
|
+
}, [configApi]);
|
|
12
|
+
};
|
|
13
|
+
const useSanitizerTransformer = () => {
|
|
14
|
+
const config = useSanitizerConfig();
|
|
15
|
+
return useCallback(
|
|
16
|
+
async (dom) => {
|
|
17
|
+
const hosts = config == null ? void 0 : config.getOptionalStringArray("allowedIframeHosts");
|
|
18
|
+
DOMPurify.addHook("beforeSanitizeElements", removeUnsafeLinks);
|
|
19
|
+
const tags = ["link"];
|
|
20
|
+
if (hosts) {
|
|
21
|
+
tags.push("iframe");
|
|
22
|
+
DOMPurify.addHook("beforeSanitizeElements", removeUnsafeIframes(hosts));
|
|
23
|
+
}
|
|
24
|
+
return DOMPurify.sanitize(dom.outerHTML, {
|
|
25
|
+
ADD_TAGS: tags,
|
|
26
|
+
FORBID_TAGS: ["style"],
|
|
27
|
+
WHOLE_DOCUMENT: true,
|
|
28
|
+
RETURN_DOM: true
|
|
29
|
+
});
|
|
30
|
+
},
|
|
31
|
+
[config]
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export { useSanitizerTransformer };
|
|
36
|
+
//# sourceMappingURL=transformer.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformer.esm.js","sources":["../../../../src/reader/transformers/html/transformer.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport DOMPurify from 'dompurify';\nimport { useCallback, useMemo } from 'react';\n\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\n\nimport { Transformer } from '../transformer';\nimport { removeUnsafeIframes, removeUnsafeLinks } from './hooks';\n\n/**\n * Returns html sanitizer configuration\n */\nconst useSanitizerConfig = () => {\n const configApi = useApi(configApiRef);\n\n return useMemo(() => {\n return configApi.getOptionalConfig('techdocs.sanitizer');\n }, [configApi]);\n};\n\n/**\n * Returns a transformer that sanitizes the dom\n */\nexport const useSanitizerTransformer = (): Transformer => {\n const config = useSanitizerConfig();\n\n return useCallback(\n async (dom: Element) => {\n const hosts = config?.getOptionalStringArray('allowedIframeHosts');\n\n DOMPurify.addHook('beforeSanitizeElements', removeUnsafeLinks);\n const tags = ['link'];\n\n if (hosts) {\n tags.push('iframe');\n DOMPurify.addHook('beforeSanitizeElements', removeUnsafeIframes(hosts));\n }\n\n // using outerHTML as we want to preserve the html tag attributes (lang)\n return DOMPurify.sanitize(dom.outerHTML, {\n ADD_TAGS: tags,\n FORBID_TAGS: ['style'],\n WHOLE_DOCUMENT: true,\n RETURN_DOM: true,\n });\n },\n [config],\n );\n};\n"],"names":[],"mappings":";;;;;;AA2BA,MAAM,qBAAqB,MAAM;AAC/B,EAAM,MAAA,SAAA,GAAY,OAAO,YAAY,CAAA,CAAA;AAErC,EAAA,OAAO,QAAQ,MAAM;AACnB,IAAO,OAAA,SAAA,CAAU,kBAAkB,oBAAoB,CAAA,CAAA;AAAA,GACzD,EAAG,CAAC,SAAS,CAAC,CAAA,CAAA;AAChB,CAAA,CAAA;AAKO,MAAM,0BAA0B,MAAmB;AACxD,EAAA,MAAM,SAAS,kBAAmB,EAAA,CAAA;AAElC,EAAO,OAAA,WAAA;AAAA,IACL,OAAO,GAAiB,KAAA;AACtB,MAAM,MAAA,KAAA,GAAQ,iCAAQ,sBAAuB,CAAA,oBAAA,CAAA,CAAA;AAE7C,MAAU,SAAA,CAAA,OAAA,CAAQ,0BAA0B,iBAAiB,CAAA,CAAA;AAC7D,MAAM,MAAA,IAAA,GAAO,CAAC,MAAM,CAAA,CAAA;AAEpB,MAAA,IAAI,KAAO,EAAA;AACT,QAAA,IAAA,CAAK,KAAK,QAAQ,CAAA,CAAA;AAClB,QAAA,SAAA,CAAU,OAAQ,CAAA,wBAAA,EAA0B,mBAAoB,CAAA,KAAK,CAAC,CAAA,CAAA;AAAA,OACxE;AAGA,MAAO,OAAA,SAAA,CAAU,QAAS,CAAA,GAAA,CAAI,SAAW,EAAA;AAAA,QACvC,QAAU,EAAA,IAAA;AAAA,QACV,WAAA,EAAa,CAAC,OAAO,CAAA;AAAA,QACrB,cAAgB,EAAA,IAAA;AAAA,QAChB,UAAY,EAAA,IAAA;AAAA,OACb,CAAA,CAAA;AAAA,KACH;AAAA,IACA,CAAC,MAAM,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { SHADOW_DOM_STYLE_LOAD_EVENT } from '@backstage/plugin-techdocs-react';
|
|
2
|
+
|
|
3
|
+
const onCssReady = ({
|
|
4
|
+
onLoading,
|
|
5
|
+
onLoaded
|
|
6
|
+
}) => {
|
|
7
|
+
return (dom) => {
|
|
8
|
+
onLoading();
|
|
9
|
+
dom.addEventListener(
|
|
10
|
+
SHADOW_DOM_STYLE_LOAD_EVENT,
|
|
11
|
+
function handleShadowDomStyleLoad() {
|
|
12
|
+
onLoaded();
|
|
13
|
+
dom.removeEventListener(
|
|
14
|
+
SHADOW_DOM_STYLE_LOAD_EVENT,
|
|
15
|
+
handleShadowDomStyleLoad
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
return dom;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { onCssReady };
|
|
24
|
+
//# sourceMappingURL=onCssReady.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onCssReady.esm.js","sources":["../../../src/reader/transformers/onCssReady.ts"],"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 { SHADOW_DOM_STYLE_LOAD_EVENT } from '@backstage/plugin-techdocs-react';\nimport type { Transformer } from './transformer';\n\ntype OnCssReadyOptions = {\n onLoading: () => void;\n onLoaded: () => void;\n};\n\nexport const onCssReady = ({\n onLoading,\n onLoaded,\n}: OnCssReadyOptions): Transformer => {\n return dom => {\n onLoading();\n dom.addEventListener(\n SHADOW_DOM_STYLE_LOAD_EVENT,\n function handleShadowDomStyleLoad() {\n onLoaded();\n dom.removeEventListener(\n SHADOW_DOM_STYLE_LOAD_EVENT,\n handleShadowDomStyleLoad,\n );\n },\n );\n return dom;\n };\n};\n"],"names":[],"mappings":";;AAwBO,MAAM,aAAa,CAAC;AAAA,EACzB,SAAA;AAAA,EACA,QAAA;AACF,CAAsC,KAAA;AACpC,EAAA,OAAO,CAAO,GAAA,KAAA;AACZ,IAAU,SAAA,EAAA,CAAA;AACV,IAAI,GAAA,CAAA,gBAAA;AAAA,MACF,2BAAA;AAAA,MACA,SAAS,wBAA2B,GAAA;AAClC,QAAS,QAAA,EAAA,CAAA;AACT,QAAI,GAAA,CAAA,mBAAA;AAAA,UACF,2BAAA;AAAA,UACA,wBAAA;AAAA,SACF,CAAA;AAAA,OACF;AAAA,KACF,CAAA;AACA,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"removeMkdocsHeader.esm.js","sources":["../../../src/reader/transformers/removeMkdocsHeader.ts"],"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 type { Transformer } from './transformer';\n\nexport const removeMkdocsHeader = (): Transformer => {\n return dom => {\n // Remove the header\n dom.querySelector('.md-header')?.remove();\n\n return dom;\n };\n};\n"],"names":[],"mappings":"AAkBO,MAAM,qBAAqB,MAAmB;AACnD,EAAA,OAAO,CAAO,GAAA,KAAA;AAnBhB,IAAA,IAAA,EAAA,CAAA;AAqBI,IAAI,CAAA,EAAA,GAAA,GAAA,CAAA,aAAA,CAAc,YAAY,CAAA,KAA9B,IAAiC,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,MAAA,EAAA,CAAA;AAEjC,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
let ReactDOMPromise;
|
|
2
|
+
if (process.env.HAS_REACT_DOM_CLIENT) {
|
|
3
|
+
ReactDOMPromise = import('react-dom/client');
|
|
4
|
+
} else {
|
|
5
|
+
ReactDOMPromise = import('react-dom');
|
|
6
|
+
}
|
|
7
|
+
function renderReactElement(element, root) {
|
|
8
|
+
ReactDOMPromise.then((ReactDOM) => {
|
|
9
|
+
if ("createRoot" in ReactDOM) {
|
|
10
|
+
ReactDOM.createRoot(root).render(element);
|
|
11
|
+
} else {
|
|
12
|
+
ReactDOM.render(element, root);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { renderReactElement };
|
|
18
|
+
//# sourceMappingURL=renderReactElement.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderReactElement.esm.js","sources":["../../../src/reader/transformers/renderReactElement.ts"],"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\nlet ReactDOMPromise: Promise<\n typeof import('react-dom') | typeof import('react-dom/client')\n>;\nif (process.env.HAS_REACT_DOM_CLIENT) {\n ReactDOMPromise = import('react-dom/client');\n} else {\n ReactDOMPromise = import('react-dom');\n}\n\n/** @internal */\nexport function renderReactElement(element: JSX.Element, root: HTMLElement) {\n ReactDOMPromise.then(ReactDOM => {\n if ('createRoot' in ReactDOM) {\n ReactDOM.createRoot(root).render(element);\n } else {\n ReactDOM.render(element, root);\n }\n });\n}\n"],"names":[],"mappings":"AAgBA,IAAI,eAAA,CAAA;AAGJ,IAAI,OAAA,CAAQ,IAAI,oBAAsB,EAAA;AACpC,EAAA,eAAA,GAAkB,OAAO,kBAAkB,CAAA,CAAA;AAC7C,CAAO,MAAA;AACL,EAAA,eAAA,GAAkB,OAAO,WAAW,CAAA,CAAA;AACtC,CAAA;AAGgB,SAAA,kBAAA,CAAmB,SAAsB,IAAmB,EAAA;AAC1E,EAAA,eAAA,CAAgB,KAAK,CAAY,QAAA,KAAA;AAC/B,IAAA,IAAI,gBAAgB,QAAU,EAAA;AAC5B,MAAA,QAAA,CAAS,UAAW,CAAA,IAAI,CAAE,CAAA,MAAA,CAAO,OAAO,CAAA,CAAA;AAAA,KACnC,MAAA;AACL,MAAS,QAAA,CAAA,MAAA,CAAO,SAAS,IAAI,CAAA,CAAA;AAAA,KAC/B;AAAA,GACD,CAAA,CAAA;AACH;;;;"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
const rewriteDocLinks = () => {
|
|
2
|
+
return (dom) => {
|
|
3
|
+
const updateDom = (list, attributeName) => {
|
|
4
|
+
Array.from(list).filter((elem) => elem.hasAttribute(attributeName)).forEach((elem) => {
|
|
5
|
+
const elemAttribute = elem.getAttribute(attributeName);
|
|
6
|
+
if (elemAttribute) {
|
|
7
|
+
if (elemAttribute.match(/^https?:\/\//i)) {
|
|
8
|
+
elem.setAttribute("target", "_blank");
|
|
9
|
+
}
|
|
10
|
+
try {
|
|
11
|
+
const normalizedWindowLocation = normalizeUrl(
|
|
12
|
+
window.location.href
|
|
13
|
+
);
|
|
14
|
+
elem.setAttribute(
|
|
15
|
+
attributeName,
|
|
16
|
+
new URL(elemAttribute, normalizedWindowLocation).toString()
|
|
17
|
+
);
|
|
18
|
+
} catch (_e) {
|
|
19
|
+
elem.replaceWith(elem.textContent || elemAttribute);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
};
|
|
24
|
+
updateDom(Array.from(dom.getElementsByTagName("a")), "href");
|
|
25
|
+
return dom;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
function normalizeUrl(input) {
|
|
29
|
+
const url = new URL(input);
|
|
30
|
+
if (!url.pathname.endsWith("/") && !url.pathname.endsWith(".html")) {
|
|
31
|
+
url.pathname += "/";
|
|
32
|
+
}
|
|
33
|
+
return url.toString();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { normalizeUrl, rewriteDocLinks };
|
|
37
|
+
//# sourceMappingURL=rewriteDocLinks.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rewriteDocLinks.esm.js","sources":["../../../src/reader/transformers/rewriteDocLinks.ts"],"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 type { Transformer } from './transformer';\n\nexport const rewriteDocLinks = (): Transformer => {\n return dom => {\n const updateDom = <T extends Element>(\n list: Array<T>,\n attributeName: string,\n ): void => {\n Array.from(list)\n .filter(elem => elem.hasAttribute(attributeName))\n .forEach((elem: T) => {\n const elemAttribute = elem.getAttribute(attributeName);\n if (elemAttribute) {\n // if link is external, add target to open in a new window or tab\n if (elemAttribute.match(/^https?:\\/\\//i)) {\n elem.setAttribute('target', '_blank');\n }\n\n try {\n const normalizedWindowLocation = normalizeUrl(\n window.location.href,\n );\n elem.setAttribute(\n attributeName,\n new URL(elemAttribute, normalizedWindowLocation).toString(),\n );\n } catch (_e) {\n // Non-parseable links should be re-written as plain text.\n elem.replaceWith(elem.textContent || elemAttribute);\n }\n }\n });\n };\n\n updateDom(Array.from(dom.getElementsByTagName('a')), 'href');\n\n return dom;\n };\n};\n\n/** Make sure that the input url always ends with a '/' */\nexport function normalizeUrl(input: string): string {\n const url = new URL(input);\n\n if (!url.pathname.endsWith('/') && !url.pathname.endsWith('.html')) {\n url.pathname += '/';\n }\n\n return url.toString();\n}\n"],"names":[],"mappings":"AAkBO,MAAM,kBAAkB,MAAmB;AAChD,EAAA,OAAO,CAAO,GAAA,KAAA;AACZ,IAAM,MAAA,SAAA,GAAY,CAChB,IAAA,EACA,aACS,KAAA;AACT,MAAA,KAAA,CAAM,IAAK,CAAA,IAAI,CACZ,CAAA,MAAA,CAAO,CAAQ,IAAA,KAAA,IAAA,CAAK,YAAa,CAAA,aAAa,CAAC,CAAA,CAC/C,OAAQ,CAAA,CAAC,IAAY,KAAA;AACpB,QAAM,MAAA,aAAA,GAAgB,IAAK,CAAA,YAAA,CAAa,aAAa,CAAA,CAAA;AACrD,QAAA,IAAI,aAAe,EAAA;AAEjB,UAAI,IAAA,aAAA,CAAc,KAAM,CAAA,eAAe,CAAG,EAAA;AACxC,YAAK,IAAA,CAAA,YAAA,CAAa,UAAU,QAAQ,CAAA,CAAA;AAAA,WACtC;AAEA,UAAI,IAAA;AACF,YAAA,MAAM,wBAA2B,GAAA,YAAA;AAAA,cAC/B,OAAO,QAAS,CAAA,IAAA;AAAA,aAClB,CAAA;AACA,YAAK,IAAA,CAAA,YAAA;AAAA,cACH,aAAA;AAAA,cACA,IAAI,GAAA,CAAI,aAAe,EAAA,wBAAwB,EAAE,QAAS,EAAA;AAAA,aAC5D,CAAA;AAAA,mBACO,EAAI,EAAA;AAEX,YAAK,IAAA,CAAA,WAAA,CAAY,IAAK,CAAA,WAAA,IAAe,aAAa,CAAA,CAAA;AAAA,WACpD;AAAA,SACF;AAAA,OACD,CAAA,CAAA;AAAA,KACL,CAAA;AAEA,IAAA,SAAA,CAAU,MAAM,IAAK,CAAA,GAAA,CAAI,qBAAqB,GAAG,CAAC,GAAG,MAAM,CAAA,CAAA;AAE3D,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF,EAAA;AAGO,SAAS,aAAa,KAAuB,EAAA;AAClD,EAAM,MAAA,GAAA,GAAM,IAAI,GAAA,CAAI,KAAK,CAAA,CAAA;AAEzB,EAAI,IAAA,CAAC,GAAI,CAAA,QAAA,CAAS,QAAS,CAAA,GAAG,CAAK,IAAA,CAAC,GAAI,CAAA,QAAA,CAAS,QAAS,CAAA,OAAO,CAAG,EAAA;AAClE,IAAA,GAAA,CAAI,QAAY,IAAA,GAAA,CAAA;AAAA,GAClB;AAEA,EAAA,OAAO,IAAI,QAAS,EAAA,CAAA;AACtB;;;;"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const scrollIntoNavigation = () => {
|
|
2
|
+
return (dom) => {
|
|
3
|
+
setTimeout(() => {
|
|
4
|
+
const activeNavItems = dom == null ? void 0 : dom.querySelectorAll(`li.md-nav__item--active`);
|
|
5
|
+
if (activeNavItems.length !== 0) {
|
|
6
|
+
activeNavItems.forEach((activeNavItem) => {
|
|
7
|
+
const checkbox = activeNavItem == null ? void 0 : activeNavItem.querySelector("input");
|
|
8
|
+
if (!(checkbox == null ? void 0 : checkbox.checked)) {
|
|
9
|
+
checkbox == null ? void 0 : checkbox.click();
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
const lastItem = activeNavItems[activeNavItems.length - 1];
|
|
13
|
+
lastItem.scrollIntoView();
|
|
14
|
+
}
|
|
15
|
+
}, 200);
|
|
16
|
+
return dom;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export { scrollIntoNavigation };
|
|
21
|
+
//# sourceMappingURL=scrollIntoNavigation.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrollIntoNavigation.esm.js","sources":["../../../src/reader/transformers/scrollIntoNavigation.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 type { Transformer } from './transformer';\n\nexport const scrollIntoNavigation = (): Transformer => {\n return dom => {\n setTimeout(() => {\n const activeNavItems = dom?.querySelectorAll(`li.md-nav__item--active`);\n if (activeNavItems.length !== 0) {\n // expand all navigation items that are active\n activeNavItems.forEach(activeNavItem => {\n const checkbox = activeNavItem?.querySelector('input');\n if (!checkbox?.checked) {\n checkbox?.click();\n }\n });\n\n const lastItem = activeNavItems[activeNavItems.length - 1];\n lastItem.scrollIntoView();\n }\n }, 200);\n return dom;\n };\n};\n"],"names":[],"mappings":"AAkBO,MAAM,uBAAuB,MAAmB;AACrD,EAAA,OAAO,CAAO,GAAA,KAAA;AACZ,IAAA,UAAA,CAAW,MAAM;AACf,MAAM,MAAA,cAAA,GAAiB,2BAAK,gBAAiB,CAAA,CAAA,uBAAA,CAAA,CAAA,CAAA;AAC7C,MAAI,IAAA,cAAA,CAAe,WAAW,CAAG,EAAA;AAE/B,QAAA,cAAA,CAAe,QAAQ,CAAiB,aAAA,KAAA;AACtC,UAAM,MAAA,QAAA,GAAW,+CAAe,aAAc,CAAA,OAAA,CAAA,CAAA;AAC9C,UAAI,IAAA,EAAC,qCAAU,OAAS,CAAA,EAAA;AACtB,YAAU,QAAA,IAAA,IAAA,GAAA,KAAA,CAAA,GAAA,QAAA,CAAA,KAAA,EAAA,CAAA;AAAA,WACZ;AAAA,SACD,CAAA,CAAA;AAED,QAAA,MAAM,QAAW,GAAA,cAAA,CAAe,cAAe,CAAA,MAAA,GAAS,CAAC,CAAA,CAAA;AACzD,QAAA,QAAA,CAAS,cAAe,EAAA,CAAA;AAAA,OAC1B;AAAA,OACC,GAAG,CAAA,CAAA;AACN,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const simplifyMkdocsFooter = () => {
|
|
2
|
+
return (dom) => {
|
|
3
|
+
var _a, _b;
|
|
4
|
+
(_a = dom.querySelector(".md-footer .md-copyright")) == null ? void 0 : _a.remove();
|
|
5
|
+
(_b = dom.querySelector(".md-footer-copyright")) == null ? void 0 : _b.remove();
|
|
6
|
+
return dom;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export { simplifyMkdocsFooter };
|
|
11
|
+
//# sourceMappingURL=simplifyMkdocsFooter.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"simplifyMkdocsFooter.esm.js","sources":["../../../src/reader/transformers/simplifyMkdocsFooter.ts"],"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 type { Transformer } from './transformer';\n\nexport const simplifyMkdocsFooter = (): Transformer => {\n return dom => {\n // Remove new mkdocs copyright\n dom.querySelector('.md-footer .md-copyright')?.remove();\n // Remove old mkdocs copyright\n dom.querySelector('.md-footer-copyright')?.remove();\n return dom;\n };\n};\n"],"names":[],"mappings":"AAkBO,MAAM,uBAAuB,MAAmB;AACrD,EAAA,OAAO,CAAO,GAAA,KAAA;AAnBhB,IAAA,IAAA,EAAA,EAAA,EAAA,CAAA;AAqBI,IAAI,CAAA,EAAA,GAAA,GAAA,CAAA,aAAA,CAAc,0BAA0B,CAAA,KAA5C,IAA+C,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,MAAA,EAAA,CAAA;AAE/C,IAAI,CAAA,EAAA,GAAA,GAAA,CAAA,aAAA,CAAc,sBAAsB,CAAA,KAAxC,IAA2C,GAAA,KAAA,CAAA,GAAA,EAAA,CAAA,MAAA,EAAA,CAAA;AAC3C,IAAO,OAAA,GAAA,CAAA;AAAA,GACT,CAAA;AACF;;;;"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
var animations = () => `
|
|
2
|
+
/*================== Animations ==================*/
|
|
3
|
+
/*
|
|
4
|
+
Disable CSS animations on link colors as they lead to issues in dark mode.
|
|
5
|
+
The dark mode color theme is applied later and theirfore there is always an animation from light to dark mode when navigation between pages.
|
|
6
|
+
*/
|
|
7
|
+
.md-dialog, .md-nav__link, .md-footer__link, .md-typeset a, .md-typeset a::before, .md-typeset .headerlink {
|
|
8
|
+
transition: none;
|
|
9
|
+
}
|
|
10
|
+
`;
|
|
11
|
+
|
|
12
|
+
export { animations as default };
|
|
13
|
+
//# sourceMappingURL=animations.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animations.esm.js","sources":["../../../../../src/reader/transformers/styles/rules/animations.ts"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport default () => `\n/*================== Animations ==================*/\n/*\n Disable CSS animations on link colors as they lead to issues in dark mode.\n The dark mode color theme is applied later and theirfore there is always an animation from light to dark mode when navigation between pages.\n*/\n.md-dialog, .md-nav__link, .md-footer__link, .md-typeset a, .md-typeset a::before, .md-typeset .headerlink {\n transition: none;\n}\n`;\n"],"names":[],"mappings":"AAgBA,iBAAe,MAAM,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;;;;"}
|