Skip to content

Instantly share code, notes, and snippets.

@aravindanve
Created May 15, 2023 07:18
Show Gist options
  • Save aravindanve/1958c3b2c00aa84cb4a63b4464578816 to your computer and use it in GitHub Desktop.
Save aravindanve/1958c3b2c00aa84cb4a63b4464578816 to your computer and use it in GitHub Desktop.
import { StatusBar } from "expo-status-bar";
import { StyleSheet, Text, View, useWindowDimensions } from "react-native";
import {
RenderHTML,
Document,
Node,
NodeWithChildren,
isDomElement,
} from "react-native-render-html";
import { parseDocument } from "htmlparser2";
const html = `
<p>
This is some sample text. <b>This text is bold. <i>This text is bold and italic.</i></b>
<u>Now this is some underlined, <i>italic underlined</i> and <b>bold underlined</b> text.</u>
<u>Finally, <b>this is <i>all three. <u>Now this is just redundant.</u></i></b></u>
</p>
<p>
This is some sample text. <strong class="test">This text is bold. <em>This text is bold and italic.</em></strong>
<u>Now this is some underlined, <i>italic underlined</i> and <strong>bold underlined</strong> text.</u>
<u>Finally, <strong>this is <i>all three. <u>Now this is just redundant.</u></i></strong></u>
</p>`;
export const isNodeWithChildren = (node: Node): node is NodeWithChildren => {
return "children" in node;
};
export const addStyleClassesToDom = (document: Document) => {
const stack = [[document, 0, 0]] as [Node, number, number][];
while (stack.length) {
let changed = false;
let [node, bCount, iCount] = stack.pop() as [Node, number, number];
if (isNodeWithChildren(node)) {
if (isDomElement(node)) {
if (["b", "strong"].indexOf(node.name) !== -1) {
bCount += 1;
changed = true;
} else if (["i", "em"].indexOf(node.name) !== -1) {
iCount += 1;
changed = true;
}
if (changed) {
node.attribs.class = node.attribs.class
? node.attribs.class + " "
: "";
if (bCount) node.attribs.class += "bold";
if (iCount) node.attribs.class += "italic";
}
}
for (const child of node.children) {
stack.push([child, bCount, iCount]);
}
}
}
return document;
};
export default function App() {
const { width } = useWindowDimensions();
const document = parseDocument(html);
return (
<View style={styles.container}>
<RenderHTML
contentWidth={width}
source={{ dom: addStyleClassesToDom(document) }}
classesStyles={{
bold: {
color: "red",
},
italic: {
color: "blue",
},
bolditalic: {
color: "magenta",
},
}}
/>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment