All files / modules/10-common/components/LinkifyText LinkifyText.tsx

100% Statements 25/25
88.89% Branches 8/9
100% Functions 3/3
100% Lines 23/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69              309x 309x                   309x 58x 58x 58x     58x 7x   7x   7x 6x     7x   7x     58x 52x     58x     309x 6x 6x 6x     10x 3x           7x                    
/*
 * Copyright 2021 Harness Inc. All rights reserved.
 * Use of this source code is governed by the PolyForm Shield 1.0.0 license
 * that can be found in the licenses directory at the root of this repository, also available at
 * https://polyformproject.org/wp-content/uploads/2020/06/PolyForm-Shield-1.0.0.txt.
 */
 
import React from 'react'
import { Text, TextProps } from '@wings-software/uicore'
 
interface BrokenText {
  type: 'TEXT' | 'URL'
  content: string
}
 
/**
 * adopted from https://github.com/nteract/ansi-to-react/blob/master/src/index.ts#L104
 */
export const breakOnLinks = (content = ''): BrokenText[] => {
  const LINK_REGEX = /(\s*|^)(https?:\/\/(?:www\.|(?!www))[^\s.]+\.[^\s]{2,}|www\.[^\s]+\.[^\s]{2,})/g
  const nodes: BrokenText[] = []
  let index = 0
  let match: RegExpExecArray | null
 
  while ((match = LINK_REGEX.exec(content)) !== null) {
    const [, pre, url] = match
 
    const startIndex = match.index + pre.length
 
    if (startIndex > index) {
      nodes.push({ type: 'TEXT', content: content.substring(index, startIndex) })
    }
 
    nodes.push({ type: 'URL', content: url })
 
    index = LINK_REGEX.lastIndex
  }
 
  if (index < content.length) {
    nodes.push({ type: 'TEXT', content: content.substring(index) })
  }
 
  return nodes
}
 
export const LinkifyText: React.FC<{ content?: string; textProps?: TextProps; linkStyles?: string }> = props => {
  const { content, textProps = {}, linkStyles = '' } = props
  const textItems: BrokenText[] = breakOnLinks(content)
  return (
    <>
      {textItems.map((textItem, index) => {
        if (textItem.type === 'URL') {
          return (
            <a key={index} href={textItem.content} target="_blank" rel="noreferrer" className={linkStyles}>
              {textItem.content}
            </a>
          )
        } else {
          return (
            <Text key={index} {...textProps} inline>
              {textItem.content}
            </Text>
          )
        }
      })}
    </>
  )
}