目前只支持转换字体颜色、背景颜色、粗体、斜体、删除线、下划线、超链接,剩下的会根据需求持续更新

1、将delta转换成html

delta列子

我们应该转换成下面这个样子

这里需要用到一个组件 QuillDeltaToHtmlConverter,本来可以直接用的,但是不能识别颜色,所以只能重写里面的方法 convert

class CustomQuillDeltaToHtmlConverter extends QuillDeltaToHtmlConverter {
  final List<Map<String, dynamic>> delta; // 声明 delta 属性

  CustomQuillDeltaToHtmlConverter(
      this.delta, // 在构造函数中初始化 delta
      ConverterOptions options)
      : super(delta, options);

  @override
  String convert() {
    var html = '';

    for (var op in delta) {
      var attributes = op['attributes'] ?? {};
      var text = op['insert'] ?? '';

      // 处理颜色
      String colorStyle = attributes['color'] != null
          ? 'style="color: ${attributes['color']};"'
          : '';

      // 处理背景颜色
      String bgColorStyle = attributes['background'] != null
          ? 'style="background: ${attributes['background']};"'
          : '';

      // 生成 HTML
      if (attributes.isNotEmpty) {
        html += '<span $colorStyle>';
        html += '<span $bgColorStyle>';
        // 检查是否有超链接
        if (attributes['link'] != null) {
          var link = attributes['link'];
          html += '<a href="$link" $colorStyle $bgColorStyle>';
        } else {
          html += '<span $colorStyle $bgColorStyle>';
        }
        if (attributes['bold'] == true) html += '<strong>';
        if (attributes['italic'] == true) html += '<em>';
        if (attributes['underline'] == true) html += '<u>';
        if (attributes['strike'] == true) html += '<s>';

        html += text;

        if (attributes['strike'] == true) html += '</s>';
        if (attributes['underline'] == true) html += '</u>';
        if (attributes['italic'] == true) html += '</em>';
        if (attributes['bold'] == true) html += '</strong>';
        html += '</span>';

        // 结束链接或 span
        if (attributes['link'] != null) {
          html += '</a>';
        } else {
          html += '</span>';
        }
      } else {
        html += text;
      }
    }

    return html.replaceAll('\n', '<br/>'); // 处理换行
  }
}

2、将html转换成delta

转换方法

class HtmlToDeltaConverter {
  static Delta htmlToDelta(String html) {
    final document = html_parser.parse(html);
    var delta = Delta();

    // 处理节点并合并到 delta 中
    for (final node in document.body?.nodes ?? []) {
      if (node is dom.Element) {
        delta = delta.concat(_parseInlineStyles(node));
      }
    }

    // 检查末尾是否有换行符
    if (delta.length == 0 || (delta.last.data != '\n')) {
      delta.insert('\n'); // 如果没有换行符,则添加一个
    }

    return delta;
  }

  static Delta _parseInlineStyles(dom.Element element,
      [Map<String, dynamic>? inheritedStyles]) {
    var delta = Delta();
    var currentAttributes = _parseElementStyles(element);

    // 合并当前样式和继承的样式
    if (inheritedStyles != null) {
      currentAttributes.addAll(inheritedStyles);
    }

    for (final node in element.nodes) {
      if (node is dom.Text) {
        // 合并文本并应用当前的样式
        delta.insert(node.text, currentAttributes);
      } else if (node is dom.Element) {
        if (node.localName == 'br') {
          delta.insert('\n');
        } else {
          // 处理其他内联元素并合并样式
          delta = delta.concat(_parseInlineStyles(node, currentAttributes));
        }
      }
    }

    return delta;
  }

  static Map<String, dynamic> _parseElementStyles(dom.Element element) {
    final Map<String, dynamic> attributes = {};

    // 检查样式
    if (element.localName == 'strong') attributes['bold'] = true;
    if (element.localName == 'em') attributes['italic'] = true;
    if (element.localName == 'u') attributes['underline'] = true;
    if (element.localName == 's') attributes['strike'] = true;

    // 检查超链接
    if (element.localName == 'a') {
      final href = element.attributes['href'];
      if (href != null) {
        attributes['link'] = href; // 添加超链接属性
      }
    }

    var style = element.attributes['style'];
    if (style != null) {
      final colorValue = _parseColorFromStyle(style, 'color');
      if (colorValue != null) attributes['color'] = colorValue;

      final bgColorValue = _parseColorFromStyle(style, 'background');
      if (bgColorValue != null) attributes['background'] = bgColorValue;
    }

    return attributes;
  }

  static String? _parseColorFromStyle(String style, String type) {
    // 正则表达式字符串拼接
    final colorRegex = '$type:\\s*#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})';
    final colorMatch = RegExp(colorRegex).firstMatch(style);

    if (colorMatch != null) {
      return '#${colorMatch.group(1)}'; // 返回完整颜色值
    }

    // 匹配 rgba() 或 rgb() 格式
    final rgbaRegex =
        '$type:\\s*rgba?\\(\\s*(\\d+),\\s*(\\d+),\\s*(\\d+)(?:,\\s*([0-9.]+))?\\s*\\)';
    final rgbaMatch = RegExp(rgbaRegex).firstMatch(style);

    if (rgbaMatch != null) {
      final r = int.parse(rgbaMatch.group(1)!);
      final g = int.parse(rgbaMatch.group(2)!);
      final b = int.parse(rgbaMatch.group(3)!);
      return '#${(r << 16 | g << 8 | b).toRadixString(16).padLeft(6, '0')}'; // 转换为十六进制
    }

    return null; // 如果没有找到任何颜色
  }
}

 

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐