123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- /**
- * Copyright (c) Facebook, Inc. and its affiliates.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @flow
- * @format
- */
- import {ansiToJson} from 'anser';
- import Text from '../../Text/Text';
- import View from '../../Components/View/View';
- import * as React from 'react';
- import type {TextStyleProp} from 'react-native/Libraries/StyleSheet/StyleSheet';
- // Afterglow theme from https://iterm2colorschemes.com/
- const COLORS = {
- 'ansi-black': 'rgb(27, 27, 27)',
- 'ansi-red': 'rgb(187, 86, 83)',
- 'ansi-green': 'rgb(144, 157, 98)',
- 'ansi-yellow': 'rgb(234, 193, 121)',
- 'ansi-blue': 'rgb(125, 169, 199)',
- 'ansi-magenta': 'rgb(176, 101, 151)',
- 'ansi-cyan': 'rgb(140, 220, 216)',
- // Instead of white, use the default color provided to the component
- // 'ansi-white': 'rgb(216, 216, 216)',
- 'ansi-bright-black': 'rgb(98, 98, 98)',
- 'ansi-bright-red': 'rgb(187, 86, 83)',
- 'ansi-bright-green': 'rgb(144, 157, 98)',
- 'ansi-bright-yellow': 'rgb(234, 193, 121)',
- 'ansi-bright-blue': 'rgb(125, 169, 199)',
- 'ansi-bright-magenta': 'rgb(176, 101, 151)',
- 'ansi-bright-cyan': 'rgb(140, 220, 216)',
- 'ansi-bright-white': 'rgb(247, 247, 247)',
- };
- export default function Ansi({
- text,
- style,
- }: {
- text: string,
- style: TextStyleProp,
- ...
- }): React.Node {
- let commonWhitespaceLength = Infinity;
- const parsedLines = text.split(/\n/).map(line =>
- ansiToJson(line, {
- json: true,
- remove_empty: true,
- use_classes: true,
- }),
- );
- parsedLines.map(lines => {
- // The third item on each line includes the whitespace of the source code.
- // We are looking for the least amount of common whitespace to trim all lines.
- // Example: Array [" ", " 96 |", " text", ...]
- const match = lines[2] && lines[2]?.content?.match(/^ +/);
- const whitespaceLength = (match && match[0]?.length) || 0;
- if (whitespaceLength < commonWhitespaceLength) {
- commonWhitespaceLength = whitespaceLength;
- }
- });
- const getText = (content, key) => {
- if (key === 1) {
- // Remove the vertical bar after line numbers
- return content.replace(/\| $/, ' ');
- } else if (key === 2 && commonWhitespaceLength < Infinity) {
- // Remove common whitespace at the beginning of the line
- return content.substr(commonWhitespaceLength);
- } else {
- return content;
- }
- };
- return (
- <View style={{flexDirection: 'column'}}>
- {parsedLines.map((items, i) => (
- <View style={{flexDirection: 'row'}} key={i}>
- {items.map((bundle, key) => {
- const textStyle =
- bundle.fg && COLORS[bundle.fg]
- ? {
- backgroundColor: bundle.bg && COLORS[bundle.bg],
- color: bundle.fg && COLORS[bundle.fg],
- }
- : {
- backgroundColor: bundle.bg && COLORS[bundle.bg],
- };
- return (
- <Text style={[style, textStyle]} key={key}>
- {getText(bundle.content, key)}
- </Text>
- );
- })}
- </View>
- ))}
- </View>
- );
- }
|