conorhastings / react-native-syntax-highlighter

a syntax highlighter for react native using https://github.com/conorhastings/react-syntax-highlighter under the hood
MIT License
167 stars 25 forks source link

Add support for TypeScript types #26

Open ShivamJoker opened 3 years ago

ShivamJoker commented 3 years ago

Hey thanks for the library can you please implement types from the original library

Almaju commented 3 years ago

I found the code really hard to read and debug so I made myself a (simpler) version which is Typescript ready. Feel free to use it.

import { useTheme } from "@minimalui/core";
import * as React from "react";
import { Text, TextStyle, View } from "react-native";
import Highlighter, { SyntaxHighlighterProps } from "react-syntax-highlighter";
import {
  tomorrow as lightStyle,
  tomorrowNight as darkStyle,
} from "react-syntax-highlighter/dist/esm/styles/hljs";

type Node = {
  children?: Node[];
  properties?: {
    className: string[];
  };
  tagName?: string;
  type: string;
  value?: string;
};

type StyleSheet = { [key: string]: TextStyle };

type RendererParams = {
  rows: Node[];
  stylesheet: StyleSheet;
};

export const SyntaxHighlighter: React.FunctionComponent<SyntaxHighlighterProps> = (
  props
) => {
  const theme = useTheme();

  const cleanStyle = (style: TextStyle) => {
    const clean: TextStyle = {
      ...style,
      display: undefined,
    };
    return clean;
  };

  const stylesheet: StyleSheet = Object.fromEntries(
    Object.entries(
      (theme.palette.type === "light" ? lightStyle : darkStyle) as StyleSheet
    ).map(([className, style]) => [className, cleanStyle(style)])
  );

  const renderNode = (nodes: Node[], key = "0") =>
    nodes.reduce<React.ReactNode[]>((acc, node, index) => {
      if (node.children) {
        acc.push(
          <Text
            // eslint-disable-next-line react/no-array-index-key
            key={`${key}.${index}`}
            style={[
              {
                color: stylesheet.hljs.color,
              },
              ...(node.properties?.className || []).map((c) => stylesheet[c]),
              {
                fontSize: 14,
                fontFamily: "monospace",
              },
            ]}
          >
            {renderNode(node.children, `${key}.${index}`)}
          </Text>
        );
      }

      if (node.value) {
        acc.push(node.value);
      }

      return acc;
    }, []);

  const nativeRenderer = ({ rows }: RendererParams) => {
    return (
      <View
        style={[
          stylesheet.hljs,
          { backgroundColor: theme.palette.background.paper, padding: 16 },
        ]}
      >
        {renderNode(rows)}
      </View>
    );
  };

  return (
    <Highlighter
      {...props}
      CodeTag={View}
      customStyle={{
        padding: 0,
      }}
      PreTag={View}
      renderer={nativeRenderer}
      style={stylesheet}
    />
  );
};

export default SyntaxHighlighter;
ShivamJoker commented 2 years ago

@Almaju how do we get the bg color ? without the ui lib

Almaju commented 2 years ago

@ShivamJoker I only use two variables from my UI lib, the palette type and the background color for cards.

type Theme = {
  palette: {
    type: "light" | "dark",
    background: {
      paper: string,
    }
  }
}

You can remove const theme = useTheme(); then replace theme.palette.type === "light" and theme.palette.background.paper by your values (hardcoded or variables).

alex14vdk commented 8 months ago

@Almaju it seems your version is pretty good, thx, but i've found one problem:

if i run my app with your component on android, between every line i have very high distanсe, like line has bottom and top padding
for example, if i write this code:

import { EPageName } from 'shared/config/enums';
import { TMoveToPage } from './types';
import { TMove } from './types';

export const moveToPage: TMoveToPage = navigation => page => () => navigation.navigate(EPageName[page as keyof EPageName]);

and when i run app on web, it's ok

but on android it looks like:


import { EPageName } from 'shared/config/enums';

import { TMoveToPage } from './types';

import { TMove } from './types';

export const moveToPage: TMoveToPage = navigation => page => () => navigation.navigate(EPageName[page as keyof EPageName]);

mb do you know how to fix it?