Skip to content

Commit

Permalink
Merge pull request #7 from fram-x/release/0.1.0
Browse files Browse the repository at this point in the history
Release-0.1.0
  • Loading branch information
bjornegil authored Sep 24, 2018
2 parents 54c6248 + a1c581c commit b91d703
Show file tree
Hide file tree
Showing 14 changed files with 360 additions and 37 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ buck-out/

# Bundle artifact
*.jsbundle
/coverage
/.vscode/.react
9 changes: 9 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Jest All",
"program": "${workspaceRoot}/node_modules/jest/bin/jest",
"args": ["--runInBand"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"name": "Attach to packager",
"program": "${workspaceRoot}/.vscode/launchReactNative.js",
Expand Down
101 changes: 89 additions & 12 deletions App.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,41 @@ export default class App extends Component<Props> {
return (
<View style={styles.container}>
<StyledText
text="Welcome to React Native <b>Styled Text</b> demo!"
text="Welcome to <b>React Native <demo>Styled Text</demo></b> demo!"
style={styles.welcome}
textStyles={textStyles}
/>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Text style={styles.instructions}>To get started, edit App.js</Text>
<Text style={styles.instructions}>{instructions}</Text>
<StyledText
text="Run <code>yarn add react-native-styled-text</code> to install"
style={styles.instruction}
textStyles={textStyles}
/>
<View style={styles.jsxContainer}>
<StyledText
text={'<ltgt>&lt;</ltgt><comp>StyledText</comp>'}
style={styles.jsx}
textStyles={jsxStyles}
/>
<StyledText
text={'text<eq>=</eq><string>"Happy &lt;b&gt;Styling&lt;/b&gt;!"'}
style={[styles.jsx, styles.jsxProp]}
textStyles={jsxStyles}
/>
<StyledText
text={"style<eq>=</eq><brace>{</brace>styles.header<brace>}</brace>"}
style={[styles.jsx, styles.jsxProp]}
textStyles={jsxStyles}
/>
<StyledText
text="<ltgt>/></ltgt>"
style={styles.jsx}
textStyles={jsxStyles}
/>
</View>
<StyledText
text="Happy <b>Styling</b>!"
style={styles.header}
/>
</View>
);
}
Expand All @@ -40,24 +68,73 @@ const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
padding: 30,
},
instructions: {
textAlign: 'center',
instruction: {
fontSize: 18,
textAlign: 'left',
color: '#333333',
marginBottom: 5,
padding: 30,
},
header: {
fontSize: 24,
color: 'orange',
textAlign: 'center',
padding: 30,
},
jsxContainer: {
backgroundColor: '#333',
padding: 10,
},
jsx: {
textAlign: 'left',
paddingLeft: 20,
paddingVertical: 4,
fontWeight: '500',
fontSize: 18,
fontFamily: 'courier',
},
jsxProp: {
paddingLeft: 40,
color: '#8EDDFF',
},
});

const textStyles = StyleSheet.create({
b: {
fontWeight: 'bold',
demo: {
textShadowOffset: { width: 2, height: 2 },
textShadowColor: '#555555',
textShadowRadius: 6,
fontSize: 24,
fontStyle: 'italic',
color: '#22AA44',
},
code: {
fontWeight: 'bold',
fontFamily: 'courier',
fontSize: 18,
}
});

const jsxStyles = StyleSheet.create({
ltgt: {
color: '#888',
},
comp: {
color: '#00CCB0',
},
eq: {
color: 'white',
},
brace: {
color: '#4797D6',
},
string: {
color: '#D68E76',
}
})
});
107 changes: 106 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,117 @@
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-blue.svg"></a>

## Introduction
The purpose of this library is to support easy rendering of mixed text styles.

<img src="https://github.com/fram-x/react-native-styled-text/raw/develop/docs/example.png" width="400">

The library implements a `StyledText` component taking an HTML-like text and a styles object as input properties.

## Installation
To install the library into your project, run yarn or npm:

`yarn add react-native-styled-text`

or

`npm i react-native-styled-text`

## Examples

### API
### Using default styles
For simple styling `StyledText` supports some predefined styles:

* b: **bold**
* i: *italic*

Example:

```javascript
import { StyleSheet } from 'react-native';
import { StyledText } from 'react-native-styled-text';

...
<StyledText
text="Happy <b>Styling</b>!"
style={styles.header}
/>
...

const styles = StyleSheet.create({
header: {
fontSize: 24,
color: 'orange',
textAlign: 'center',
padding: 30,
},
});

```

Renders as

<img src="https://github.com/fram-x/react-native-styled-text/raw/develop/docs/happyStyling.png" width="200">

### Using custom styles
For richer styling, you set the `textStyles` property of `StyledText` to an object (`StyleSheet`) containing your custom text styles and apply the styles in the `text` property.

Example:

```javascript
import { StyleSheet } from 'react-native';
import { StyledText } from 'react-native-styled-text';

...
<StyledText
text="Welcome to <b>React Native <demo>Styled Text</demo></b> demo!"
style={styles.welcome}
textStyles={textStyles}
/>
...

const styles = StyleSheet.create({
welcome: {
fontSize: 20,
textAlign: 'center',
padding: 30,
},
});

const textStyles = StyleSheet.create({
demo: {
textShadowOffset: { width: 2, height: 2 },
textShadowColor: '#555555',
textShadowRadius: 6,
fontSize: 24,
fontStyle: 'italic',
color: '#22AA44',
},
});

```

Renders as

<img src="https://github.com/fram-x/react-native-styled-text/raw/develop/docs/welcome.png" width="280">


## API
`StyledText` exposes the following properties:

| Name | Description |
| ---- | ----------- |
| text | String with style tags for mixed styling of the text. Each style tag must match one of the styles provided in textStyles or one of the default styles, see below. |
| style | Base style for the component, typically including layout properties. (Optional) |
| textStyles | Object (`StyleSheet`) containing definition of the styles used in the provided text. (Optional) |

The following default styles are defined:

| Name | Description |
| ---- | ----------- |
| b | **bold** |
| i | *italic* |



### Contributors
Bjørn Egil Hansen (@bjornegil)
Expand Down
Binary file added docs/example.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/happyStyling.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/welcome.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 14 additions & 6 deletions lib/StyledText/lexicalAnalyzer.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@

export type Token = {
type: string,
lexeme: string,
}

export const TOKEN_BEGIN_TAG = 'beginTag';
export const TOKEN_END_TAG = 'endTag';
export const TOKEN_BEGIN_TAG = 'begin tag';
export const TOKEN_END_TAG = 'end tag';
export const TOKEN_TEXT = 'text';

const replaceCodes = (text: string) => {
return text
.replace(/&quot;/g, '"')
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>')
}

export const scan = (text: string): Array<Token> => {
const tagRegex = /<([\w-]+)>|<\/([\w-]*)>/;
const tokens = [];
Expand All @@ -17,18 +23,20 @@ export const scan = (text: string): Array<Token> => {
const tag = tagRegex.exec(remainingText);

if (!tag) {
tokens.push({ type: TOKEN_TEXT, lexeme: remainingText });
const lexeme = replaceCodes(remainingText);
tokens.push({ type: TOKEN_TEXT, lexeme });
remainingText = '';
break;
}

if (tag.index > 0) {
const headText = remainingText.substring(0, tag.index);
tokens.push({ type: TOKEN_TEXT, lexeme: headText });
const lexeme = replaceCodes(headText);
tokens.push({ type: TOKEN_TEXT, lexeme });
remainingText = remainingText.substring(tag.index);
}

const styleName = tag[1];
const styleName = tag[1] || tag[2];
if (tag[0].startsWith('</')) {
tokens.push({ type: TOKEN_END_TAG, lexeme: styleName });
} else {
Expand Down
23 changes: 16 additions & 7 deletions lib/StyledText/parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,19 @@ const parseMixedText = (tokens: Array<Token>, startIndex: number)
const token = tokens[index];
switch (token.type) {
case TOKEN_BEGIN_TAG: {
const { styledText, length } = parseStyledText(tokens, index);
mixedText.push(styledText);
index += length;
break;
}
const { styledText, length } = parseStyledText(tokens, index);
mixedText.push(styledText);
index += length;
break;
}
case TOKEN_TEXT:
mixedText.push(token.lexeme);
index++;
break;
default: break;
default:
console.warn('Unexpected ' + token.type + ': ' + token.lexeme);
index++;
break;
}
}

Expand All @@ -72,6 +75,12 @@ const parseMixedText = (tokens: Array<Token>, startIndex: number)

export const parse = (text: string): Mixed => {
const tokens = scan(text);
const { mixedText } = parseMixedText(tokens, 0);
const { mixedText, length } = parseMixedText(tokens, 0);

if (length < tokens.length) {
const unexpectedToken = tokens[length];
console.warn('Unexpected ' + unexpectedToken.type + ': ' + unexpectedToken.lexeme);
}

return mixedText;
};
Loading

0 comments on commit b91d703

Please sign in to comment.