UNPKG

kui-shell

Version:

This is the monorepo for Kui, the hybrid command-line/GUI electron-based Kubernetes tool

292 lines 11.5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const strip_ansi_1 = require("strip-ansi"); const table_1 = require("../models/table"); const pretty_print_1 = require("./pretty-print"); const i18n_1 = require("../../util/i18n"); const strings = i18n_1.default('core'); const isAnsi = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><]/; function indexOf(haystack, needle, startIdx) { const idx = haystack.indexOf(needle, startIdx); if (idx !== -1) { return { startIdx, endIdx: idx + needle.length }; } let hidx = startIdx; let nidx = 0; while (hidx < haystack.length && nidx < needle.length) { const h = haystack.charAt(hidx); const n = needle.charAt(nidx); if (h === '\x1b') { do { hidx++; } while (hidx < haystack.length && !(haystack.charAt(hidx) === 'm')); hidx++; } else if (nidx > 0 && isAnsi.test(h)) { hidx++; } else if (h !== n) { hidx++; nidx = 0; } else { hidx++; nidx++; } } if (nidx === needle.length) { return { startIdx, endIdx: hidx }; } else { return { startIdx, endIdx: startIdx + needle.length }; } } function maybeURL(str) { try { const url = new URL(str); if (url.host) { const link = document.createElement('a'); link.target = '_blank'; link.innerText = strings('link'); link.title = str; link.href = str; return link; } } catch (err) { } } const split = (str, splits, headerCells) => __awaiter(void 0, void 0, void 0, function* () { const stripped = strip_ansi_1.default(str); let lastEnd = 0; return Promise.all(splits.map((splitIndex, idx) => __awaiter(void 0, void 0, void 0, function* () { const plain = stripped.substring(splitIndex, splits[idx + 1] || stripped.length).trim(); const { startIdx, endIdx } = indexOf(str, plain, lastEnd); const value = str.slice(startIdx, endIdx).trim(); const valueDom = maybeURL(plain) || (yield pretty_print_1.default([value], false)); lastEnd = endIdx; return { key: headerCells && headerCells[idx], value: plain, valueDom, css: '' }; }))); }); exports.preprocessTable = (raw) => __awaiter(void 0, void 0, void 0, function* () { return Promise.all(raw.map((table) => __awaiter(void 0, void 0, void 0, function* () { const firstNewlineIdx = table.indexOf('\n'); let header = strip_ansi_1.default(table.substring(0, firstNewlineIdx).replace(/\t/g, ' ')); if (header.trim().length === 0) { table = table.slice(firstNewlineIdx + 1); const secondNewlineIdx = table.indexOf('\n'); header = strip_ansi_1.default(table.substring(0, secondNewlineIdx).replace(/\t/g, ' ')); } const headerCells = yield header .split(/(\t|\s\s)+\s?/) .filter(x => x && !x.match(/(\t|\s\s)/)) .map(_ => _.trim()); const columnStarts = []; for (let idx = 0, jdx = 0; idx < headerCells.length; idx++) { const { offset, prefix } = idx === 0 ? { offset: 0, prefix: '' } : { offset: 1, prefix: ' ' }; const newJdx = header.indexOf(prefix + headerCells[idx] + ' ', jdx); if (newJdx < 0) { jdx = header.indexOf(' ' + headerCells[idx], jdx); } else { jdx = newJdx; } columnStarts.push(jdx + offset); jdx = newJdx + headerCells[idx].length; } const tinyColumns = columnStarts.reduce((yup, start, idx) => { return yup && (idx > 0 && start - columnStarts[idx - 1] <= 2); }, true); if (columnStarts.length <= 1 || tinyColumns) { return { trailingString: table }; } else { const possibleRows = table.split(/\n/); const endOfTable = possibleRows.map(strip_ansi_1.default).findIndex(row => { const nope = columnStarts.findIndex(idx => { return idx > 0 && !/\s/.test(row[idx - 1]); }); return nope !== -1; }); const rows = endOfTable === -1 ? possibleRows : possibleRows.slice(0, endOfTable); const preprocessed = (yield Promise.all(rows.map(line => { return split(line, columnStarts, headerCells); }))).filter(x => x); const trailingString = endOfTable !== -1 && possibleRows.slice(endOfTable).join('\n'); return { trailingString, rows: preprocessed }; } }))); }); const capitalize = (str) => { return str.length === 0 ? str : str[0].toUpperCase() + str.slice(1).toLowerCase(); }; exports.outerCSSForKey = { NAME: 'entity-name-group', READY: 'a-few-numbers-wide', KIND: 'max-width-id-like entity-kind', NAMESPACE: 'entity-name-group entity-name-group-narrow', DISPLAY: 'hide-with-sidecar', TYPE: 'hide-with-sidecar', ENDPOINT: 'hide-with-sidecar', CLUSTER: 'entity-name-group entity-name-group-narrow hide-with-sidecar', AUTHINFO: 'entity-name-group entity-name-group-narrow hide-with-sidecar', REFERENCE: 'entity-name-group entity-name-group-narrow hide-with-sidecar', CREATED: 'hide-with-sidecar', 'CREATED AT': 'hide-with-sidecar', ID: 'max-width-id-like', CURRENT: 'entity-name-group entity-name-group-extra-narrow text-center', DESIRED: 'entity-name-group entity-name-group-extra-narrow text-center', RESTARTS: 'very-narrow', 'LAST SEEN': 'hide-with-sidecar entity-name-group-extra-narrow', 'FIRST SEEN': 'hide-with-sidecar entity-name-group-extra-narrow', UPDATED: 'min-width-date-like', REVISION: 'hide-with-sidecar', AGE: 'hide-with-sidecar very-narrow', 'PORT(S)': 'entity-name-group entity-name-group-narrow hide-with-sidecar', SUBOBJECT: 'entity-name-group entity-name-group-extra-narrow' }; const fillTo = (length, maxColumns) => { if (length >= maxColumns) { return []; } else { return new Array(maxColumns - length).fill(''); } }; exports.cssForKey = { NAME: 'entity-name', SOURCE: 'lighter-text smaller-text', SUBOBJECT: 'lighter-text smaller-text', 'CREATED AT': 'lighter-text smaller-text', AGE: 'slightly-deemphasize', 'APP VERSION': 'pre-wrap slightly-deemphasize', UPDATED: 'slightly-deemphasize somewhat-smaller-text' }; const tagForKey = { PHASE: 'badge', STATE: 'badge', STATUS: 'badge' }; exports.cssForValue = { NORMAL: 'green-background', Normal: 'green-background', normal: 'green-background', UNKNOWN: '', DEPLOYED: 'green-background', DELETED: '', SUPERSEDED: 'yellow-background', FAILED: 'red-background', DELETING: 'yellow-background', 'Init:0/1': 'yellow-background', PodScheduled: 'yellow-background', PodInitializing: 'yellow-background', Initialized: 'yellow-background', Terminating: 'yellow-background', CrashLoopBackOff: 'red-background', Error: 'red-background', Failed: 'red-background', Running: 'green-background', Pending: 'yellow-background', Completed: 'gray-background', Unknown: '', Ready: 'green-background', ProvisionedSuccessfully: 'green-background', Active: 'green-background', Online: 'green-background', NodeReady: 'green-background', Pulled: 'green-background', Rebooted: 'green-background', Started: 'green-background', Created: 'green-background', Succeeded: 'green-background', SuccessfulCreate: 'green-background', SuccessfulMountVol: 'green-background', ContainerCreating: 'yellow-background', Starting: 'yellow-background', NodeNotReady: 'yellow-background', Killing: 'yellow-background', Deleting: 'yellow-background', Pulling: 'yellow-background', BackOff: 'yellow-background', FailedScheduling: 'red-background', FailedKillPod: 'red-background' }; exports.formatTable = (entityType, lines) => { const nameColumnIdx = Math.max(0, lines[0].findIndex(({ key }) => key === 'NAME')); const maxColumns = lines.reduce((max, columns) => Math.max(max, columns.length), 0); const keyForFirstColumn = lines[0][nameColumnIdx].key.replace(/:/g, '').toUpperCase(); const allRows = lines.map((columns, idx) => { const nameForDisplay = columns[0].value; const firstColumnCSS = idx === 0 || columns[0].key !== 'CURRENT' ? '' : 'selected-entity'; const rowIsSelected = columns[0].key === 'CURRENT' && nameForDisplay === '*'; const rowCSS = [rowIsSelected ? 'selected-row' : '']; const attributes = columns .slice(1) .map(({ key, value: column, valueDom, css }) => ({ key, value: idx > 0 && /STATUS|STATE/i.test(key) ? capitalize(column) : column, valueDom, css })) .map(({ key, value: column, valueDom, css }, colIdx) => ({ key, tag: (idx > 0 && tagForKey[key]) || undefined, onclick: false, outerCSS: (exports.outerCSSForKey[key] || '') + (colIdx <= 1 || colIdx === nameColumnIdx - 1 || /STATUS/i.test(key) ? '' : ' hide-with-sidecar'), css: css + (column.length > 20 ? ' pretty-wide' : '') + ' ' + ((idx > 0 && exports.cssForKey[key]) || '') + ' ' + (exports.cssForValue[column] || ''), valueDom, value: column })) .concat(fillTo(columns.length, maxColumns)); const row = { key: keyForFirstColumn, name: nameForDisplay, nameDom: columns[0].valueDom, fontawesome: idx !== 0 && columns[0].key === 'CURRENT' && 'fas fa-network-wired', onclick: false, css: firstColumnCSS, rowCSS, outerCSS: exports.outerCSSForKey[columns[0].key] || '', attributes }; return row; }); const hasHeader = !/[:/]/.test(allRows[0].name); const header = hasHeader ? allRows[0] : undefined; const body = hasHeader ? allRows.slice(1) : allRows; const style = !header ? table_1.TableStyle.Light : table_1.TableStyle.Medium; const model = { title: entityType, header, body, style, noSort: true }; return model; }; //# sourceMappingURL=ascii-to-table.js.map