rn-shiki 0.0.34 → 0.0.36

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "rn-shiki",
3
3
  "type": "module",
4
- "version": "0.0.34",
4
+ "version": "0.0.36",
5
5
  "description": "Shiki syntax highlighter for React Native.",
6
6
  "author": "Ryan Skinner <hello@ryanskinner.com>",
7
7
  "license": "MIT",
@@ -1,9 +1,38 @@
1
1
  import type { SyntaxHighlighterProps } from 'src/types/shiki'
2
2
  import React from 'react'
3
- import { Text, View } from 'react-native'
3
+ import { Platform, ScrollView, StyleSheet, Text, View } from 'react-native'
4
4
  import { useSyntaxHighlighter } from '../../hooks/useSyntaxHighlighter'
5
+ import SyntaxLine from './SyntaxLine'
5
6
 
6
- function SyntaxHighlighter({ text, language, languageId, theme }: SyntaxHighlighterProps) {
7
+ const monospaceFont = Platform.select({
8
+ ios: 'Menlo',
9
+ android: 'monospace',
10
+ default: 'monospace',
11
+ })
12
+
13
+ const styles = StyleSheet.create({
14
+ container: {
15
+ flex: 1,
16
+ minHeight: 20,
17
+ },
18
+ scrollContent: {
19
+ flexGrow: 1,
20
+ padding: 8,
21
+ },
22
+ contentContainer: {
23
+ minWidth: '100%',
24
+ },
25
+ errorText: {
26
+ padding: 8,
27
+ color: '#ff6b6b',
28
+ },
29
+ loadingText: {
30
+ padding: 8,
31
+ color: '#666666',
32
+ },
33
+ })
34
+
35
+ function SyntaxHighlighter({ text, language, languageId, theme, fontSize = 14 }: SyntaxHighlighterProps & { fontSize?: number }) {
7
36
  const { tokens, error, isLoading } = useSyntaxHighlighter({
8
37
  text,
9
38
  language,
@@ -13,43 +42,46 @@ function SyntaxHighlighter({ text, language, languageId, theme }: SyntaxHighligh
13
42
 
14
43
  if (error) {
15
44
  return (
16
- <Text style={{ color: '#ff6b6b', fontFamily: 'monospace' }}>
45
+ <Text
46
+ style={[
47
+ styles.errorText,
48
+ {
49
+ fontFamily: monospaceFont,
50
+ fontSize,
51
+ },
52
+ ]}
53
+ >
17
54
  Error:
55
+ {' '}
18
56
  {error}
19
57
  </Text>
20
58
  )
21
59
  }
22
60
 
23
61
  if (isLoading) {
24
- return <Text style={{ color: '#666666', fontFamily: 'monospace' }}>Loading...</Text>
62
+ return (
63
+ <Text
64
+ style={[
65
+ styles.loadingText,
66
+ {
67
+ fontFamily: monospaceFont,
68
+ fontSize,
69
+ },
70
+ ]}
71
+ >
72
+ Loading...
73
+ </Text>
74
+ )
25
75
  }
26
76
 
27
77
  return (
28
- <View>
29
- {tokens.map((line, lineIndex) => (
30
- <View key={`line-${lineIndex}`} style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
31
- {line.map((token, tokenIndex) => (
32
- <Text
33
- key={`${lineIndex}-${tokenIndex}`}
34
- style={{
35
- color: token.color || '#000000',
36
- fontFamily: 'monospace',
37
- fontStyle: token.fontStyle as unknown as 'normal' | 'italic',
38
- }}
39
- >
40
- {token.content.replace(/ /g, '\u00A0')}
41
- </Text>
42
- ))}
43
- <Text
44
- style={{
45
- fontFamily: 'monospace',
46
- }}
47
- >
48
- {'\n'}
49
- </Text>
50
- </View>
51
- ))}
52
- </View>
78
+ <ScrollView horizontal showsHorizontalScrollIndicator={Platform.OS !== 'web'} style={styles.container} contentContainerStyle={styles.scrollContent}>
79
+ <View style={styles.contentContainer} onStartShouldSetResponder={() => true}>
80
+ {tokens.map((line, lineIndex) => (
81
+ <SyntaxLine key={`line-${lineIndex}`} line={line} fontSize={fontSize} />
82
+ ))}
83
+ </View>
84
+ </ScrollView>
53
85
  )
54
86
  }
55
87
 
@@ -1,27 +1,61 @@
1
1
  import type { TokenType } from '../../types'
2
2
  import React from 'react'
3
- import { Text, View } from 'react-native'
3
+ import { Platform, StyleSheet, Text, View } from 'react-native'
4
+
5
+ const monospaceFont = Platform.select({
6
+ ios: 'Menlo',
7
+ android: 'monospace',
8
+ default: 'monospace',
9
+ })
10
+
11
+ const styles = StyleSheet.create({
12
+ lineContainer: {
13
+ flexDirection: 'row',
14
+ flexWrap: 'wrap',
15
+ },
16
+ token: {
17
+ includeFontPadding: false,
18
+ },
19
+ })
4
20
 
5
21
  interface SyntaxLineProps {
6
22
  line: TokenType[]
7
23
  fontSize?: number
8
24
  }
9
25
 
10
- function SyntaxLine({ line, fontSize }: SyntaxLineProps) {
26
+ function SyntaxLine({ line, fontSize = 14 }: SyntaxLineProps) {
27
+ const lineHeight = fontSize * 1.5
28
+
11
29
  return (
12
- <View style={{ flexDirection: 'row', flexWrap: 'wrap' }}>
30
+ <View
31
+ style={[
32
+ styles.lineContainer,
33
+ {
34
+ minHeight: lineHeight,
35
+ },
36
+ ]}
37
+ >
13
38
  {line.map((token, tokenIndex) => {
14
- // Preserve whitespace
15
39
  const content = token.content.replace(/ /g, '\u00A0')
16
40
  return (
17
41
  <Text
18
- key={`${content}-${tokenIndex}`}
19
- style={{
20
- color: token.color,
21
- fontFamily: 'monospace',
22
- fontSize,
23
- fontStyle: token.fontStyle as 'normal' | 'italic',
24
- }}
42
+ key={`${tokenIndex}-${content.slice(0, 8)}`}
43
+ style={[
44
+ styles.token,
45
+ {
46
+ color: token.color || '#FFFFFF',
47
+ fontFamily: monospaceFont,
48
+ fontSize,
49
+ fontStyle: token.fontStyle as 'normal' | 'italic',
50
+ fontWeight: token.fontWeight as 'normal' | 'bold',
51
+ lineHeight,
52
+ ...(Platform.OS === 'ios'
53
+ ? {
54
+ paddingTop: 1,
55
+ }
56
+ : {}),
57
+ },
58
+ ]}
25
59
  >
26
60
  {content}
27
61
  </Text>
@@ -1,6 +1,6 @@
1
1
  export interface TokenType {
2
2
  content: string
3
- color: string
3
+ color?: string
4
4
  fontStyle?: string
5
5
  fontWeight?: string
6
6
  }
@@ -16,4 +16,5 @@ export interface SyntaxHighlighterProps {
16
16
  language: LanguageInput
17
17
  languageId: string
18
18
  theme?: ThemeRegistrationAny
19
+ fontSize?: number
19
20
  }