diff --git a/.changeset/lemon-cherries-sleep.md b/.changeset/lemon-cherries-sleep.md new file mode 100644 index 0000000000..b640d5312c --- /dev/null +++ b/.changeset/lemon-cherries-sleep.md @@ -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 diff --git a/packages/core-components/package.json b/packages/core-components/package.json index a885afc8c7..942b38cbf2 100644 --- a/packages/core-components/package.json +++ b/packages/core-components/package.json @@ -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", diff --git a/packages/core-components/src/components/LogViewer/LogLine.test.tsx b/packages/core-components/src/components/LogViewer/LogLine.test.tsx index c5fd6e39ca..73c58d1e3e 100644 --- a/packages/core-components/src/components/LogViewer/LogLine.test.tsx +++ b/packages/core-components/src/components/LogViewer/LogLine.test.tsx @@ -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( + [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', + ); + }); +}); diff --git a/packages/core-components/src/components/LogViewer/LogLine.tsx b/packages/core-components/src/components/LogViewer/LogLine.tsx index c8ff5cbceb..951b2154bf 100644 --- a/packages/core-components/src/components/LogViewer/LogLine.tsx +++ b/packages/core-components/src/components/LogViewer/LogLine.tsx @@ -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, @@ -137,6 +139,21 @@ export function calculateHighlightedChunks( return chunks; } +const renderLink = ({ + attributes, + content, +}: { + attributes: { [attr: string]: any }; + content: string; +}) => { + const { href, ...props } = attributes; + return ( + + {content} + + ); +}; + export interface LogLineProps { line: AnsiLine; classes: ReturnType; @@ -169,7 +186,7 @@ export function LogLine({ : classes.textHighlight), )} > - {text} + {text} )), [chunks, highlightResultIndex, classes], diff --git a/packages/core-components/src/components/LogViewer/LogViewer.stories.tsx b/packages/core-components/src/components/LogViewer/LogViewer.stories.tsx index 255e1d03b8..d244ef7715 100644 --- a/packages/core-components/src/components/LogViewer/LogViewer.stories.tsx +++ b/packages/core-components/src/components/LogViewer/LogViewer.stories.tsx @@ -26,7 +26,7 @@ export default { const exampleLog = `Starting up task with 3 steps Beginning step Fetch Skeleton + Template -info: Fetching template content from remote URL {"timestamp":"2021-12-03T15:47:11.625Z"} +info: 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"} info: Listing files and directories in template {"timestamp":"2021-12-03T15:47:12.797Z"} info: 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"} info: Writing file .editorconfig to template output path with mode 33188. {"timestamp":"2021-12-03T15:47:12.816Z"} diff --git a/yarn.lock b/yarn.lock index b75e039709..160da14576 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"