Pasting table from Kibana into GitLab doesn't format as a table

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

We have this neat copy from spreadsheet and paste in Markdown feature: https://docs.gitlab.com/ee/user/markdown.html#copy-from-spreadsheet-and-paste-in-markdown

This works great from spreadsheets (as documented) but not so well from Kibana. For instance, this table: https://log.gprd.gitlab.net/goto/91e630283d5b4b7da3e1bdfd67967b88

image

In Firefox, pastes like:

	Time
json.tag
Jun 15, 2020 @ 08:42:13.210rails.application
Jun 15, 2020 @ 08:42:12.931rails.application
Jun 15, 2020 @ 08:42:12.681rails.production
Jun 15, 2020 @ 08:42:12.498rails.graphql

And in Chrome, pastes like:

	Time	json.tag
	Jun 15, 2020 @ 08:53:44.994	rails.application
	Jun 15, 2020 @ 08:53:44.686	rails.production
	Jun 15, 2020 @ 08:53:44.667	rails.api
	Jun 15, 2020 @ 08:53:44.638	rails.production
	Jun 15, 2020 @ 08:53:44.630	rails.api

Using https://evercoder.github.io/clipboard-inspector/, it looks like the HTML data looks like:

<table ng-if="infiniteScroll" class="kbn-table table" data-test-subj="docTable"><thead kbn-table-header="" columns="columns" index-pattern="indexPattern" sort-order="sorting" on-change-sort-order="onChangeSortOrder" on-move-column="onMoveColumn" on-remove-column="onRemoveColumn"><tr data-test-subj="docTableHeader" class="kbnDocTableHeader"><th style="width: 24px;"></th><th data-test-subj="docTableHeaderField"><span data-test-subj="docTableHeader-json.time">Time<span class="euiToolTipAnchor"></span></span></th></tr></thead></table><span data-test-subj="docTableHeader-json.tag">json.tag<span class="euiToolTipAnchor"></span></span><table ng-if="infiniteScroll" class="kbn-table table" data-test-subj="docTable"><tbody>
      <tr ng-repeat="row in hits|limitTo:limit track by row._index+row._type+row._id+row._score+row._version+row._routing" kbn-table-row="row" columns="columns" sorting="sorting" index-pattern="indexPattern" filter="filter" filters="filters" class="kbnDocTable__row" ng-class="{'kbnDocTable__row--highlight': row['$$_isAnchor']}" data-test-subj="docTableRow" on-add-column="onAddColumn" on-remove-column="onRemoveColumn"><td ng-click="toggleRow()" data-test-subj="docTableExpandToggleColumn" class="kbnDocTableCell__toggleDetails">
  </td></tr></tbody></table><table ng-if="infiniteScroll" class="kbn-table table" data-test-subj="docTable"><tbody><tr ng-repeat="row in hits|limitTo:limit track by row._index+row._type+row._id+row._score+row._version+row._routing" kbn-table-row="row" columns="columns" sorting="sorting" index-pattern="indexPattern" filter="filter" filters="filters" class="kbnDocTable__row" ng-class="{'kbnDocTable__row--highlight': row['$$_isAnchor']}" data-test-subj="docTableRow" on-add-column="onAddColumn" on-remove-column="onRemoveColumn"><td ng-click="toggleRow()" data-test-subj="docTableExpandToggleColumn" class="kbnDocTableCell__toggleDetails">
</td><td class="eui-textNoWrap" data-test-subj="docTableField" width="1%"><span ng-non-bindable="">Jun 15, 2020 @ 08:42:13.210</span><span class="kbnDocTableCell__filter"></span></td></tr></tbody></table><div class="truncate-by-height"><span ng-non-bindable="">rails.application</span></div><span class="kbnDocTableCell__filter"></span><table ng-if="infiniteScroll" class="kbn-table table" data-test-subj="docTable"><tbody><tr ng-repeat="row in hits|limitTo:limit track by row._index+row._type+row._id+row._score+row._version+row._routing" kbn-table-row="row" columns="columns" sorting="sorting" index-pattern="indexPattern" filter="filter" filters="filters" class="kbnDocTable__row" ng-class="{'kbnDocTable__row--highlight': row['$$_isAnchor']}" data-test-subj="docTableRow" on-add-column="onAddColumn" on-remove-column="onRemoveColumn"><td ng-click="toggleRow()" data-test-subj="docTableExpandToggleColumn" class="kbnDocTableCell__toggleDetails">
  </td></tr></tbody></table><span ng-non-bindable="">Jun 15, 2020 @ 08:42:12.931</span><span class="kbnDocTableCell__filter"></span><div class="truncate-by-height"><span ng-non-bindable="">rails.application</span></div><span class="kbnDocTableCell__filter"></span><table ng-if="infiniteScroll" class="kbn-table table" data-test-subj="docTable"><tbody><tr data-test-subj="docTableDetailsRow" class="kbnDocTableDetails__row"></tr><tr ng-repeat="row in hits|limitTo:limit track by row._index+row._type+row._id+row._score+row._version+row._routing" kbn-table-row="row" columns="columns" sorting="sorting" index-pattern="indexPattern" filter="filter" filters="filters" class="kbnDocTable__row" ng-class="{'kbnDocTable__row--highlight': row['$$_isAnchor']}" data-test-subj="docTableRow" on-add-column="onAddColumn" on-remove-column="onRemoveColumn"><td ng-click="toggleRow()" data-test-subj="docTableExpandToggleColumn" class="kbnDocTableCell__toggleDetails">
  </td></tr></tbody></table><span ng-non-bindable="">Jun 15, 2020 @ 08:42:12.681</span><span class="kbnDocTableCell__filter"></span><div class="truncate-by-height"><span ng-non-bindable="">rails.production</span></div><span class="kbnDocTableCell__filter"></span><table ng-if="infiniteScroll" class="kbn-table table" data-test-subj="docTable"><tbody><tr data-test-subj="docTableDetailsRow" class="kbnDocTableDetails__row"></tr><tr ng-repeat="row in hits|limitTo:limit track by row._index+row._type+row._id+row._score+row._version+row._routing" kbn-table-row="row" columns="columns" sorting="sorting" index-pattern="indexPattern" filter="filter" filters="filters" class="kbnDocTable__row" ng-class="{'kbnDocTable__row--highlight': row['$$_isAnchor']}" data-test-subj="docTableRow" on-add-column="onAddColumn" on-remove-column="onRemoveColumn"><td ng-click="toggleRow()" data-test-subj="docTableExpandToggleColumn" class="kbnDocTableCell__toggleDetails">
  </td></tr></tbody></table><span ng-non-bindable="">Jun 15, 2020 @ 08:42:12.498</span><span class="kbnDocTableCell__filter"></span><div class="truncate-by-height"><span ng-non-bindable="">rails.graphql</span></div>

Which has more than one table. https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/behaviors/markdown/paste_markdown_table.js specifically says:

    // We're only looking for exactly one table. If there happens to be
    // multiple tables, it's possible an application copied data into
    // the clipboard that is not related to a simple table. It may also be
    // complicated converting multiple tables into Markdown.

Which is fair enough.

Edited by 🤖 GitLab Bot 🤖