beam-cli
Version:
A beautifully simple CLI for running Lighthouse audits on a statically generated (SSG) website
80 lines (79 loc) • 4.17 kB
JavaScript
import React, { useEffect, useState } from 'react';
import { Box, Spacer, Text } from 'ink';
import figures from 'figures';
import useDimensions from 'ink-use-stdout-dimensions';
import { categoryTitles, lighthouseCategoriesArray, } from '../../lighthouse/categories.js';
const determineColour = (score) => {
if (score < 0.5)
return 'red';
if (score < 0.9)
return 'yellow';
return 'green';
};
const scoreColumnWidth = 6;
const presetColumnWidth = 9;
const LighthouseScore = ({ score }) => {
if (score < 0)
return React.createElement(Text, null, ''.padEnd(scoreColumnWidth, ' '));
const colour = determineColour(score);
const scoreText = Math.round(score * 100).toString();
return (React.createElement(Text, { color: colour }, scoreText
.padStart(scoreColumnWidth - 1, ' ')
.padEnd(scoreColumnWidth, ' ')));
};
const LighthouseScores = ({ scores, }) => {
const scoreValues = lighthouseCategoriesArray.map(cat => scores[cat] ?? -1);
return (React.createElement(React.Fragment, null, scoreValues.map((score, index) => (
/* eslint-disable react/no-array-index-key */
// ! Disabled rule there is nothing unique about each item.
React.createElement(LighthouseScore, { key: index, score: score })
/* eslint-enable react/no-array-index-key */
))));
};
const MetricTitles = ({ selectedCategory, selectedTab, }) => {
if (selectedTab === 'Page Sizes')
return (React.createElement(Text, { underline: selectedCategory !== 'path' }, "Transfer Size (KiB)"));
return (React.createElement(React.Fragment, null, lighthouseCategoriesArray.map(cat => {
const selected = cat === selectedCategory;
return (React.createElement(Text, { key: cat, underline: selected }, categoryTitles[cat]
.slice(0, scoreColumnWidth - 2)
.toUpperCase()
.padStart(scoreColumnWidth - 1, ' ')
.padEnd(scoreColumnWidth, ' ')));
})));
};
/* eslint-disable no-mixed-operators */
const calculateMaxUrlLength = (columns) => columns - 12 - 5 * scoreColumnWidth - presetColumnWidth;
/* eslint-enable no-mixed-operators */
const truncateUrl = (url, maxLength) => {
if (url.length <= maxLength)
return url;
return `${url.slice(0, maxLength - 3)}...`;
};
export const ExplorerTable = ({ results, selectedIndex, selectedCategory, selectedTab }) => {
const [columns] = useDimensions();
const [maxUrlLength, setMaxUrlLength] = useState(calculateMaxUrlLength(columns));
useEffect(() => {
setMaxUrlLength(calculateMaxUrlLength(columns));
}, [columns]);
return (React.createElement(Box, { borderStyle: 'round', borderColor: 'cyan', padding: 1, flexDirection: 'column' },
React.createElement(Box, { flexDirection: 'row' },
React.createElement(Text, null,
''.padStart(2, ' '),
React.createElement(Text, { underline: selectedCategory === 'path' }, "URL")),
React.createElement(Spacer, null),
React.createElement(MetricTitles, { selectedCategory: selectedCategory, selectedTab: selectedTab }),
selectedTab === 'Page Sizes' ? null : (React.createElement(Text, { dimColor: true }, 'PRESET'.padStart(presetColumnWidth, ' ')))),
React.createElement(Text, null, " "),
results.map((result, index) => {
const selected = index === selectedIndex;
return (React.createElement(Box, { key: result.name, flexDirection: 'row' },
React.createElement(Text, null,
selected ? `${figures.arrowRight} ` : ' ',
React.createElement(Text, { underline: selected }, truncateUrl(result.url, maxUrlLength))),
React.createElement(Spacer, null),
selectedTab === 'Page Sizes' ? (React.createElement(Text, null, result.sizeDisplay)) : (React.createElement(React.Fragment, null,
React.createElement(LighthouseScores, { scores: result.scores }),
React.createElement(Text, { dimColor: true }, (result.mobile ? 'mobile' : 'desktop').padStart(presetColumnWidth, ' '))))));
})));
};