import DocMarkdownBlock from '../../../components/docs/DocMarkdownBlock';
import { ParsedContent, separateFrontMatter } from '../../../helpers/markdown';
import { isSonarCloud } from '../../../helpers/system';
-import { PluginType } from '../../../types/plugins';
+import { InstalledPlugin, PluginType } from '../../../types/plugins';
import { getUrlsList } from '../navTreeUtils';
import getPages from '../pages';
import '../styles.css';
removeSideBarClass();
}
- getLanguagePluginsDocumentation = (tree: DocNavigationItem[]) => {
- return getInstalledPlugins(PluginType.Bundled)
- .then(plugins =>
- Promise.all(
- plugins.map(plugin => {
- if (plugin.documentationPath) {
- const matchArray = /^static\/(.*)/.exec(plugin.documentationPath);
-
- if (matchArray && matchArray.length > 1) {
- // eslint-disable-next-line promise/no-nesting
- return getPluginStaticFileContent(plugin.key, matchArray[1]).then(
- content => content,
- () => undefined
- );
- }
- }
- return undefined;
- })
- )
- )
- .then(contents => contents.filter(isDefined))
- .then(contents => {
- const regex = new RegExp(`/${LANGUAGES_BASE_URL}/\\w+/$`);
- const overridablePaths = getUrlsList(tree).filter(
- path => regex.test(path) && path !== `/${LANGUAGES_BASE_URL}/overview/`
- );
-
- const parsedContent: T.Dict<ParsedContent> = {};
-
- contents.forEach(content => {
- const parsed = separateFrontMatter(content);
- if (
- parsed &&
- parsed.frontmatter &&
- parsed.frontmatter.key &&
- overridablePaths.includes(`/${LANGUAGES_BASE_URL}/${parsed.frontmatter.key}/`)
- ) {
- parsedContent[`${LANGUAGES_BASE_URL}/${parsed.frontmatter.key}`] = parsed;
+ getLanguagePluginsDocumentation = async (tree: DocNavigationItem[]) => {
+ const plugins = await getInstalledPlugins(PluginType.Bundled).catch(
+ () => [] as InstalledPlugin[]
+ );
+
+ const pluginsWithDoc = await Promise.all(
+ plugins.map(plugin => {
+ if (plugin.documentationPath) {
+ const matchArray = /^static\/(.*)/.exec(plugin.documentationPath);
+
+ if (matchArray && matchArray.length > 1) {
+ return getPluginStaticFileContent(plugin.key, matchArray[1]).then(
+ content => ({ ...plugin, content }),
+ () => undefined
+ );
}
- });
+ }
+
+ return undefined;
+ })
+ );
+
+ const regex = new RegExp(`/${LANGUAGES_BASE_URL}/\\w+/$`);
+ const overridablePaths = getUrlsList(tree).filter(
+ path => regex.test(path) && path !== `/${LANGUAGES_BASE_URL}/overview/`
+ );
+
+ const parsedContent: T.Dict<ParsedContent> = {};
+
+ pluginsWithDoc.filter(isDefined).forEach(plugin => {
+ const parsed = separateFrontMatter(plugin.content);
+
+ if (plugin.issueTrackerUrl) {
+ // Inject issue tracker link
+ let issueTrackerLink = '## Issue Tracker';
+ issueTrackerLink += '\r\n';
+ issueTrackerLink += `Check the [issue tracker](${plugin.issueTrackerUrl}) for this language.`;
+ parsed.content = `${parsed.content}\r\n${issueTrackerLink}`;
+ }
+
+ if (
+ parsed?.frontmatter?.key &&
+ overridablePaths.includes(`/${LANGUAGES_BASE_URL}/${parsed.frontmatter.key}/`)
+ ) {
+ parsedContent[`${LANGUAGES_BASE_URL}/${parsed.frontmatter.key}`] = parsed;
+ }
+ });
- return parsedContent;
- });
+ return parsedContent;
};
render() {
);
}
- const page = pages.find(p => p.url === '/' + splat);
+ const page = pages.find(p => p.url === `/${splat}`);
const mainTitle = translate(
'documentation.page_title',
isSonarCloud() ? 'sonarcloud' : 'sonarqube'
import { request } from 'sonar-ui-common/helpers/request';
import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
import { isSonarCloud } from '../../../../helpers/system';
+import { InstalledPlugin } from '../../../../types/plugins';
import getPages from '../../pages';
import App from '../App';
jest.mock('../../../../api/plugins', () => ({
getInstalledPlugins: jest.fn().mockResolvedValue([
- { key: 'csharp', documentationPath: 'static/documentation.md' },
+ {
+ key: 'csharp',
+ documentationPath: 'static/documentation.md',
+ issueTrackerUrl: 'csharp_plugin_issue_tracker_url'
+ },
{ key: 'vbnet', documentationPath: 'Sstatic/documentation.md' },
{ key: 'vbnett', documentationPath: undefined }
- ])
+ ] as InstalledPlugin[])
}));
beforeEach(() => {
);
});
+it('should display the issue tracker url of the plugin if it exists', async () => {
+ (isSonarCloud as jest.Mock).mockReturnValue(false);
+
+ const wrapper = shallowRender({ params: { splat: 'analysis/languages/csharp/' } });
+ await waitAndUpdate(wrapper);
+
+ const { content } = (getPages as jest.Mock).mock.calls[0][0]['analysis/languages/csharp'];
+
+ expect(content).toContain('csharp_plugin_issue_tracker_url');
+});
+
function shallowRender(props: Partial<App['props']> = {}) {
return shallow(<App params={{ splat: 'lorem/ipsum' }} {...props} />);
}