CLI for Oblique Strategies.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.5 KiB

  1. const DEFAULT_CARD_WIDTH = 32;
  2. const DEFAULT_CARD_HEIGHT = 8;
  3. type CardPresenterOptions = {
  4. width: number,
  5. height: number
  6. }
  7. const makeCardEdge = (width: number, symbols: string) => {
  8. const middlePart = Math.floor(symbols.length / 2);
  9. return (
  10. new Array<string>(width)
  11. .fill(symbols.at(middlePart) as string)
  12. .map((s, i, ss) => {
  13. if (i < middlePart) {
  14. return symbols.at(i);
  15. }
  16. if (i >= (ss.length - 1) - middlePart) {
  17. return symbols.at(ss.length - i - 1);
  18. }
  19. return s;
  20. })
  21. .join('')
  22. );
  23. };
  24. const encloseInCard = async (
  25. cardText: string,
  26. cardWidth: number,
  27. cardHeight: number,
  28. symbols: [string, string, string],
  29. ) => {
  30. // can't import es modules naturally, we use dynamic imports here
  31. const { default: wrapAnsi } = await import('wrap-ansi');
  32. const lineWidth = cardWidth - (symbols[1].length - 1);
  33. const text = wrapAnsi(cardText, lineWidth, { hard: true, trim: true });
  34. const lines = text.split('\n').map((line) => {
  35. let centeredLine = line;
  36. while (centeredLine.length < lineWidth) {
  37. // add space after
  38. centeredLine = `${centeredLine}${symbols[1].at(3) as string}`;
  39. if (centeredLine.length < lineWidth) {
  40. // add space before
  41. centeredLine = `${symbols[1].at(1) as string}${centeredLine}`;
  42. }
  43. }
  44. return centeredLine.slice(0, lineWidth);
  45. });
  46. const displayLines = [...lines];
  47. while (displayLines.length < cardHeight - 2) {
  48. const blank = new Array(lineWidth).fill(symbols[1].at(1) as string).join('');
  49. displayLines.push(blank);
  50. if (displayLines.length < cardHeight - 2) {
  51. displayLines.unshift(blank);
  52. }
  53. }
  54. const cardCenter = displayLines
  55. .map((line) => (
  56. `${symbols[1].at(0) as string}${symbols[1].at(1) as string}${line}${symbols[1].at(3) as string}${symbols[1].at(4) as string}`
  57. ))
  58. .join('\n');
  59. return [
  60. makeCardEdge(cardWidth, symbols[0]),
  61. cardCenter,
  62. makeCardEdge(cardWidth, symbols[2]),
  63. ].join('\n');
  64. };
  65. export default (options = {} as CardPresenterOptions) => async (card: string) => {
  66. const {
  67. width: cardWidthRaw = DEFAULT_CARD_WIDTH,
  68. height: cardHeightRaw = DEFAULT_CARD_HEIGHT,
  69. } = options;
  70. const cardWidth = Math.max(cardWidthRaw, DEFAULT_CARD_WIDTH);
  71. const cardHeight = Math.max(cardHeightRaw, DEFAULT_CARD_HEIGHT);
  72. const cardContents = await encloseInCard(
  73. card,
  74. cardWidth,
  75. cardHeight,
  76. [
  77. ' ,-. ',
  78. '| A |',
  79. " `-' ",
  80. ],
  81. );
  82. const Console = console;
  83. Console.log(cardContents);
  84. };