Added support for clickable URLs
Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Updated `LogLine` component, which is used by the `LogViewer`, to turn URLs into clickable links. This feature is on by default
|
||||
@@ -54,6 +54,8 @@
|
||||
"dagre": "^0.8.5",
|
||||
"history": "^5.0.0",
|
||||
"immer": "^9.0.1",
|
||||
"linkify-react": "4.1.1",
|
||||
"linkifyjs": "4.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"pluralize": "^8.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
|
||||
@@ -14,12 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { renderInTestApp } from '@backstage/test-utils';
|
||||
import { AnsiLine, ChunkModifiers } from './AnsiProcessor';
|
||||
import {
|
||||
LogLine,
|
||||
calculateHighlightedChunks,
|
||||
findSearchResults,
|
||||
getModifierClasses,
|
||||
} from './LogLine';
|
||||
import React from 'react';
|
||||
|
||||
describe('getModifierClasses', () => {
|
||||
const classes = {
|
||||
@@ -354,3 +357,30 @@ describe('calculateHighlightedChunks', () => {
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('linkify', () => {
|
||||
it('should add links around URLs', async () => {
|
||||
const classes = {};
|
||||
const testText = new AnsiLine(1, [
|
||||
{
|
||||
text: 'Fetching template content from remote URL: https://github.com/backstage/software-templates/tree/main/scaffolder-templates/react-ssr-template/skeleton',
|
||||
modifiers: {},
|
||||
},
|
||||
]);
|
||||
|
||||
const rendered = await renderInTestApp(
|
||||
<LogLine
|
||||
line={testText}
|
||||
classes={classes as Parameters<typeof getModifierClasses>[0]}
|
||||
searchText=""
|
||||
/>,
|
||||
);
|
||||
const link = await rendered.findByText(
|
||||
'https://github.com/backstage/software-templates/tree/main/scaffolder-templates/react-ssr-template/skeleton',
|
||||
);
|
||||
expect(link).toBeInTheDocument();
|
||||
expect(link.getAttribute('href')).toContain(
|
||||
'https://github.com/backstage/software-templates/tree/main/scaffolder-templates/react-ssr-template/skeleton',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,6 +19,8 @@ import { AnsiChunk, AnsiLine, ChunkModifiers } from './AnsiProcessor';
|
||||
import startCase from 'lodash/startCase';
|
||||
import classnames from 'classnames';
|
||||
import { useStyles } from './styles';
|
||||
import Linkify from 'linkify-react';
|
||||
import { Link } from '../Link';
|
||||
|
||||
export function getModifierClasses(
|
||||
classes: ReturnType<typeof useStyles>,
|
||||
@@ -137,6 +139,21 @@ export function calculateHighlightedChunks(
|
||||
return chunks;
|
||||
}
|
||||
|
||||
const renderLink = ({
|
||||
attributes,
|
||||
content,
|
||||
}: {
|
||||
attributes: { [attr: string]: any };
|
||||
content: string;
|
||||
}) => {
|
||||
const { href, ...props } = attributes;
|
||||
return (
|
||||
<Link to={href} {...props}>
|
||||
{content}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
export interface LogLineProps {
|
||||
line: AnsiLine;
|
||||
classes: ReturnType<typeof useStyles>;
|
||||
@@ -169,7 +186,7 @@ export function LogLine({
|
||||
: classes.textHighlight),
|
||||
)}
|
||||
>
|
||||
{text}
|
||||
<Linkify options={{ render: renderLink }}>{text}</Linkify>
|
||||
</span>
|
||||
)),
|
||||
[chunks, highlightResultIndex, classes],
|
||||
|
||||
@@ -26,7 +26,7 @@ export default {
|
||||
|
||||
const exampleLog = `Starting up task with 3 steps
|
||||
Beginning step Fetch Skeleton + Template
|
||||
[32minfo[39m: Fetching template content from remote URL {"timestamp":"2021-12-03T15:47:11.625Z"}
|
||||
[32minfo[39m: Fetching template content from remote URL: https://github.com/backstage/software-templates/tree/main/scaffolder-templates/react-ssr-template/skeleton {"timestamp":"2021-12-03T15:47:11.625Z"}
|
||||
[32minfo[39m: Listing files and directories in template {"timestamp":"2021-12-03T15:47:12.797Z"}
|
||||
[32minfo[39m: Processing 33 template files/directories with input values {"component_id":"srnthsrthntrhsn","description":"rnthsrtnhssrthnrsthn","destination":{"host":"github.com","owner":"rtshnsrtmhrstmh","repo":"srtmhsrtmhrsthms"},"owner":"rstnhrstnhsrthn","timestamp":"2021-12-03T15:47:12.801Z"}
|
||||
[32minfo[39m: Writing file .editorconfig to template output path with mode 33188. {"timestamp":"2021-12-03T15:47:12.816Z"}
|
||||
|
||||
@@ -4088,6 +4088,8 @@ __metadata:
|
||||
dagre: ^0.8.5
|
||||
history: ^5.0.0
|
||||
immer: ^9.0.1
|
||||
linkify-react: 4.1.1
|
||||
linkifyjs: 4.1.1
|
||||
lodash: ^4.17.21
|
||||
msw: ^1.0.0
|
||||
pluralize: ^8.0.0
|
||||
@@ -29116,6 +29118,23 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"linkify-react@npm:4.1.1":
|
||||
version: 4.1.1
|
||||
resolution: "linkify-react@npm:4.1.1"
|
||||
peerDependencies:
|
||||
linkifyjs: ^4.0.0
|
||||
react: ">= 15.0.0"
|
||||
checksum: 2f213f134055d4a11587e7e0bc3e0ef7e372c8c0d1419dbc5bb8e3a280f325bea9ad9d8d6017fd79f8f86fa4127ed75cbe6f320ef9d92a00ae510f320db0f408
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"linkifyjs@npm:4.1.1":
|
||||
version: 4.1.1
|
||||
resolution: "linkifyjs@npm:4.1.1"
|
||||
checksum: 312b75ec9bc6e7107f2b70e50682e8baccd7b94a64bf7b88cecd352032126b0d6fa7ea41394c417a178c718caa79b70e6ab3570eee7b96a12399689d666e68fb
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lint-staged@npm:^13.0.0":
|
||||
version: 13.2.0
|
||||
resolution: "lint-staged@npm:13.2.0"
|
||||
|
||||
Reference in New Issue
Block a user