Skip to content

Commit

Permalink
Merge pull request #623 from lsst-ts/tickets/DM-43471
Browse files Browse the repository at this point in the history
Fix the feature to convert Jira ticket names into hyperlinks
  • Loading branch information
sebastian-aranda authored Mar 26, 2024
2 parents 09c78a9 + b52e53d commit 629efe6
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 27 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Version History
v5.30.0
-------

* Fix the feature to convert Jira ticket names into hyperlinks `<https://github.com/lsst-ts/LOVE-frontend/pull/623>`_
* Fix content cleaning on RichTextEditor `<https://github.com/lsst-ts/LOVE-frontend/pull/622>`_
* Update missing reference to the jira service `<https://github.com/lsst-ts/LOVE-frontend/pull/621>`_
* Add Night Report implementation `<https://github.com/lsst-ts/LOVE-frontend/pull/619>`_
Expand Down
39 changes: 30 additions & 9 deletions love/src/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ if (Array.prototype.flat === undefined) {
});
}

/**
* Applies a series of functions to a value, passing the result of each function as the argument to the next function.
*
* @param {...Function} fns - The functions to be applied.
* @returns {Function} A new function that applies the given functions in sequence.
*/
export const pipe =
(...fns) =>
(x) =>
fns.reduce((v, f) => f(v), x);

/**
MIT License
Copyright (c) Luke Edwards <[email protected]> (lukeed.com)
Expand Down Expand Up @@ -1911,15 +1922,6 @@ export function htmlToJiraMarkdown(html) {
return `{code}${p1}{code}`;
});

// Parse Jira tickets names
// At this point, hyperlinks have been already parsed.
// The following regex allows us to parse Jira tickets names that are not hyperlinks
const jiraTicketRegexString = `(?<!\\[[^\\]]*)(${AUTO_HYPERLINK_JIRA_PROJECTS.join('|')})+-\\d+\\b`;
const jiraTicketRegex = new RegExp(jiraTicketRegexString, 'g');
markdown = markdown.replace(jiraTicketRegex, (match) => {
return `[${match}|${JIRA_TICKETS_BASE_URL}/${match}]`;
});

// TODO: DM-41265
// markdown = markdown.replace(/<ul>|<\/ul>|<ol>|<\/ol>|<li>/g, '');
// markdown = markdown.replace(/<\/li>/g, '\n');
Expand Down Expand Up @@ -2035,6 +2037,25 @@ export function jiraMarkdownToHtml(markdown, options = { codeFriendly: true }) {
return html;
}

/**
* Converts Jira ticket names to hyperlinks.
* Jira ticket names are expected to be in the format <JIRA_PROJECT>-<NUMBER>.
* The JIRA_PROJECT is expected to be one of the projects defined in the AUTO_HYPERLINK_JIRA_PROJECTS constant.
* This function only conver Jira ticket names that are not hyperlinks.
* THE INPUT TEXT MUST BE IN MARKDOWN FORMAT.
* @param {string} markdown - The text in markdown format containing Jira ticket names.
* @returns {string} - The text with Jira ticket names converted to hyperlinks in markdown format.
*/
export function convertJiraTicketNamesToHyperlinks(markdown) {
// The following regex matches Jira tickets that are not inside markdown hyperlinks
// by using a negative lookbehind assertion.
const jiraTicketRegexString = `(?<!\\[[^\\]]*)(${AUTO_HYPERLINK_JIRA_PROJECTS.join('|')})+-\\d+\\b`;
const jiraTicketRegex = new RegExp(jiraTicketRegexString, 'g');
return markdown.replace(jiraTicketRegex, (match) => {
return `[${match}|${JIRA_TICKETS_BASE_URL}/${match}]`;
});
}

/**
* Function to transform an html string to an array of tokens
* @param {string} html html string to be transformed
Expand Down
32 changes: 15 additions & 17 deletions love/src/Utils.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { htmlToJiraMarkdown, jiraMarkdownToHtml } from './Utils';
import { htmlToJiraMarkdown, jiraMarkdownToHtml, convertJiraTicketNamesToHyperlinks } from './Utils';
import { JIRA_TICKETS_BASE_URL } from './Config';

describe('htmlToJiraMarkdown', () => {
Expand Down Expand Up @@ -26,22 +26,6 @@ describe('htmlToJiraMarkdown', () => {
expect(htmlToJiraMarkdown(input)).toEqual(expectedOutput);
});

it('should convert Jira tickets to links', () => {
const input =
'<p>This is a string with mixed content</p>' +
'<h1>This is a heading.</h1>' +
'<p>This is an already formatted link <a href="https://jira.lsstcorp.org/browse/DM-41184" rel="noopener noreferrer" target="_blank">DM-41184</a>.</p>' +
'<p>This is a ticket name not yet formatted DM-41184.</p>' +
'<p>This is an already parsed link [DM-41184|https://jira.lsstcorp.org/browse/DM-41184].</p>';
const expectedOutput =
'This is a string with mixed content\r\n' +
'h1. This is a heading.\r\n' +
'This is an already formatted link [DM-41184|https://jira.lsstcorp.org/browse/DM-41184].\r\n' +
`This is a ticket name not yet formatted [DM-41184|${JIRA_TICKETS_BASE_URL}/DM-41184].\r\n` +
'This is an already parsed link [DM-41184|https://jira.lsstcorp.org/browse/DM-41184].\r\n';
expect(htmlToJiraMarkdown(input)).toEqual(expectedOutput);
});

it('should handle indentations', () => {
const input =
'<p>This is a string with mixed content</p>' +
Expand Down Expand Up @@ -144,3 +128,17 @@ describe('jiraMarkdownToHtml', () => {
expect(jiraMarkdownToHtml(input, options)).toEqual(expectedOutput);
});
});

describe('convertJiraTicketNamesToHyperlinks', () => {
it('should convert Jira tickets to hyperlinks', () => {
const input =
'This is a string with mixed content.\r\n' +
'This is a ticket name not yet formatted DM-41184.\r\n' +
'This is an already parsed link [DM-41184|https://jira.lsstcorp.org/browse/DM-41184].\r\n';
const expectedOutput =
'This is a string with mixed content.\r\n' +
`This is a ticket name not yet formatted [DM-41184|${JIRA_TICKETS_BASE_URL}/DM-41184].\r\n` +
'This is an already parsed link [DM-41184|https://jira.lsstcorp.org/browse/DM-41184].\r\n';
expect(convertJiraTicketNamesToHyperlinks(input)).toEqual(expectedOutput);
});
});
5 changes: 4 additions & 1 deletion love/src/components/OLE/NonExposure/NonExposure.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ import ManagerInterface, {
jiraMarkdownToHtml,
getObsDayFromDate,
formatOLETimeOfIncident,
pipe,
convertJiraTicketNamesToHyperlinks,
} from 'Utils';

import OrderableTable from 'components/GeneralPurpose/OrderableTable/OrderableTable';
Expand Down Expand Up @@ -215,7 +217,8 @@ export default class NonExposure extends Component {
className: styles.tableHead,
render: (value, row) => {
const files = getFilesURLs(row.urls);
const parsedValue = jiraMarkdownToHtml(value);
// We ensure to convert Jira ticket names to hyperlinks before converting the markdown to html
const parsedValue = pipe(convertJiraTicketNamesToHyperlinks, jiraMarkdownToHtml)(value);
return (
<>
<div
Expand Down

0 comments on commit 629efe6

Please sign in to comment.