techdocs-plugin: add feedback link for Github/Gitlab source repos
Signed-off-by: Chongyang Adrian, Ke <ftt.adrian.ke@grabtaxi.com>
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
---
|
||||
'@backstage/plugin-techdocs': minor
|
||||
---
|
||||
|
||||
Add feedback link icon in Techdocs Reader that directs to Gitlab or Github repo issue page with prefilled title and source link.
|
||||
For link to appear, requires repo_url and edit_uri to be filled in mkdocs.yml, as per https://www.mkdocs.org/user-guide/configuration. edit_uri will need to be specified for self-hosted Gitlab/Github with different hostnames.
|
||||
Gitlab or Github detection checks for 'gitlab' or 'github' in hostname of source in repo_url;
|
||||
additionally 'techdocs.feedback.gitlab' and '.github' in app config can be used to specify hostnames that should be recognised as the respective Git hosting for the feedback link.
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { EntityName } from '@backstage/catalog-model';
|
||||
import { useApi } from '@backstage/core';
|
||||
import { useApi, configApiRef } from '@backstage/core';
|
||||
import { BackstageTheme } from '@backstage/theme';
|
||||
import { useTheme } from '@material-ui/core';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
@@ -31,6 +31,7 @@ import transformer, {
|
||||
rewriteDocLinks,
|
||||
sanitizeDOM,
|
||||
simplifyMkdocsFooter,
|
||||
addGitFeedbackLink,
|
||||
} from '../transformers';
|
||||
import { TechDocsNotFound } from './TechDocsNotFound';
|
||||
import TechDocsProgressBar from './TechDocsProgressBar';
|
||||
@@ -52,6 +53,7 @@ export const Reader = ({ entityId, onReady }: Props) => {
|
||||
const [loadedPath, setLoadedPath] = useState('');
|
||||
const [atInitialLoad, setAtInitialLoad] = useState(true);
|
||||
const [newerDocsExist, setNewerDocsExist] = useState(false);
|
||||
const configApi = useApi(configApiRef);
|
||||
|
||||
const {
|
||||
value: isSynced,
|
||||
@@ -142,6 +144,7 @@ export const Reader = ({ entityId, onReady }: Props) => {
|
||||
rewriteDocLinks(),
|
||||
removeMkdocsHeader(),
|
||||
simplifyMkdocsFooter(),
|
||||
addGitFeedbackLink(configApi),
|
||||
injectCss({
|
||||
css: `
|
||||
body {
|
||||
@@ -313,6 +316,7 @@ export const Reader = ({ entityId, onReady }: Props) => {
|
||||
name,
|
||||
newerDocsExist,
|
||||
isSynced,
|
||||
configApi,
|
||||
]);
|
||||
|
||||
// docLoadError not considered an error state if sync request is still ongoing
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createTestShadowDom } from '../../test-utils';
|
||||
import { addGitFeedbackLink } from './addGitFeedbackLink';
|
||||
|
||||
const configApi = {
|
||||
getOptionalString: function getOptionalString(key: string) {
|
||||
return key === 'gitlab' ? 'gitlab.com' : 'github.com';
|
||||
},
|
||||
};
|
||||
|
||||
describe('addGitFeedbackLink', () => {
|
||||
it('adds a feedback link when a Gitlab source edit link is available', () => {
|
||||
const shadowDom = createTestShadowDom(
|
||||
`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<article class="md-content__inner">
|
||||
<h1>HeaderText</h1>
|
||||
<a title="Edit this page" href="https://gitlab.com/reponame/username/docs/TestDoc.md"></>
|
||||
</article>
|
||||
</html>
|
||||
`,
|
||||
{
|
||||
preTransformers: [addGitFeedbackLink(configApi)],
|
||||
postTransformers: [],
|
||||
},
|
||||
);
|
||||
|
||||
expect(shadowDom.querySelector('#git-feedback-link')).toBeTruthy();
|
||||
expect(
|
||||
(shadowDom.querySelector('#git-feedback-link') as HTMLLinkElement)!.href,
|
||||
).toEqual(
|
||||
'https://gitlab.com/reponame/username/issues/new?issue[title]=Documentation%20Feedback%3A%20HeaderText&issue[description]=Page%20source%3A%0Ahttps%3A%2F%2Fgitlab.com%2Freponame%2Fusername%2Fdocs%2FTestDoc.md%0A%0AFeedback%3A',
|
||||
);
|
||||
});
|
||||
|
||||
it('adds a feedback link when a Github source edit link is available', () => {
|
||||
const shadowDom = createTestShadowDom(
|
||||
`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<article class="md-content__inner">
|
||||
<h1>HeaderText</h1>
|
||||
<a title="Edit this page" href="https://github.com/reponame/username/docs/TestDoc.md"></>
|
||||
</article>
|
||||
</html>
|
||||
`,
|
||||
{
|
||||
preTransformers: [addGitFeedbackLink(configApi)],
|
||||
postTransformers: [],
|
||||
},
|
||||
);
|
||||
|
||||
expect(shadowDom.querySelector('#git-feedback-link')).toBeTruthy();
|
||||
expect(
|
||||
(shadowDom.querySelector('#git-feedback-link') as HTMLLinkElement)!.href,
|
||||
).toEqual(
|
||||
'https://github.com/reponame/username/issues/new?title=Documentation%20Feedback%3A%20HeaderText&body=Page%20source%3A%0Ahttps%3A%2F%2Fgithub.com%2Freponame%2Fusername%2Fdocs%2FTestDoc.md%0A%0AFeedback%3A',
|
||||
);
|
||||
});
|
||||
|
||||
it('does not add a feedback link when no source edit link is available', () => {
|
||||
const shadowDom = createTestShadowDom(
|
||||
`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<article class="md-content__inner">
|
||||
<h1 id="conveyor-pipelines">Conveyor Pipelines<a class="headerlink" href="http://headerlink.com">¶</a></h1>
|
||||
</article>
|
||||
</html>
|
||||
`,
|
||||
{
|
||||
preTransformers: [addGitFeedbackLink(configApi)],
|
||||
postTransformers: [],
|
||||
},
|
||||
);
|
||||
|
||||
expect(shadowDom.querySelector('#git-feedback-link')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('does not add a feedback link when a Gitlab or Github source edit link is not available', () => {
|
||||
const shadowDom = createTestShadowDom(
|
||||
`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<article class="md-content__inner">
|
||||
<h1 id="conveyor-pipelines">Conveyor Pipelines<a class="headerlink" href="http://headerlink.com">¶</a></h1>
|
||||
<a href="https://not-a-git-provider.com/reponame/username/docs/TestDoc.md"/>
|
||||
</article>
|
||||
</html>
|
||||
`,
|
||||
{
|
||||
preTransformers: [addGitFeedbackLink(configApi)],
|
||||
postTransformers: [],
|
||||
},
|
||||
);
|
||||
|
||||
expect(shadowDom.querySelector('#git-feedback-link')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2021 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { Transformer } from './index';
|
||||
import FeedbackOutlinedIcon from '@material-ui/icons/FeedbackOutlined';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
|
||||
// requires repo
|
||||
export const addGitFeedbackLink = (configApi: any): Transformer => {
|
||||
return dom => {
|
||||
// attempting to use selectors that are more likely to be static as MkDocs updates over time
|
||||
const sourceAnchor = dom.querySelector(
|
||||
'[title="Edit this page"]',
|
||||
) as HTMLAnchorElement;
|
||||
|
||||
// don't show if edit link not available in raw page
|
||||
if (!sourceAnchor || !sourceAnchor.href) {
|
||||
return dom;
|
||||
}
|
||||
let gitHost = '';
|
||||
|
||||
const sourceURL = new URL(sourceAnchor.href);
|
||||
const githubHosts = configApi
|
||||
.getConfigArray('integrations.github')
|
||||
.map((integration: any) => integration.data.host);
|
||||
const gitlabHosts = configApi
|
||||
.getConfigArray('integrations.gitlab')
|
||||
.map((integration: any) => integration.data.host);
|
||||
|
||||
// don't show if can't identify edit link hostname as a gitlab/github hosting
|
||||
if (
|
||||
githubHosts.includes(sourceURL.hostname) ||
|
||||
sourceURL.origin.includes('github')
|
||||
) {
|
||||
gitHost = 'github';
|
||||
} else if (
|
||||
gitlabHosts.includes(sourceURL.hostname) ||
|
||||
sourceURL.origin.includes('gitlab')
|
||||
) {
|
||||
gitHost = 'gitlab';
|
||||
} else {
|
||||
return dom;
|
||||
}
|
||||
|
||||
// topmost h1 only contains title for whole page
|
||||
const title = (dom.querySelector('article>h1') as HTMLElement).childNodes[0]
|
||||
.textContent;
|
||||
const issueTitle = encodeURIComponent(`Documentation Feedback: ${title}`);
|
||||
const issueDesc = encodeURIComponent(
|
||||
`Page source:\n${sourceAnchor.href}\n\nFeedback:`,
|
||||
);
|
||||
const repoPath = sourceURL.pathname.split('/').slice(0, 3).join('/');
|
||||
|
||||
const feedbackLink = sourceAnchor.cloneNode() as HTMLAnchorElement;
|
||||
switch (gitHost) {
|
||||
case 'gitlab':
|
||||
feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?issue[title]=${issueTitle}&issue[description]=${issueDesc}`;
|
||||
break;
|
||||
case 'github':
|
||||
feedbackLink.href = `${sourceURL.origin}${repoPath}/issues/new?title=${issueTitle}&body=${issueDesc}`;
|
||||
break;
|
||||
default:
|
||||
return dom;
|
||||
}
|
||||
ReactDOM.render(React.createElement(FeedbackOutlinedIcon), feedbackLink);
|
||||
feedbackLink.style.paddingLeft = '5px';
|
||||
feedbackLink.title = 'Leave feedback for this page';
|
||||
feedbackLink.id = 'git-feedback-link';
|
||||
sourceAnchor?.insertAdjacentElement('beforebegin', feedbackLink);
|
||||
return dom;
|
||||
};
|
||||
};
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
export * from './addBaseUrl';
|
||||
export * from './addGitFeedbackLink';
|
||||
export * from './rewriteDocLinks';
|
||||
export * from './addLinkClickListener';
|
||||
export * from './removeMkdocsHeader';
|
||||
|
||||
Reference in New Issue
Block a user