当前位置: 首页 > news >正文

Java中富文本转markdown

实现富文本即html语法转md,要求是尽可能展示效果一样,可以有少许误差,另外只实现了html中的body转md,其他标签如head等未实现。

大致思路是:通过jsoup工具获取html节点,再穷举替换。前提是熟悉html以及md语法

依赖如下:

        <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.16.1</version></dependency>

代码如下:

import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;import java.util.ArrayList;
import java.util.List;public class Html2MarkdownUtil {public static void main(String[] args) {String html = "<p style=\"padding: 0; margin: 10px 0; line-height: 1.5; font-size: 16px;\"><b style=\"padding: 0; margin: 0;\">Hello<font color=\"#c24f4a\" style=\"padding: 0; margin: 0;\">world</font></b></p>";System.out.println(parseHtml2Markdown(html));}/*** 解析html2md** @param html html* @return {@link String}*/public static String parseHtml2Markdown(String html) {Document doc = Jsoup.parse(html);StringBuilder sb = new StringBuilder();for (Element element : doc.body().children()) {HtmlElement htmlElement = new HtmlElement(element);sb.append(htmlElement.getMarkdownText());}return sb.toString();}/*** 标记文本** @param element 要素* @return {@link String}*/public static String toMarkdownText(Element element) {StringBuilder sb = new StringBuilder();String tagName = element.tagName().toLowerCase();String text = element.ownText();switch (tagName) {case "h1":sb.append("# ").append(text);break;case "h2":sb.append("## ").append(text);break;case "h3":sb.append("### ").append(text);break;case "h4":sb.append("#### ").append(text);break;case "h5":sb.append("##### ").append(text);break;case "h6":sb.append("###### ").append(text);break;case "p":case "font":case "b":case "span":sb.append(text);break;case "ul":for (Element child : element.children()) {sb.append("* ").append(child.text().trim()).append("\n");}break;case "ol":int index = 1;for (Element child : element.children()) {sb.append(index).append(". ").append(child.text().trim()).append("\n");index++;}break;case "a":sb.append("[").append(text).append("](").append(element.attr("href")).append(")");break;case "strong":sb.append("**").append(text).append("**");break;case "em":sb.append("_").append(text).append("_");break;case "blockquote":sb.append("> ").append(text);break;case "img":sb.append("![");if (element.hasAttr("alt")) {sb.append(element.attr("alt"));}sb.append("](").append(element.attr("src")).append(")");break;default:break;}return sb.toString();}@Datapublic static class HtmlElement {private Element element;private String tagName;private String ownText;private boolean isNewline;private List<HtmlElement> children;public HtmlElement(Element element) {this.element = element;this.tagName = element.tagName().toLowerCase();this.ownText = element.ownText();this.isNewline = isNewline();if (!StringUtils.equalsAny(this.tagName, "ul", "ol")) {Elements children = element.children();if (children.size() > 0) {this.children = new ArrayList<>();for (Element child : children) {this.children.add(new HtmlElement(child));}}}}public boolean isNewline() {return StringUtils.equalsAny(tagName, "h1", "h2", "h3", "h4", "h5", "h6", "p", "ul", "ol", "blockquote");}public String getMarkdownText() {StringBuilder sb = new StringBuilder();sb.append(toMarkdownText(element));if (children != null && children.size() > 0) {for (HtmlElement child : children) {sb.append(child.getMarkdownText());}}if (isNewline) {sb.append("\n");}return sb.toString();}}
}

相关文章:

  • MySQL 数据库如何实现 XA 规范?
  • 开发一款短剧视频小程序软件多少钱?
  • 道可云会展元宇宙平台全新升级,打造3D沉浸式展会新模式
  • Canvas鼠标画线
  • 基于Python的PyGame的俄罗斯方块游戏设计与实现
  • 算法leetcode|91. 解码方法(rust重拳出击)
  • 信号完整性分析
  • ChatGPT一周年,奥特曼官宣 OpenAI 新动作!
  • [MTK]安卓8 ADB执行ota升级
  • 简单实现Spring容器(二)
  • uniapp 显示文件流图片
  • 利用ElementUI配置商品的规格参数
  • Spring Security6 快速实战
  • webrtc网之sip转webrtc
  • windows11 调整鼠标灵敏度方法
  • hexo+github搭建个人博客
  • C++类中的特殊成员函数
  • DataBase in Android
  • ES6语法详解(一)
  • iOS小技巧之UIImagePickerController实现头像选择
  • java 多线程基础, 我觉得还是有必要看看的
  • React Transition Group -- Transition 组件
  • STAR法则
  • Theano - 导数
  • vue2.0开发聊天程序(四) 完整体验一次Vue开发(下)
  • Vue学习第二天
  • 从输入URL到页面加载发生了什么
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 使用Maven插件构建SpringBoot项目,生成Docker镜像push到DockerHub上
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • #[Composer学习笔记]Part1:安装composer并通过composer创建一个项目
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • #我与Java虚拟机的故事#连载05:Java虚拟机的修炼之道
  • (13)Latex:基于ΤΕΧ的自动排版系统——写论文必备
  • (6)设计一个TimeMap
  • (react踩过的坑)Antd Select(设置了labelInValue)在FormItem中initialValue的问题
  • (Repost) Getting Genode with TrustZone on the i.MX
  • (SpringBoot)第七章:SpringBoot日志文件
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)Linux NTP配置详解 (Network Time Protocol)
  • (转载)(官方)UE4--图像编程----着色器开发
  • .NET CLR基本术语
  • .NET Core WebAPI中封装Swagger配置
  • .NET core 自定义过滤器 Filter 实现webapi RestFul 统一接口数据返回格式
  • .NET 解决重复提交问题
  • .net 写了一个支持重试、熔断和超时策略的 HttpClient 实例池
  • .Net的DataSet直接与SQL2005交互
  • .Net环境下的缓存技术介绍
  • .net快速开发框架源码分享
  • [ C++ ] STL_vector -- 迭代器失效问题
  • []我的函数库
  • []指针
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色