|  | @@ -4,7 +4,7 @@ import 'package:flowy_editor/document/attributes.dart';
 | 
	
		
			
				|  |  |  import 'package:flowy_editor/document/node.dart';
 | 
	
		
			
				|  |  |  import 'package:flowy_editor/document/text_delta.dart';
 | 
	
		
			
				|  |  |  import 'package:flowy_editor/render/rich_text/rich_text_style.dart';
 | 
	
		
			
				|  |  | -import 'package:flowy_editor/service/internal_key_event_handlers/delete_text_handler.dart';
 | 
	
		
			
				|  |  | +import 'package:flutter/material.dart';
 | 
	
		
			
				|  |  |  import 'package:html/parser.dart' show parse;
 | 
	
		
			
				|  |  |  import 'package:html/dom.dart' as html;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -22,6 +22,12 @@ const String tagStrong = "strong";
 | 
	
		
			
				|  |  |  const String tagSpan = "span";
 | 
	
		
			
				|  |  |  const String tagCode = "code";
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +extension on Color {
 | 
	
		
			
				|  |  | +  String toRgbaString() {
 | 
	
		
			
				|  |  | +    return 'rgba($red, $green, $blue, $alpha)';
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /// Converting the HTML to nodes
 | 
	
		
			
				|  |  |  class HTMLToNodesConverter {
 | 
	
		
			
				|  |  |    final html.Document _document;
 | 
	
	
		
			
				|  | @@ -104,29 +110,78 @@ class HTMLToNodesConverter {
 | 
	
		
			
				|  |  |      return node;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  Map<String, String> _cssStringToMap(String? cssString) {
 | 
	
		
			
				|  |  | +    final result = <String, String>{};
 | 
	
		
			
				|  |  | +    if (cssString == null) {
 | 
	
		
			
				|  |  | +      return result;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    final entries = cssString.split(";");
 | 
	
		
			
				|  |  | +    for (final entry in entries) {
 | 
	
		
			
				|  |  | +      final tuples = entry.split(":");
 | 
	
		
			
				|  |  | +      if (tuples.length < 2) {
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      result[tuples[0]] = tuples[1];
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return result;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    Attributes? _getDeltaAttributesFromHtmlAttributes(
 | 
	
		
			
				|  |  |        LinkedHashMap<Object, String> htmlAttributes) {
 | 
	
		
			
				|  |  |      final attrs = <String, dynamic>{};
 | 
	
		
			
				|  |  |      final styleString = htmlAttributes["style"];
 | 
	
		
			
				|  |  | -    if (styleString != null) {
 | 
	
		
			
				|  |  | -      final entries = styleString.split(";");
 | 
	
		
			
				|  |  | -      for (final entry in entries) {
 | 
	
		
			
				|  |  | -        final tuples = entry.split(":");
 | 
	
		
			
				|  |  | -        if (tuples.length < 2) {
 | 
	
		
			
				|  |  | -          continue;
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        if (tuples[0] == "font-weight") {
 | 
	
		
			
				|  |  | -          int? weight = int.tryParse(tuples[1]);
 | 
	
		
			
				|  |  | -          if (weight != null && weight > 500) {
 | 
	
		
			
				|  |  | -            attrs["bold"] = true;
 | 
	
		
			
				|  |  | -          }
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | +    final cssMap = _cssStringToMap(styleString);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    final fontWeightStr = cssMap["font-weight"];
 | 
	
		
			
				|  |  | +    if (fontWeightStr != null) {
 | 
	
		
			
				|  |  | +      int? weight = int.tryParse(fontWeightStr);
 | 
	
		
			
				|  |  | +      if (weight != null && weight > 500) {
 | 
	
		
			
				|  |  | +        attrs["bold"] = true;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +    final backgroundColorStr = cssMap["background-color"];
 | 
	
		
			
				|  |  | +    final backgroundColor = _tryParseCssColorString(backgroundColorStr);
 | 
	
		
			
				|  |  | +    if (backgroundColor != null) {
 | 
	
		
			
				|  |  | +      attrs[StyleKey.backgroundColor] =
 | 
	
		
			
				|  |  | +          '0x${backgroundColor.value.toRadixString(16)}';
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |      return attrs.isEmpty ? null : attrs;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +  Color? _tryParseCssColorString(String? colorString) {
 | 
	
		
			
				|  |  | +    if (colorString == null) {
 | 
	
		
			
				|  |  | +      return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    final reg = RegExp(r'rgba\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)');
 | 
	
		
			
				|  |  | +    final match = reg.firstMatch(colorString);
 | 
	
		
			
				|  |  | +    if (match == null) {
 | 
	
		
			
				|  |  | +      return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (match.groupCount < 4) {
 | 
	
		
			
				|  |  | +      return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    final redStr = match.group(1);
 | 
	
		
			
				|  |  | +    final greenStr = match.group(2);
 | 
	
		
			
				|  |  | +    final blueStr = match.group(3);
 | 
	
		
			
				|  |  | +    final alphaStr = match.group(4);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    final red = redStr != null ? int.tryParse(redStr) : null;
 | 
	
		
			
				|  |  | +    final green = greenStr != null ? int.tryParse(greenStr) : null;
 | 
	
		
			
				|  |  | +    final blue = blueStr != null ? int.tryParse(blueStr) : null;
 | 
	
		
			
				|  |  | +    final alpha = alphaStr != null ? int.tryParse(alphaStr) : null;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    if (red == null || green == null || blue == null || alpha == null) {
 | 
	
		
			
				|  |  | +      return null;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    return Color.fromARGB(alpha, red, green, blue);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    _handleRichTextElement(Delta delta, html.Element element) {
 | 
	
		
			
				|  |  |      if (element.localName == tagSpan) {
 | 
	
		
			
				|  |  |        delta.insert(element.text,
 | 
	
	
		
			
				|  | @@ -321,9 +376,19 @@ class NodesToHTMLConverter {
 | 
	
		
			
				|  |  |    String _attributesToCssStyle(Map<String, dynamic> attributes) {
 | 
	
		
			
				|  |  |      final cssMap = <String, String>{};
 | 
	
		
			
				|  |  |      if (attributes[StyleKey.backgroundColor] != null) {
 | 
	
		
			
				|  |  | -      cssMap["background-color"] = attributes[StyleKey.backgroundColor];
 | 
	
		
			
				|  |  | -    } else if (attributes[StyleKey.color] != null) {
 | 
	
		
			
				|  |  | -      cssMap["color"] = attributes[StyleKey.color];
 | 
	
		
			
				|  |  | +      final color = Color(
 | 
	
		
			
				|  |  | +        int.parse(attributes[StyleKey.backgroundColor]),
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  | +      cssMap["background-color"] = color.toRgbaString();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (attributes[StyleKey.color] != null) {
 | 
	
		
			
				|  |  | +      final color = Color(
 | 
	
		
			
				|  |  | +        int.parse(attributes[StyleKey.color]),
 | 
	
		
			
				|  |  | +      );
 | 
	
		
			
				|  |  | +      cssMap["color"] = color.toRgbaString();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if (attributes[StyleKey.bold] == true) {
 | 
	
		
			
				|  |  | +      cssMap["font-weight"] = "bold";
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      return _cssMapToCssStyle(cssMap);
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -334,7 +399,7 @@ class NodesToHTMLConverter {
 | 
	
		
			
				|  |  |        if (previousValue.isEmpty) {
 | 
	
		
			
				|  |  |          return kv;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      return '$previousValue; $kv"';
 | 
	
		
			
				|  |  | +      return '$previousValue; $kv';
 | 
	
		
			
				|  |  |      });
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -360,7 +425,7 @@ class NodesToHTMLConverter {
 | 
	
		
			
				|  |  |      for (final op in delta.operations) {
 | 
	
		
			
				|  |  |        if (op is TextInsert) {
 | 
	
		
			
				|  |  |          final attributes = op.attributes;
 | 
	
		
			
				|  |  | -        if (attributes != null && attributes[StyleKey.bold] == true) {
 | 
	
		
			
				|  |  | +        if (attributes != null) {
 | 
	
		
			
				|  |  |            if (attributes.length == 1 && attributes[StyleKey.bold] == true) {
 | 
	
		
			
				|  |  |              final strong = html.Element.tag(tagStrong);
 | 
	
		
			
				|  |  |              strong.append(html.Text(op.content));
 |