diff --git a/app/gui/src/project-view/components/visualizations/TableVisualization.vue b/app/gui/src/project-view/components/visualizations/TableVisualization.vue
index ecbd3ec15636..c2573f35d8a3 100644
--- a/app/gui/src/project-view/components/visualizations/TableVisualization.vue
+++ b/app/gui/src/project-view/components/visualizations/TableVisualization.vue
@@ -8,7 +8,6 @@ import {
} from '@/components/visualizations/TableVisualization/tableVizToolbar'
import { Ast } from '@/util/ast'
import { Pattern } from '@/util/ast/match'
-import { LINKABLE_URL_REGEX } from '@/util/link'
import { useVisualizationConfig } from '@/util/visualizationBuiltins'
import type {
CellClassParams,
@@ -20,7 +19,7 @@ import type {
} from 'ag-grid-enterprise'
import { computed, onMounted, ref, shallowRef, watchEffect, type Ref } from 'vue'
import { TableVisualisationTooltip } from './TableVisualization/TableVisualisationTooltip'
-import { getCellValueType, isNumericType } from './TableVisualization/tableVizUtils'
+import { formatText, getCellValueType, isNumericType } from './TableVisualization/tableVizUtils'
export const name = 'Table'
export const icon = 'table'
@@ -193,54 +192,6 @@ function formatNumber(params: ICellRendererParams) {
return needsGrouping ? numberFormatGroupped.format(value) : numberFormat.format(value)
}
-function formatText(params: ICellRendererParams) {
- const htmlEscaped = params.value
- .replaceAll('&', '&')
- .replaceAll('<', '<')
- .replaceAll('>', '>')
-
- if (textFormatterSelected.value === 'off') {
- const replaceLinks = replaceLinksWithTag(htmlEscaped)
- return replaceLinks.replace(/^\s+|\s+$/g, ' ')
- }
-
- const partialMappings = {
- '\r': '␍
',
- '\n': '␊
',
- '\t': '→ |',
- }
- const fullMappings = {
- '\r': '␍
',
- '\n': '␊
',
- '\t': '→ |',
- }
-
- const replaceSpaces =
- textFormatterSelected.value === 'full' ?
- htmlEscaped.replaceAll(' ', '·')
- : htmlEscaped.replace(/ \s+|^ +| +$/g, function (match: string) {
- return `${match.replaceAll(' ', '·')}`
- })
-
- const replaceLinks = replaceLinksWithTag(replaceSpaces)
-
- const replaceReturns = replaceLinks.replace(
- /\r\n/g,
- '␍␊
',
- )
-
- const renderOtherWhitespace = (match: string) => {
- return textFormatterSelected.value === 'full' && match != ' ' ?
- '☐'
- : match
- }
- const newString = replaceReturns.replace(/[\s]/g, function (match: string) {
- const mapping = textFormatterSelected.value === 'full' ? fullMappings : partialMappings
- return mapping[match as keyof typeof mapping] || renderOtherWhitespace(match)
- })
- return ` ${newString} `
-}
-
function setRowLimit(newRowLimit: number) {
if (newRowLimit !== rowLimit.value) {
rowLimit.value = newRowLimit
@@ -252,13 +203,6 @@ function setRowLimit(newRowLimit: number) {
}
}
-function replaceLinksWithTag(str: string) {
- return str.replace(
- LINKABLE_URL_REGEX,
- (url: string) => `${url}`,
- )
-}
-
function escapeHTML(str: string) {
const mapping: Record = {
'&': '&',
@@ -286,7 +230,8 @@ function cellRenderer(params: ICellRendererParams) {
else if (params.value === undefined) return ''
else if (params.value === '') return 'Empty'
else if (typeof params.value === 'number') return formatNumber(params)
- else if (typeof params.value === 'string') return formatText(params)
+ else if (typeof params.value === 'string')
+ return formatText(params.value, textFormatterSelected.value)
else if (Array.isArray(params.value)) return `[Vector ${params.value.length} items]`
else if (typeof params.value === 'object') {
const valueType = params.value?.type
diff --git a/app/gui/src/project-view/components/visualizations/TableVisualization/tableVizUtils.ts b/app/gui/src/project-view/components/visualizations/TableVisualization/tableVizUtils.ts
index f3ab1cb5fa3e..b3a5107df9fe 100644
--- a/app/gui/src/project-view/components/visualizations/TableVisualization/tableVizUtils.ts
+++ b/app/gui/src/project-view/components/visualizations/TableVisualization/tableVizUtils.ts
@@ -1,3 +1,6 @@
+import { LINKABLE_URL_REGEX } from '@/util/link'
+import { TextFormatOptions } from '../TableVisualization.vue'
+
export const getCellValueType = (item: string) => {
switch (true) {
case isInteger(item):
@@ -35,3 +38,55 @@ export const isNumericType = (valueType: string) => {
const isNumber = ['Integer', 'Float', 'Decimal', 'Byte']
return isNumber.indexOf(valueType) != -1
}
+
+const replaceLinksWithTag = (str: string) => {
+ return str.replace(
+ LINKABLE_URL_REGEX,
+ (url: string) => `${url}`,
+ )
+}
+
+export const formatText = (input: string, textFormatterSelected: TextFormatOptions) => {
+ const htmlEscaped = input.replaceAll('<', '<').replaceAll('>', '>')
+
+ if (textFormatterSelected === 'off') {
+ const replaceLinks = replaceLinksWithTag(htmlEscaped)
+ return replaceLinks.replace(/^\s+|\s+$/g, ' ')
+ }
+
+ const partialMappings = {
+ '\r': '␍
',
+ '\n': '␊
',
+ '\t': '→ |',
+ }
+ const fullMappings = {
+ '\r': '␍
',
+ '\n': '␊
',
+ '\t': '→ |',
+ }
+
+ const replaceSpaces =
+ textFormatterSelected === 'full' ?
+ htmlEscaped.replaceAll(' ', '·')
+ : htmlEscaped.replace(/ \s+|^ +| +$/g, function (match: string) {
+ return `${match.replaceAll(' ', '·')}`
+ })
+
+ const replaceLinks = replaceLinksWithTag(replaceSpaces)
+
+ const replaceReturns = replaceLinks.replace(
+ /\r\n/g,
+ '␍␊
',
+ )
+
+ const renderOtherWhitespace = (match: string) => {
+ return textFormatterSelected === 'full' && match != ' ' ?
+ '☐'
+ : match
+ }
+ const newString = replaceReturns.replace(/[\s]/g, function (match: string) {
+ const mapping = textFormatterSelected === 'full' ? fullMappings : partialMappings
+ return mapping[match as keyof typeof mapping] || renderOtherWhitespace(match)
+ })
+ return ` ${newString} `
+}
diff --git a/app/gui/src/project-view/components/visualizations/__tests__/tableVizUtilsTests.spec.ts b/app/gui/src/project-view/components/visualizations/__tests__/tableVizUtilsTests.spec.ts
index 1c5ee33f76da..479af6aa83c6 100644
--- a/app/gui/src/project-view/components/visualizations/__tests__/tableVizUtilsTests.spec.ts
+++ b/app/gui/src/project-view/components/visualizations/__tests__/tableVizUtilsTests.spec.ts
@@ -1,5 +1,5 @@
import { expect, test } from 'vitest'
-import { getCellValueType, isNumericType } from '../TableVisualization/tableVizUtils'
+import { formatText, getCellValueType, isNumericType } from '../TableVisualization/tableVizUtils'
test('getCellValueType (Text)', () => {
expect(getCellValueType('Alan')).toEqual('Char')
@@ -40,3 +40,15 @@ test('isNumericType (Numeric Type)', () => {
test('isNumericType (Char Type)', () => {
expect(isNumericType('Char')).toEqual(false)
})
+
+test('formatText (text with link, full formatting)', () => {
+ expect(formatText('https://www.google.com/search?q=rock&roll', 'full')).toEqual(
+ ' https://www.google.com/search?q=rock&roll ',
+ )
+})
+
+test('formatText (text, full formatting)', () => {
+ expect(formatText('rock & roll', 'full')).toEqual(
+ ' rock·&·roll ',
+ )
+})