【RN】实现markdown文本简单解析

news/2024/10/10 15:16:22/

需求

  • 支持文本插入,比如 xxx {product_name} xxx ,如果提供了product_name变量的值为feedback,则可以渲染出 xxx feedback xxx
  • 支持链接解析,比如 [baidu](https://www.baidu.com/),可以直接渲染成超链接的形式。
  • 支持插入reactnode元素,比如 xxx {jump_node} xxx,且jump_node是一个reactnode元素,则可以将node节点插入到{}位置上。

实现

步骤:

  • 先解析链接, 返回这样子的数据结构。超链接返回url-text的对象,非超链接直接返回文本字符串
javascript">export interface LinkPart {text: string;url?: string;onClick?: string;
}export type ParsedTextPart = string | LinkPart;[{text: 'baidu',url: 'https://www.baidu.com/',},'other content','other content',
];
  • 遍历解析后的超链接数组,如果是对象,则渲染超链接;如果是字符串,继续解析
  • 解析字符串,判断需要解析的{}里面的文本是否是纯文本,如果是纯文本,则直接Text渲染;如果是react元素,则渲染该元素

TextTemplate.tsx:

javascript">import React, { ReactNode } from 'react';
import { routeCenter } from '@shopeepay-rn/route-center';
import { usePageContainerContext } from '@shopeepay-rn/page-container';
import { StyleProp, Text, TextStyle, View, ViewStyle } from 'react-native';
import { parseLinkText } from '../../utils';
import styles from './styles';interface Props {template: string;// eg: {product_name:'spp', click_node:<Text></Text>}replaceValueMap: Record<string, string | number | ReactNode>;textStyle?: StyleProp<TextStyle>;containerStyle?: StyleProp<ViewStyle>;
}/*** 支持解析字符串、解析react元素、解析超链接* @param template 需要解析的字符串* @param replaceValueMap 需要替换的key-value,value支持字符串和react元素* @param textStyle 字体样式* @param containerStyle 容器样式* @returns react元素*/
export const TextTemplate = ({template,replaceValueMap,textStyle,containerStyle,
}: Props) => {const { rootTag } = usePageContainerContext();const parseText = (text: string, index: number) => {const result: React.ReactNode[] = [];let lastIndex = 0;text.replace(/{(\w+)}/g, (match: string, key: string, offset: number) => {const replaceValue = replaceValueMap[key];if (offset > lastIndex) {// 未被匹配到的result.push(<Text key={index} style={textStyle}>{text.substring(lastIndex, offset)}</Text>);}if (React.isValidElement(replaceValue)) {// 需要替换的是reactnode元素result.push(React.cloneElement(replaceValue, { key: index }));} else if (typeof replaceValue === 'string') {// 需要替换的是字符串result.push(<Text key={index} style={textStyle}>{replaceValue}</Text>);}lastIndex = offset + match.length;return '';});if (lastIndex < text.length) {result.push(<Text key={index} style={textStyle}>{text.substring(lastIndex)}</Text>);}return result;};const parseTemplate = (text: string) => {// 解析链接const linkTexts = parseLinkText(text);return linkTexts?.map((part, index) => {return typeof part === 'string' ? (// 对于字符串,需要解析 纯字符串 还是 reactnode元素parseText(part, index)) : (<Textkey={index}style={styles.link}onPress={() =>routeCenter.navigateWeb(part.url || '',{navbar: {title: part.text || '',},},rootTag)}>{part.text}</Text>);});};return (<View style={[styles.textView, containerStyle]}><Text>{parseTemplate(template)}</Text></View>);
};

parseLinkText.ts:

javascript">export interface LinkPart {text: string;url?: string;onClick?: string;
}export type ParsedTextPart = string | LinkPart;const parseLinkText = (text: string): ParsedTextPart[] => {const regex = /\[([^\]]+)\]\(([^)]+)\)/g;const parts: ParsedTextPart[] = [];let lastIndex = 0;text.replace(regex,(match: string, p1: string, p2: string, offset: number) => {if (offset > lastIndex) {parts.push(text.substring(lastIndex, offset));}parts.push({ text: p1, url: p2 });lastIndex = offset + match.length;return '';});if (lastIndex < text.length) {parts.push(text.substring(lastIndex));}return parts;
};// FIXME: 添加 unit test
export { parseLinkText };

使用

javascript"><TextTemplatetemplate={"you can test the TextTemplate component, parse {string_text}, parse [baidu](https://www.baidu.com/) link, parse {click_node} to show popup"}replaceValueMap={{string_text:"test string",click_node:<Text>other react node</Text>}}textStyle={styles.titleText}
/>

http://www.ppmy.cn/news/1506338.html

相关文章

分享中建海龙科技的代表性建筑案例

中建海龙科技作为一家在建筑行业颇具影响力的企业&#xff0c;以其独特的建筑理念和先进的施工技术&#xff0c;创造了许多令人瞩目的成功建筑案例。其中最具代表性的是北京桦皮厂胡同8号楼的“原拆原建”项目和深圳市华章新筑项目。 北京桦皮厂胡同8号楼的“原拆原建”项目&a…

24年电赛——自动行驶小车(H题)基于 CCS Theia -陀螺仪 JY60 代码移植到 MSPM0G3507(附代码)

前言 只要搞懂 M0 的代码结构和 CCS 的图形化配置方法&#xff0c;代码移植就会变的很简单。因为本次电赛的需要&#xff0c;正好陀螺仪部分代码的移植是我完成的。&#xff08;末尾附全部代码&#xff09; 一、JY60 陀螺仪 JY60特点 1.模块集成高精度的陀螺仪、加速度计&…

AI学习记录 - 如何进行token理论知识,以GPT2为举例

AI学习记录已经发了十几篇&#xff0c;大佬们可以看看&#xff0c;如果有帮助动动小手点赞 token入门版&#xff0c;有空会更新具体代码操作&#xff0c;能学到一点东西的话&#xff0c;大佬们点个赞&#xff01;&#xff01;&#xff01; GPT4当中&#xff0c;我们提问问题是…

【Redis 进阶】哨兵 Sentinel(重点理解流程和原理)

Redis 的主从复制模式下&#xff0c;一旦主节点由于故障不能提供服务&#xff0c;需要人工进行主从切换&#xff0c;同时大量的客户端需要被通知切换到新的主节点上&#xff0c;对于上了一定规模的应用来说&#xff0c;这种方案是无法接受的&#xff0c;于是 Redis 从 2.8 开始…

windows系统的docker desktop安装 openjdk22 和 maven 3.9.8 的环境

​ 安装 Docker Desktop: 如果尚未安装 Docker Desktop&#xff0c;请从 Docker 官网 下载并安装 Docker Desktop。 创建 Dockerfile: 在你的开发目录中&#xff0c;创建一个名为 Dockerfile 的文件。这是 Docker 构建镜像所需的配置文件。 打开 Dockerfile 并添加以下内容以…

使用es-hadoop同步hive和es之间数据

&#x1f4bb;近期在华为云连接es时的时候发现不能输入账号密码&#xff0c;后面联系华为工程师了解到&#xff0c;华为云默认是非安全模式&#xff0c;即不需要输入账号密码。 如果对你有所帮助&#xff0c;欢迎点赞收藏关注不迷路哦&#x1f493; 目录 使用es-hadoop同步h…

算法力扣刷题记录 七十【70. 爬楼梯及算法性能分析:时间复杂度和空间复杂度】

前言 动态规划章节第二篇。记录 七十【70. 爬楼梯】 一、题目阅读 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xf…

python机器人编程——开发一个pymatlab工具箱(上)

目录 一、前言二、实现过程2.1 封装属性2.2 数据流化显示2.3 输入数据的适应性 三、核心代码说明3.1 设置缓存3.2 随机信号3.3 根据设置绘图 五、总结四、源码PS.扩展阅读ps1.六自由度机器人相关文章资源ps2.四轴机器相关文章资源ps3.移动小车相关文章资源 一、前言 我们知道m…