Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Link as hyperlink in terminal doesn't render correctly #73

Closed
hamxabaig opened this issue Dec 29, 2018 · 8 comments · Fixed by #292
Closed

Link as hyperlink in terminal doesn't render correctly #73

hamxabaig opened this issue Dec 29, 2018 · 8 comments · Fixed by #292
Labels
enhancement New feature or request

Comments

@hamxabaig
Copy link

hamxabaig commented Dec 29, 2018

Hey there, I tried all versions of cli-table i-e cli-table1, cli-table2 & cli-table3. All of them doesn't render the link properly.

This is the library i'm using terminal-link: Create clickable links in the terminal When i log it without cli-table3 it renders the link correctly. But when used inside the columns of cli-table it doesn't render it and mess up the table borders. (Check the pic)

What do you think can be an issue? I think cli-table is encoding the column's content which mess up the encoding provided by terminal-link?

(90m should suppose to be the link) I'm using iterm2

image

@DanielRuf
Copy link
Contributor

Hi, can you provide a small reproducible test case?

@DanielRuf DanielRuf added the enhancement New feature or request label Jan 28, 2019
@matheussampaio
Copy link

matheussampaio commented Mar 18, 2020

The problem above is caused when cli-table3 truncates the content.

Here is a small code to reproduce the problem (tested in iTerm2).

const Table = require('cli-table3')

function hyperlink(url = '', text = 'link') {
  const OSC = '\u001B]'
  const BEL = '\u0007'
  const SEP = ';'

  return [
    OSC,
    '8',
    SEP,
    SEP,
    url,
    BEL,
    text,
    OSC,
    '8',
    SEP,
    SEP,
    BEL
  ].join('')
}

const link = hyperlink('https://www.example.com', 'example')

const table1 = new Table({
  head: ['Wide Column'],
  colWidths: [100]
})

table1.push([link])

console.log(table1.toString())

const table2 = new Table({
  head: ['Narrow Column'],
  colWidths: [25]
})

table2.push([link])

console.log(table2.toString())

Output:
Screen Shot 2020-03-18 at 13 57 03


If I comment truncate, the output looks a lot closer to what I would expect:

Screen Shot 2020-03-18 at 14 00 55

I'm trying to figure out how I can fix the spacing... any tips?

@matheussampaio
Copy link

matheussampaio commented Mar 18, 2020

Here is a PoC that solves the hyperlink problem.

const Table = require('cli-table3')

const link = 'https://www.example.com'

const table1 = new Table({
  head: ['Wide Column'],
  colWidths: [100]
})

table1.push([{ hyperlink: true, content: link }])

console.log(table1.toString())

const table2 = new Table({
  head: ['Narrow Column'],
  colWidths: [15]
})

table2.push([{ hyperlink: true, content: link }])

console.log(table2.toString())

Screenshot with hyperlink feature:
image

Commit Patch:

From e4480362258452c29b589d51d31c39b40175dcec Mon Sep 17 00:00:00 2001
From: Matheus Sampaio <matheus@sampaio.us>
Date: Wed, 18 Mar 2020 16:02:18 -0600
Subject: [PATCH] feat: add hyperlink support

---
 src/cell.js  | 12 ++++++++++++
 src/utils.js |  9 +++++++++
 2 files changed, 21 insertions(+)

diff --git a/src/cell.js b/src/cell.js
index 2db7f74..a1271f8 100644
--- a/src/cell.js
+++ b/src/cell.js
@@ -36,6 +36,8 @@ class Cell {
     }
     this.colSpan = options.colSpan || 1;
     this.rowSpan = options.rowSpan || 1;
+    this.hyperlink = options.hyperlink;
+    this.hyperlinkLabel = options.hyperlinkLabel;
   }
 
   mergeTableOptions(tableOptions, cells) {
@@ -228,6 +230,16 @@ class Cell {
     let len = this.width - (this.paddingLeft + this.paddingRight);
     if (forceTruncationSymbol) line += this.truncate || '…';
     let content = utils.truncate(line, len, this.truncate);
+    if (this.hyperlink) {
+      const hyperlinkLabel = this.hyperlinkLabel || line;
+      if (utils.strlen(line) > len) {
+        content = utils.hyperlink(line, utils.truncate(hyperlinkLabel, len, this.truncate));
+      } else {
+        content = utils.hyperlink(line, hyperlinkLabel);
+      }
+
+      content += ''.padEnd(len - hyperlinkLabel.length);
+    }
     content = utils.pad(content, len, ' ', this.hAlign);
     content = leftPadding + content + rightPadding;
     return this.stylizeLine(left, content, right);
diff --git a/src/utils.js b/src/utils.js
index e6f82b2..b734d7c 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -292,11 +292,20 @@ function colorizeLines(input) {
   return output;
 }
 
+function hyperlink(url, text) {
+  const OSC = '\u001B]';
+  const BEL = '\u0007';
+  const SEP = ';';
+
+  return [OSC, '8', SEP, SEP, url, BEL, text, OSC, '8', SEP, SEP, BEL].join('');
+}
+
 module.exports = {
   strlen: strlen,
   repeat: repeat,
   pad: pad,
   truncate: truncate,
+  hyperlink: hyperlink,
   mergeOptions: mergeOptions,
   wordWrap: multiLineWordWrap,
   colorizeLines: colorizeLines,
-- 
2.24.1

@ElsaOOo
Copy link

ElsaOOo commented Sep 21, 2020

@matheussampaio the Poc has released yet? or whren?

@DanielRuf
Copy link
Contributor

@ElsaOOo PRs are very welcome.

@artjomkruglenkov
Copy link

artjomkruglenkov commented Apr 30, 2021

Any plans to support hyperlinks inside the table? Currently, I use a workaround where a hyperlink is placed in the last table column and the table itself is rendered without borders. This is the only way to hide incorrectly drawn borders.

@speedytwenty
Copy link
Collaborator

speedytwenty commented Apr 1, 2022

Just reviewing this.

There is not enough info to attempt to reproduce @hamxabaig's reported issue. (Thanks for the lead to terminal-link!)

I cannot reproduce @matheussampaio's spacing issue. When I run the code I get:
image

@matheussampaio's POC is confusing in that it uses the text as display text. But it highlights the dichotomy between display text and displaying the url.

For cli-table3 to [conveniently] support hyperlinks I do believe it needs to be embedded so that cli-table3 can control the output of the display text (whether it be the URL or otherwise). In the event hyperlinks are not supported by the output target (Eg. stdout), it should probably fallback to the link (and potentially avoid truncation with the new wrapOnWordBoundary option (which would fall on the implementors end).

Something like this is what I'd have in mind prima facie:

table.push([{ content: 'My Link Text', href: 'http://example.com' }]);
// use the link as content (no display text)
table.push([{ href: 'http://example.com' }]);

If/when I dive into this, I'll likely open a new issue as a feature request.

speedytwenty added a commit to speedytwenty/cli-table3 that referenced this issue Apr 5, 2022
speedytwenty added a commit to speedytwenty/cli-table3 that referenced this issue Apr 5, 2022
@speedytwenty speedytwenty linked a pull request Apr 5, 2022 that will close this issue
@speedytwenty
Copy link
Collaborator

Hyperlinks will be supported in the next release (v0.6.2)! The interface is simple:

table.push([
  // Specify the URL as the display text
  { href: 'http://example.com' }, 
  // Specify display text
  { href: 'http://example.com', content: 'Example text' },
]);

Link text is wrapped, truncated, etc. as usual but when the text of a cell spans multiple lines, each link is wrapped with the link.

The solution basically mimics matheussampaio's POC but cleans up the Cell API slightly as a small step toward refactoring cells for better performance.

speedytwenty added a commit that referenced this issue Apr 5, 2022
* Failing tests for hyperlink support
* Add hyperlink support for cells (#73)
* Add hyperlink example to basic usage docs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants