You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ky...@apache.org on 2019/07/31 03:09:37 UTC

[incubator-weex] branch master updated: [Core] support Richtext component on eagle (#2766)

This is an automated email from the ASF dual-hosted git repository.

kyork pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-weex.git


The following commit(s) were added to refs/heads/master by this push:
     new 0b12b28  [Core] support Richtext component on eagle (#2766)
0b12b28 is described below

commit 0b12b28d4af50bbd5592e25672daedf99f788991
Author: jianhan-he <41...@users.noreply.github.com>
AuthorDate: Wed Jul 31 11:09:31 2019 +0800

    [Core] support Richtext component on eagle (#2766)
---
 .../main/java/com/taobao/weex/bridge/WXBridge.java |  99 +++++++--
 .../com/taobao/weex/bridge/WXBridgeManager.java    | 162 +++++++++++++++
 .../java/com/taobao/weex/common/IWXBridge.java     |   9 +
 .../measurefunc/TextContentBoxMeasurement.java     |   4 +-
 .../ui/action/GraphicActionAddChildToRichtext.java |  47 +++++
 .../GraphicActionRemoveChildFromRichtext.java      |  43 ++++
 .../ui/action/GraphicActionUpdateRichtextAttr.java |  43 ++++
 .../action/GraphicActionUpdateRichtextStyle.java   |  45 ++++
 .../weex/ui/component/richtext/WXRichText.java     |  97 ++++++++-
 .../weex/ui/component/richtext/node/ANode.java     |  13 ++
 .../weex/ui/component/richtext/node/ImgNode.java   |  14 +-
 .../ui/component/richtext/node/RichTextNode.java   |  73 ++++++-
 .../richtext/node/RichTextNodeCreator.java         |   3 +
 .../richtext/node/RichTextNodeManager.java         |  11 +
 .../weex/ui/component/richtext/node/SpanNode.java  |  13 ++
 ios/sdk/WeexSDK.xcodeproj/project.pbxproj          |  48 +++++
 ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h      |  14 ++
 ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm     | 112 ++++++++++
 ios/sdk/WeexSDK/Sources/Component/WXRichText.h     |   5 +-
 ios/sdk/WeexSDK/Sources/Component/WXRichText.mm    | 118 ++++++++++-
 weex_core/Source/CMakeLists.txt                    |   7 +-
 .../android/bridge/platform/android_side.cpp       |  50 +++++
 .../Source/android/bridge/platform/android_side.h  |  11 +
 weex_core/Source/android/wrap/wx_bridge.cpp        |  51 +++++
 weex_core/Source/android/wrap/wx_bridge.h          |  11 +
 .../android/jniprebuild/jniheader/WXBridge_jni.h   | 127 +++++++++++
 weex_core/Source/core/bridge/eagle_bridge.cpp      |  10 +-
 weex_core/Source/core/bridge/eagle_bridge.h        |   1 +
 weex_core/Source/core/bridge/platform_bridge.h     |  17 ++
 weex_core/Source/core/layout/layout.h              |   3 +
 .../action/render_action_add_child_to_richtext.cpp |  40 ++++
 .../action/render_action_add_child_to_richtext.h   |  53 +++++
 .../render_action_remove_child_from_richtext.cpp   |  21 +-
 .../render_action_remove_child_from_richtext.h     |  25 ++-
 .../render_action_update_richtext_child_attr.cpp   |  40 ++++
 .../render_action_update_richtext_child_attr.h     |  46 ++++
 .../render_action_update_richtext_child_style.cpp  |  42 ++++
 .../render_action_update_richtext_child_style.h    |  47 +++++
 .../Source/core/render/node/render_object.cpp      |  42 +++-
 weex_core/Source/core/render/node/render_object.h  |  12 ++
 weex_core/Source/core/render/page/render_page.cpp  | 231 ++++++++++++++-------
 weex_core/Source/core/render/page/render_page.h    |   8 +
 42 files changed, 1741 insertions(+), 127 deletions(-)

diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
old mode 100644
new mode 100755
index 5c20a52..512ab32
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridge.java
@@ -251,7 +251,7 @@ public class WXBridge implements IWXBridge {
     try{
       return callNative(instanceId, JSONArray.parseArray(tasks), callback);
     }catch (Exception e){
-      WXLogUtils.e(TAG, "callNative throw exception: " + e.getMessage());
+      WXLogUtils.e(TAG, "callNative throw exception: " + WXLogUtils.getStackTrace(e));
       return IWXBridge.INSTANCE_RENDERING;
     }
   }
@@ -266,7 +266,7 @@ public class WXBridge implements IWXBridge {
     try {
       errorCode = WXBridgeManager.getInstance().callNative(instanceId, tasks, callback);
     } catch (Throwable e) {
-      WXLogUtils.e(TAG, "callNative throw exception:" + e.getMessage());
+      WXLogUtils.e(TAG, "callNative throw exception:" + WXLogUtils.getStackTrace(e));
     }
 
     if (WXEnvironment.isApkDebugable()) {
@@ -436,7 +436,7 @@ public class WXBridge implements IWXBridge {
     } catch (Throwable e) {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callCreateBody throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callCreateBody throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -451,7 +451,7 @@ public class WXBridge implements IWXBridge {
     } catch (Throwable e) {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callCreateFinish throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callCreateFinish throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -469,7 +469,7 @@ public class WXBridge implements IWXBridge {
     } catch (Throwable e) {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "reloadPageNative throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "reloadPageNative throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
   }
@@ -487,7 +487,7 @@ public class WXBridge implements IWXBridge {
     } catch (Throwable e) {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callCreateBody throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callCreateBody throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -507,7 +507,7 @@ public class WXBridge implements IWXBridge {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
         e.printStackTrace();
-        WXLogUtils.e(TAG, "callAddElement throw error:" + e.getMessage());
+        WXLogUtils.e(TAG, "callAddElement throw error:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -521,7 +521,7 @@ public class WXBridge implements IWXBridge {
       errorCode = WXBridgeManager.getInstance().callRemoveElement(instanceId, ref);
     } catch (Throwable e) {
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callRemoveElement throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callRemoveElement throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -535,7 +535,7 @@ public class WXBridge implements IWXBridge {
       errorCode = WXBridgeManager.getInstance().callMoveElement(instanceId, ref, parentref, index);
     } catch (Throwable e) {
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callMoveElement throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callMoveElement throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -550,7 +550,7 @@ public class WXBridge implements IWXBridge {
     } catch (Throwable e) {
       //catch everything during call native.
       // if(WXEnvironment.isApkDebugable()){
-      WXLogUtils.e(TAG, "callAddEvent throw exception:" + e.getMessage());
+      WXLogUtils.e(TAG, "callAddEvent throw exception:" + WXLogUtils.getStackTrace(e));
       // }
     }
     return errorCode;
@@ -565,7 +565,7 @@ public class WXBridge implements IWXBridge {
     } catch (Throwable e) {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callRemoveEvent throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callRemoveEvent throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -584,7 +584,7 @@ public class WXBridge implements IWXBridge {
     } catch (Throwable e) {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callUpdateStyle throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callUpdateStyle throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -599,7 +599,7 @@ public class WXBridge implements IWXBridge {
     } catch (Throwable e) {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callUpdateAttr throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callUpdateAttr throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -607,6 +607,67 @@ public class WXBridge implements IWXBridge {
 
   @Override
   @CalledByNative
+  public int callAddChildToRichtext(String instanceId, String nodeType, String ref, String parentRef, String richTextRef,
+                             HashMap<String, String> styles, HashMap<String, String> attrs){
+    int errorCode = IWXBridge.INSTANCE_RENDERING;
+    try {
+      errorCode = WXBridgeManager.getInstance().callAddChildToRichtext(instanceId, nodeType, ref, parentRef, richTextRef,
+              styles, attrs);
+    } catch (Throwable e) {
+      //catch everything during call native.
+      if (WXEnvironment.isApkDebugable()) {
+        WXLogUtils.e(TAG, "callAddChildToRichtext throw exception:" + WXLogUtils.getStackTrace(e));
+      }
+    }
+    return errorCode;
+  }
+  @Override
+  @CalledByNative
+  public int callRemoveChildFromRichtext(String instanceId, String ref, String parentRef, String richTextRef){
+    int errorCode = IWXBridge.INSTANCE_RENDERING;
+    try {
+      errorCode = WXBridgeManager.getInstance().callRemoveChildFromRichtext(instanceId, ref, parentRef, richTextRef);
+    } catch (Throwable e) {
+      //catch everything during call native.
+      if (WXEnvironment.isApkDebugable()) {
+        WXLogUtils.e(TAG, "callRemoveChildFromRichtext throw exception:" + WXLogUtils.getStackTrace(e));
+      }
+    }
+    return errorCode;
+  }
+
+  @Override
+  @CalledByNative
+  public int callUpdateRichtextStyle(String instanceId, String ref, HashMap<String, String> styles, String parentRef, String richTextRef){
+    int errorCode = IWXBridge.INSTANCE_RENDERING;
+    try {
+      errorCode = WXBridgeManager.getInstance().callUpdateRichtextStyle(instanceId, ref, styles, parentRef, richTextRef);
+    } catch (Throwable e) {
+      //catch everything during call native.
+      if (WXEnvironment.isApkDebugable()) {
+        WXLogUtils.e(TAG, "callUpdateRichtextStyle throw exception:" + WXLogUtils.getStackTrace(e));
+      }
+    }
+    return errorCode;
+  }
+  @Override
+  @CalledByNative
+  public int callUpdateRichtextChildAttr(String instanceId, String ref, HashMap<String, String> attrs, String parentRef, String richTextRef){
+    int errorCode = IWXBridge.INSTANCE_RENDERING;
+    try {
+      errorCode = WXBridgeManager.getInstance().callUpdateRichtextChildAttr(instanceId, ref, attrs, parentRef, richTextRef);
+    } catch (Throwable e) {
+      //catch everything during call native.
+      if (WXEnvironment.isApkDebugable()) {
+        WXLogUtils.e(TAG, "callUpdateRichtextChildAttr throw exception:" + WXLogUtils.getStackTrace(e));
+      }
+    }
+    return errorCode;
+  }
+
+
+  @Override
+  @CalledByNative
   public int callLayout(String instanceId, String ref, int top, int bottom, int left, int right, int height, int width, boolean isRTL, int index) {
     int errorCode = IWXBridge.INSTANCE_RENDERING;
     try {
@@ -614,7 +675,7 @@ public class WXBridge implements IWXBridge {
     } catch (Throwable e) {
       //catch everything during call native.
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callLayout throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callLayout throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -627,7 +688,7 @@ public class WXBridge implements IWXBridge {
     try {
       errorCode = WXBridgeManager.getInstance().callCreateFinish(instanceId);
     } catch (Throwable e) {
-      WXLogUtils.e(TAG, "callCreateFinish throw exception:" + e.getMessage());
+      WXLogUtils.e(TAG, "callCreateFinish throw exception:" + WXLogUtils.getStackTrace(e));
     }
     return errorCode;
   }
@@ -639,7 +700,7 @@ public class WXBridge implements IWXBridge {
     try {
       errorCode = WXBridgeManager.getInstance().callRenderSuccess(instanceId);
     } catch (Throwable e) {
-      WXLogUtils.e(TAG, "callCreateFinish throw exception:" + e.getMessage());
+      WXLogUtils.e(TAG, "callCreateFinish throw exception:" + WXLogUtils.getStackTrace(e));
     }
     return errorCode;
   }
@@ -651,7 +712,7 @@ public class WXBridge implements IWXBridge {
     try {
       errorCode = WXBridgeManager.getInstance().callAppendTreeCreateFinish(instanceId, ref);
     } catch (Throwable e) {
-      WXLogUtils.e(TAG, "callAppendTreeCreateFinish throw exception:" + e.getMessage());
+      WXLogUtils.e(TAG, "callAppendTreeCreateFinish throw exception:" + WXLogUtils.getStackTrace(e));
     }
     return errorCode;
   }
@@ -664,7 +725,7 @@ public class WXBridge implements IWXBridge {
       errorCode = WXBridgeManager.getInstance().callHasTransitionPros(instanceId, ref, styles);
     } catch (Throwable e) {
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "callHasTransitionPros throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "callHasTransitionPros throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return errorCode;
@@ -678,7 +739,7 @@ public class WXBridge implements IWXBridge {
       obj = WXBridgeManager.getInstance().getMeasurementFunc(instanceId, renderObjectPtr);
     } catch (Throwable e) {
       if (WXEnvironment.isApkDebugable()) {
-        WXLogUtils.e(TAG, "getMeasurementFunc throw exception:" + e.getMessage());
+        WXLogUtils.e(TAG, "getMeasurementFunc throw exception:" + WXLogUtils.getStackTrace(e));
       }
     }
     return obj;
diff --git a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
old mode 100644
new mode 100755
index 0ad54e6..27136f6
--- a/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/bridge/WXBridgeManager.java
@@ -65,6 +65,7 @@ import com.taobao.weex.ui.WXComponentRegistry;
 import com.taobao.weex.ui.WXRenderManager;
 import com.taobao.weex.ui.action.ActionReloadPage;
 import com.taobao.weex.ui.action.BasicGraphicAction;
+import com.taobao.weex.ui.action.GraphicActionAddChildToRichtext;
 import com.taobao.weex.ui.action.GraphicActionAddElement;
 import com.taobao.weex.ui.action.GraphicActionAddEvent;
 import com.taobao.weex.ui.action.GraphicActionAppendTreeCreateFinish;
@@ -73,10 +74,13 @@ import com.taobao.weex.ui.action.GraphicActionCreateFinish;
 import com.taobao.weex.ui.action.GraphicActionLayout;
 import com.taobao.weex.ui.action.GraphicActionMoveElement;
 import com.taobao.weex.ui.action.GraphicActionRefreshFinish;
+import com.taobao.weex.ui.action.GraphicActionRemoveChildFromRichtext;
 import com.taobao.weex.ui.action.GraphicActionRemoveElement;
 import com.taobao.weex.ui.action.GraphicActionRemoveEvent;
 import com.taobao.weex.ui.action.GraphicActionRenderSuccess;
 import com.taobao.weex.ui.action.GraphicActionUpdateAttr;
+import com.taobao.weex.ui.action.GraphicActionUpdateRichtextAttr;
+import com.taobao.weex.ui.action.GraphicActionUpdateRichtextStyle;
 import com.taobao.weex.ui.action.GraphicActionUpdateStyle;
 import com.taobao.weex.ui.action.GraphicPosition;
 import com.taobao.weex.ui.action.GraphicSize;
@@ -3010,6 +3014,164 @@ public class WXBridgeManager implements Callback, BactchExecutor {
       WXSDKManager.getInstance().getSDKInstance(instanceId).setComponentsInfoExceedGPULimit(ext);
     }
   }
+
+  public int callAddChildToRichtext(String instanceId, String nodeType, String ref, String parentRef, String richTextRef,
+                                    HashMap<String, String> styles, HashMap<String, String> attrs){
+    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
+      if (WXEnvironment.isApkDebugable()){
+        WXLogUtils.d("[WXBridgeManager] call callAddChildToRichtext arguments is null");
+      }
+
+      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
+              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callAddChildToRichtext",
+              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
+      return IWXBridge.INSTANCE_RENDERING_ERROR;
+    }
+
+    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
+      mLodBuilder.append("[WXBridgeManager] callAddChildToRichtext >>>> instanceId:").append(instanceId)
+              .append(", nodeType:").append(nodeType).append(", ref:").append(ref).append(", parentRef:")
+              .append(parentRef).append(", richTextRef:").append(richTextRef).append(", styles:")
+              .append(styles.toString()).append(", attrs:").append(attrs.toString());
+      WXLogUtils.d(mLodBuilder.substring(0));
+      mLodBuilder.setLength(0);
+    }
+
+    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
+      return IWXBridge.DESTROY_INSTANCE;
+    }
+    try {
+      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
+      if (instance != null) {
+        final BasicGraphicAction action = new GraphicActionAddChildToRichtext(instance,nodeType,ref,parentRef,richTextRef,styles,attrs
+        );
+        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
+      }
+    } catch (Exception e) {
+      WXLogUtils.e("[WXBridgeManager] callAddChildToRichtext exception: ", WXLogUtils.getStackTrace(e));
+      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
+              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callAddChildToRichtext",
+              WXLogUtils.getStackTrace(e), null);
+    }
+
+    return IWXBridge.INSTANCE_RENDERING;
+  }
+
+  public int callRemoveChildFromRichtext(String instanceId, String ref, String parentRef, String richTextRef){
+    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
+      if (WXEnvironment.isApkDebugable()){
+        WXLogUtils.d("[WXBridgeManager] call callRemoveChildFromRichtext arguments is null");
+      }
+
+      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
+              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRemoveChildFromRichtext",
+              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
+      return IWXBridge.INSTANCE_RENDERING_ERROR;
+    }
+
+    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
+      mLodBuilder.append("[WXBridgeManager] callRemoveChildFromRichtext >>>> instanceId:").append(instanceId)
+              .append(", ref:").append(ref).append(", parentRef:").append(parentRef).append(", richTextRef:").append(richTextRef);
+      WXLogUtils.d(mLodBuilder.substring(0));
+      mLodBuilder.setLength(0);
+    }
+
+    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
+      return IWXBridge.DESTROY_INSTANCE;
+    }
+    try {
+      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
+      if (instance != null) {
+        final BasicGraphicAction action = new GraphicActionRemoveChildFromRichtext(instance, ref, parentRef, richTextRef);
+        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
+      }
+    } catch (Exception e) {
+      WXLogUtils.e("[WXBridgeManager] callRemoveChildFromRichtext exception: ", e);
+      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
+              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRemoveChildFromRichtext",
+              WXLogUtils.getStackTrace(e), null);
+    }
+
+    return IWXBridge.INSTANCE_RENDERING;
+  }
+
+  public int callUpdateRichtextStyle(String instanceId, String ref, HashMap<String, String> styles, String parentRef, String richTextRef){
+    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
+      if (WXEnvironment.isApkDebugable()){
+        WXLogUtils.d("[WXBridgeManager] call callUpdateRichtextStyle arguments is null");
+      }
+
+      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
+              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateRichtextStyle",
+              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
+      return IWXBridge.INSTANCE_RENDERING_ERROR;
+    }
+
+    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
+      mLodBuilder.append("[WXBridgeManager] callUpdateRichtextStyle >>>> instanceId:").append(instanceId)
+              .append(", ref:").append(ref).append(", styles:").append(styles.toString()).append(", parentRef:")
+              .append(parentRef).append(", richTextRef:").append(richTextRef);
+      WXLogUtils.d(mLodBuilder.substring(0));
+      mLodBuilder.setLength(0);
+    }
+
+    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
+      return IWXBridge.DESTROY_INSTANCE;
+    }
+    try {
+      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
+      if (instance != null) {
+        final BasicGraphicAction action = new GraphicActionUpdateRichtextStyle(instance, ref, styles, parentRef, richTextRef);
+        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
+      }
+    } catch (Exception e) {
+      WXLogUtils.e("[WXBridgeManager] callUpdateRichtextStyle exception: ", e);
+      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
+              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateRichtextStyle",
+              WXLogUtils.getStackTrace(e), null);
+    }
+
+    return IWXBridge.INSTANCE_RENDERING;
+  }
+  public int callUpdateRichtextChildAttr(String instanceId, String ref, HashMap<String, String> attrs, String parentRef, String richTextRef){
+    if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) {
+      if (WXEnvironment.isApkDebugable()){
+        WXLogUtils.d("[WXBridgeManager] call callUpdateRichtextChildAttr arguments is null");
+      }
+
+      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
+              WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateRichtextChildAttr",
+              "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null);
+      return IWXBridge.INSTANCE_RENDERING_ERROR;
+    }
+
+    if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) {
+      mLodBuilder.append("[WXBridgeManager] callUpdateRichtextChildAttr >>>> instanceId:").append(instanceId)
+              .append(", ref:").append(ref).append(", attrs:").append(attrs.toString()).append(", parentRef:")
+              .append(parentRef).append(", richTextRef:").append(richTextRef);
+      WXLogUtils.d(mLodBuilder.substring(0));
+      mLodBuilder.setLength(0);
+    }
+
+    if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) {
+      return IWXBridge.DESTROY_INSTANCE;
+    }
+    try {
+      WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
+      if (instance != null) {
+        final BasicGraphicAction action = new GraphicActionUpdateRichtextAttr(instance, ref, attrs, parentRef, richTextRef);
+        WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action);
+      }
+    } catch (Exception e) {
+      WXLogUtils.e("[WXBridgeManager] callUpdateRichtextChildAttr exception: ", e);
+      WXExceptionUtils.commitCriticalExceptionRT(instanceId,
+              WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateRichtextChildAttr",
+              WXLogUtils.getStackTrace(e), null);
+    }
+
+    return IWXBridge.INSTANCE_RENDERING;
+  }
+
   public int callLayout(String pageId, String ref, int top, int bottom, int left, int right, int height, int width, boolean isRTL, int index) {
 
     if (TextUtils.isEmpty(pageId) || TextUtils.isEmpty(ref)) {
diff --git a/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java b/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java
old mode 100644
new mode 100755
index 0df86f7..5e69b5c
--- a/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java
+++ b/android/sdk/src/main/java/com/taobao/weex/common/IWXBridge.java
@@ -155,6 +155,15 @@ public interface IWXBridge extends IWXObject {
   int callUpdateAttrs(String instanceId, String ref,
                       HashMap<String, String> attrs);
 
+  int callAddChildToRichtext(String instanceId, String nodeType, String ref, String parentRef, String richTextRef,
+                             HashMap<String, String> styles, HashMap<String, String> attrs);
+
+  int callRemoveChildFromRichtext(String instanceId, String ref, String parentRef, String richTextRef);
+
+  int callUpdateRichtextStyle(String instanceId, String ref, HashMap<String, String> styles, String parentRef, String richTextRef);
+
+  int callUpdateRichtextChildAttr(String instanceId, String ref, HashMap<String, String> attrs, String parentRef, String richTextRef);
+
   int callLayout(String instanceId, String ref, int top, int bottom, int left, int right, int height, int width, boolean isRTL, int index);
 
   int callCreateFinish(String instanceId);
diff --git a/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java b/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java
old mode 100644
new mode 100755
index a5facd5..3a22532
--- a/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java
+++ b/android/sdk/src/main/java/com/taobao/weex/layout/measurefunc/TextContentBoxMeasurement.java
@@ -142,7 +142,7 @@ public class TextContentBoxMeasurement extends ContentBoxMeasurement {
     hasBeenMeasured = true;
     float textWidth = getTextWidth(mTextPaint, width, widthMeasureMode == MeasureMode.EXACTLY);
 
-    if (textWidth > 0 && mText != null) {
+    if (textWidth > 0 && spanned != null) {
       layout = createLayout(textWidth,null);
       previousWidth = layout.getWidth();
       if (Float.isNaN(width)) {
@@ -458,7 +458,7 @@ public class TextContentBoxMeasurement extends ContentBoxMeasurement {
     float contentWidth = WXDomUtils.getContentWidth(mComponent.getPadding(), mComponent.getBorder(), computedWidth);
     if (contentWidth > 0) {
       spanned = createSpanned(mText);
-      if (mText != null) {
+      if (spanned != null) {
         layout = createLayout(contentWidth, layout);
         previousWidth = layout.getWidth();
       } else {
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionAddChildToRichtext.java b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionAddChildToRichtext.java
new file mode 100755
index 0000000..bddad36
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionAddChildToRichtext.java
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.taobao.weex.ui.action;
+
+import android.support.annotation.NonNull;
+import android.util.Log;
+
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.ui.component.richtext.WXRichText;
+
+import java.util.HashMap;
+
+public class GraphicActionAddChildToRichtext extends BasicGraphicAction {
+
+    public GraphicActionAddChildToRichtext(@NonNull WXSDKInstance instance, String nodeType, String ref, String parentRef, String richTextRef,
+                                           HashMap<String, String> styles, HashMap<String, String> attrs){
+        super(instance,richTextRef);
+        if(WXSDKManager.getInstance() != null && WXSDKManager.getInstance().getWXRenderManager() != null) {
+            WXRichText richText = (WXRichText) WXSDKManager.getInstance().getWXRenderManager()
+                    .getWXComponent(getPageId(), richTextRef);
+            if (richText != null) {
+                richText.AddChildNode(ref, nodeType, parentRef, styles, attrs);
+            }
+        }
+    }
+    @Override
+    public void executeAction() {
+
+    }
+}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionRemoveChildFromRichtext.java b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionRemoveChildFromRichtext.java
new file mode 100755
index 0000000..5c5cf2c
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionRemoveChildFromRichtext.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.taobao.weex.ui.action;
+
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.ui.component.richtext.WXRichText;
+import com.taobao.weex.ui.component.richtext.node.RichTextNode;
+
+public class GraphicActionRemoveChildFromRichtext extends BasicGraphicAction{
+    private String ref;
+    private String parentRef;
+    private WXRichText richText;
+    public GraphicActionRemoveChildFromRichtext(WXSDKInstance instance,String ref,String parentRef,String richtextRef){
+        super(instance, richtextRef);
+        this.ref = ref;
+        this.parentRef = parentRef;
+        richText = (WXRichText) WXSDKManager.getInstance().getWXRenderManager().
+                getWXComponent(instance.getInstanceId(),richtextRef);
+        if(richText != null){
+            richText.removeChildNode(parentRef,ref);
+        }
+    }
+    @Override
+    public void executeAction() {
+    }
+}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateRichtextAttr.java b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateRichtextAttr.java
new file mode 100755
index 0000000..3c30eb5
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateRichtextAttr.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.taobao.weex.ui.action;
+
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.ui.component.richtext.WXRichText;
+import java.util.HashMap;
+import java.util.Map;
+
+public class GraphicActionUpdateRichtextAttr extends BasicGraphicAction{
+
+    public GraphicActionUpdateRichtextAttr(WXSDKInstance instance, String ref, HashMap<String, String> attrs, String parentRef, String richTextRef){
+        super(instance, richTextRef);
+        WXRichText richText =  (WXRichText) WXSDKManager.getInstance().getWXRenderManager()
+                .getWXComponent(getPageId(), richTextRef);
+        if(richText != null) {
+            Map<String, Object> map = new HashMap<>();
+            map.putAll(attrs);
+            richText.updateChildNodeAttrs(ref, map);
+        }
+    }
+    @Override
+    public void executeAction() {
+    }
+
+}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateRichtextStyle.java b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateRichtextStyle.java
new file mode 100755
index 0000000..c5c3231
--- /dev/null
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/action/GraphicActionUpdateRichtextStyle.java
@@ -0,0 +1,45 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package com.taobao.weex.ui.action;
+
+import com.taobao.weex.WXSDKInstance;
+import com.taobao.weex.WXSDKManager;
+import com.taobao.weex.ui.component.richtext.WXRichText;
+import com.taobao.weex.ui.component.richtext.node.RichTextNode;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class GraphicActionUpdateRichtextStyle  extends BasicGraphicAction{
+    public GraphicActionUpdateRichtextStyle(WXSDKInstance instance, String ref, HashMap<String, String> styles, String parentRef, String richTextRef){
+        super(instance, richTextRef);
+        WXRichText richText =  (WXRichText) WXSDKManager.getInstance().getWXRenderManager()
+                .getWXComponent(getPageId(), richTextRef);
+        if(richText != null){
+                Map<String, Object> map = new HashMap<>();
+                map.putAll(styles);
+                richText.updateChildNodeStyles(ref, map);
+
+        }
+    }
+    @Override
+    public void executeAction() {
+
+    }
+}
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/WXRichText.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/WXRichText.java
old mode 100644
new mode 100755
index 0fccd12..06357a6
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/WXRichText.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/WXRichText.java
@@ -22,6 +22,7 @@ package com.taobao.weex.ui.component.richtext;
 import android.content.Context;
 import android.support.annotation.NonNull;
 import android.text.Spannable;
+import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.SpannedString;
 import android.text.TextUtils;
@@ -34,10 +35,15 @@ import com.taobao.weex.ui.component.WXComponent;
 import com.taobao.weex.ui.component.WXText;
 import com.taobao.weex.ui.component.WXVContainer;
 import com.taobao.weex.ui.component.richtext.node.RichTextNode;
+import com.taobao.weex.ui.component.richtext.node.RichTextNodeManager;
 
 import java.lang.reflect.InvocationTargetException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 public class WXRichText extends WXText {
+  private List<RichTextNode> nodes = new LinkedList<>();
 
   static class RichTextContentBoxMeasurement extends TextContentBoxMeasurement {
 
@@ -48,18 +54,25 @@ public class WXRichText extends WXText {
     @NonNull
     @Override
     protected Spanned createSpanned(String text) {
-      if (mComponent.getInstance() != null & mComponent.getInstance().getUIContext() != null &&
-              !TextUtils.isEmpty(mComponent.getInstanceId())) {
-        Spannable spannable = RichTextNode.parse(
-                mComponent.getInstance().getUIContext(),
-                mComponent.getInstanceId(),
-                mComponent.getRef(),
-                text);
+      if(!TextUtils.isEmpty(text)) {
+        if (mComponent.getInstance() != null & mComponent.getInstance().getUIContext() != null &&
+                !TextUtils.isEmpty(mComponent.getInstanceId())) {
+          Spannable spannable = RichTextNode.parse(
+                  mComponent.getInstance().getUIContext(),
+                  mComponent.getInstanceId(),
+                  mComponent.getRef(),
+                  text);
+          updateSpannable(spannable, RichTextNode.createSpanFlag(0));
+          return spannable;
+        } else {
+          return new SpannedString("");
+        }
+      }
+      else {
+        Spannable spannable = ((WXRichText)mComponent).toSpan();
         updateSpannable(spannable, RichTextNode.createSpanFlag(0));
         return spannable;
-      } else {
-        return new SpannedString("");
-      }
+        }
     }
   }
 
@@ -74,6 +87,70 @@ public class WXRichText extends WXText {
     super(instance, parent, basicComponentData);
     setContentBoxMeasurement(new RichTextContentBoxMeasurement(this));
   }
+  public void AddChildNode(String ref, String nodeType,String parentRef, Map<String,String> styles,Map<String,String> attrs) {
+    if(getInstance() != null && getInstance().getUIContext() != null && !TextUtils.isEmpty(getInstanceId()) &&
+            !TextUtils.isEmpty(ref) && !TextUtils.isEmpty(nodeType)) {
+      RichTextNode child = RichTextNodeManager.createRichTextNode(getInstance().getUIContext(), getInstanceId(), getRef(), ref, nodeType, styles, attrs);
+      if (TextUtils.isEmpty(parentRef)) {
+        nodes.add(child);
+      } else {
+        RichTextNode parent = findRichNode(parentRef);
+        if (parent != null) {
+          parent.addChildNode(child);
+        }
+      }
+    }
+  }
+  private Spannable toSpan(){
+    SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
+    if(nodes != null && !nodes.isEmpty()){
+      for(RichTextNode node:nodes){
+        spannableStringBuilder.append(node.toSpan(1));
+      }
+    }
+    return spannableStringBuilder;
+  }
+
+  public void removeChildNode(String parentRef,String ref) {
+    if (nodes != null && !nodes.isEmpty()) {
+      if (parentRef.equals("")) {
+        for (RichTextNode node : nodes) {
+          if (TextUtils.equals(node.getRef(), ref)) {
+            nodes.remove(node);
+          }
+        }
+      } else {
+        RichTextNode parent = findRichNode(parentRef);
+        if (parent != null) {
+          parent.removeChildNode(ref);
+        }
+      }
+    }
+  }
+  public void updateChildNodeStyles(String ref,Map<String,Object> styles){
+    RichTextNode node = findRichNode(ref);
+    if(node != null){
+      node.updateStyles(styles);
+    }
+  }
+  public void updateChildNodeAttrs(String ref,Map<String,Object> attrs){
+    RichTextNode node = findRichNode(ref);
+    if(node != null){
+      node.updateAttrs(attrs);
+    }
+  }
+  private RichTextNode findRichNode(String ref){
+    if(!TextUtils.isEmpty(ref)) {
+      RichTextNode theNode;
+      if (nodes != null && !nodes.isEmpty()) {
+        for (RichTextNode node : nodes) {
+          if ((theNode = node.findRichNode(ref)) != null)
+            return theNode;
+        }
+      }
+    }
+    return null;
+  }
 
   @Override
   protected WXRichTextView initComponentHostView(@NonNull Context context) {
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/ANode.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/ANode.java
old mode 100644
new mode 100755
index c61645f..b657188
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/ANode.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/ANode.java
@@ -19,11 +19,15 @@
 package com.taobao.weex.ui.component.richtext.node;
 
 import android.content.Context;
+import android.support.v4.util.ArrayMap;
 import android.text.SpannableStringBuilder;
 
 import com.taobao.weex.ui.component.richtext.span.ASpan;
 import com.taobao.weex.ui.component.richtext.span.ItemClickSpan;
 
+import java.util.ArrayList;
+import java.util.Map;
+
 class ANode extends RichTextNode {
 
   static class ANodeCreator implements RichTextNodeCreator<ANode> {
@@ -32,6 +36,12 @@ class ANode extends RichTextNode {
     public ANode createRichTextNode(Context context, String instanceId, String componentRef) {
       return new ANode(context, instanceId, componentRef);
     }
+    @Override
+    public ANode createRichTextNode(Context context,String instanceId,String componentRef,String ref,
+                                      Map<String,Object> styles, Map<String,Object> attrs){
+      return new ANode(context,instanceId,componentRef,ref,styles,attrs);
+    }
+
   }
 
   public static final String NODE_TYPE = "a";
@@ -40,6 +50,9 @@ class ANode extends RichTextNode {
   private ANode(Context context, String instanceId, String componentRef) {
     super(context, instanceId, componentRef);
   }
+  private ANode(Context context, String instanceId, String componentRef, String ref, Map<String,Object> styles, Map<String,Object> attrs) {
+    super(context, instanceId, componentRef, ref, styles, attrs);
+  }
 
   @Override
   public String toString() {
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/ImgNode.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/ImgNode.java
old mode 100644
new mode 100755
index 557cdd2..69f66ee
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/ImgNode.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/ImgNode.java
@@ -24,6 +24,7 @@ import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.support.annotation.NonNull;
+import android.support.v4.util.ArrayMap;
 import android.text.SpannableStringBuilder;
 import com.taobao.weex.WXSDKEngine;
 import com.taobao.weex.WXSDKInstance;
@@ -35,8 +36,11 @@ import com.taobao.weex.ui.component.richtext.span.ImgSpan;
 import com.taobao.weex.ui.component.richtext.span.ItemClickSpan;
 import com.taobao.weex.utils.ImgURIUtil;
 import com.taobao.weex.utils.WXUtils;
+
+import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 class ImgNode extends RichTextNode {
 
@@ -46,6 +50,11 @@ class ImgNode extends RichTextNode {
     public ImgNode createRichTextNode(Context context, String instanceId, String componentRef) {
       return new ImgNode(context, instanceId, componentRef);
     }
+    @Override
+    public ImgNode createRichTextNode(Context context,String instanceId,String componentRef,String ref,
+                                       Map<String,Object> styles, Map<String,Object> attrs){
+      return new ImgNode(context,instanceId,componentRef,ref,styles,attrs);
+    }
   }
 
   public static final String NODE_TYPE = "image";
@@ -53,10 +62,13 @@ class ImgNode extends RichTextNode {
   private ImgNode(Context context, String instanceId, String componentRef) {
     super(context, instanceId, componentRef);
   }
+  private ImgNode(Context context, String instanceId, String componentRef, String ref, Map<String,Object> styles, Map<String,Object> attrs) {
+    super(context, instanceId, componentRef, ref, styles, attrs);
+  }
 
   @Override
   public String toString() {
-    return " ";
+    return "\uFEFF";
   }
 
   @Override
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNode.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNode.java
old mode 100644
new mode 100755
index 3ff9622..036940b
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNode.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNode.java
@@ -29,6 +29,7 @@ import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
+import android.text.TextUtils;
 import android.text.style.AbsoluteSizeSpan;
 import android.text.style.BackgroundColorSpan;
 import android.text.style.ForegroundColorSpan;
@@ -40,6 +41,7 @@ import com.taobao.weex.WXSDKManager;
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.dom.WXCustomStyleSpan;
 import com.taobao.weex.dom.WXStyle;
+import com.taobao.weex.utils.WXLogUtils;
 import com.taobao.weex.utils.WXResourceUtils;
 import java.util.ArrayList;
 import java.util.LinkedList;
@@ -60,6 +62,7 @@ public abstract class RichTextNode {
     protected final Context mContext;
     protected final String mInstanceId;
     protected final String mComponentRef;
+    protected final String mRef;
     protected Map<String, Object> style;
     protected Map<String, Object> attr;
     protected List<RichTextNode> children;
@@ -68,6 +71,25 @@ public abstract class RichTextNode {
         mContext = context;
         mInstanceId = instanceId;
         mComponentRef = componentRef;
+        mRef = null;
+    }
+    protected RichTextNode(Context context, String instanceId, String componentRef, String ref, Map<String,Object> styles, Map<String,Object> attrs) {
+        mContext = context;
+        mInstanceId = instanceId;
+        mComponentRef = componentRef;
+        mRef = ref;
+        if(styles != null){
+            style = styles;
+        }
+        else {
+            style = new ArrayMap<>(0);
+        }
+        if (attrs != null) {
+            attr = attrs;
+        } else {
+            attr = new ArrayMap<>(0);
+        }
+        children = new LinkedList<>();
     }
 
     public static
@@ -102,6 +124,10 @@ public abstract class RichTextNode {
 
     protected abstract boolean isInternalNode();
 
+    public String getRef(){
+        return mRef;
+    }
+
     final void parse(@NonNull Context context, @NonNull String instanceId, @NonNull String componentRef, JSONObject jsonObject) {
         JSONObject jsonStyle, jsonAttr, child;
         JSONArray jsonChildren;
@@ -133,6 +159,37 @@ public abstract class RichTextNode {
             children = new ArrayList<>(0);
         }
     }
+    public void addChildNode(RichTextNode child){
+        if(children == null){
+            children = new LinkedList<>();
+        }
+        if(child != null && isInternalNode()){
+            children.add(child);
+        }
+    }
+    public void removeChildNode(String ref){
+        if(children != null && !children.isEmpty() && !TextUtils.isEmpty(ref)){
+            try {
+                for (RichTextNode child : children) {
+                    if (TextUtils.equals(child.mRef, ref)) {
+                        children.remove(child);
+                    }
+                }
+            }catch(Exception e){
+                WXLogUtils.getStackTrace(e);
+            }
+        }
+    }
+    public void updateStyles(Map<String,Object> styles){
+        if(styles != null && !styles.isEmpty()){
+            style.putAll(styles);
+        }
+    }
+    public void updateAttrs(Map<String,Object> attrs){
+        if(attr != null && !attrs.isEmpty()){
+            attr.putAll(attrs);
+        }
+    }
 
     protected void updateSpans(SpannableStringBuilder spannableStringBuilder, int level) {
         WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(mInstanceId);
@@ -173,6 +230,7 @@ public abstract class RichTextNode {
             MAX_LEVEL << Spanned.SPAN_PRIORITY_SHIFT;
     }
 
+
     private static
     @NonNull
     Spannable parse(@NonNull List<RichTextNode> list) {
@@ -183,7 +241,7 @@ public abstract class RichTextNode {
         return spannableStringBuilder;
     }
 
-    private Spannable toSpan(int level) {
+    public Spannable toSpan(int level) {
         SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
         spannableStringBuilder.append(toString());
         if (isInternalNode() && children != null) {
@@ -217,4 +275,17 @@ public abstract class RichTextNode {
             return null;
         }
     }
+    public RichTextNode findRichNode(String ref){
+        RichTextNode theNode;
+        if(mRef != null && TextUtils.equals(mRef,ref)){
+            return this;
+        }
+        if(children != null && !children.isEmpty()){
+            for (RichTextNode child:children) {
+                if((theNode = child.findRichNode(ref)) != null)
+                    return theNode;
+            }
+        }
+        return null;
+    }
 }
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java
old mode 100644
new mode 100755
index 26e3055..faaf6ca
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java
@@ -20,7 +20,10 @@ package com.taobao.weex.ui.component.richtext.node;
 
 import android.content.Context;
 
+import java.util.Map;
+
 public interface RichTextNodeCreator<T extends RichTextNode> {
 
   T createRichTextNode(Context context, String instanceId, String componentRef);
+  T createRichTextNode(Context context,String instanceId,String componentRef,String ref,Map<String,Object> styles, Map<String,Object> attrs);
 }
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeManager.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeManager.java
old mode 100644
new mode 100755
index c374487..d47cabc
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeManager.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeManager.java
@@ -59,4 +59,15 @@ public class RichTextNodeManager {
     }
     return instance;
   }
+  public static RichTextNode createRichTextNode(Context context,String instanceId,String componentRef,String ref,
+                                         String nodeType,Map<String,String> styles,Map<String,String> attrs){
+    RichTextNode instance;
+    try{
+      instance = registeredTextNodes.get(nodeType).createRichTextNode(context,instanceId,componentRef,ref,styles,attrs);
+    }catch (Exception e){
+      WXLogUtils.e("Richtext", WXLogUtils.getStackTrace(e));
+      instance = null;
+    }
+    return instance;
+  }
 }
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/SpanNode.java b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/SpanNode.java
old mode 100644
new mode 100755
index 4bfe0c9..dc48c1e
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/SpanNode.java
+++ b/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/SpanNode.java
@@ -19,12 +19,16 @@
 package com.taobao.weex.ui.component.richtext.node;
 
 import android.content.Context;
+import android.support.v4.util.ArrayMap;
 import android.text.SpannableStringBuilder;
 
 import com.taobao.weex.common.Constants;
 import com.taobao.weex.dom.TextDecorationSpan;
 import com.taobao.weex.dom.WXStyle;
 
+import java.util.ArrayList;
+import java.util.Map;
+
 class SpanNode extends RichTextNode {
 
   static class SpanNodeCreator implements RichTextNodeCreator<SpanNode> {
@@ -33,6 +37,12 @@ class SpanNode extends RichTextNode {
     public SpanNode createRichTextNode(Context context, String instanceId, String componentRef) {
       return new SpanNode(context, instanceId, componentRef);
     }
+
+    @Override
+    public SpanNode createRichTextNode(Context context,String instanceId,String componentRef,String ref,
+                                       Map<String,Object> styles, Map<String,Object> attrs){
+      return new SpanNode(context,instanceId,componentRef,ref,styles,attrs);
+    }
   }
 
   public static final String NODE_TYPE = "span";
@@ -40,6 +50,9 @@ class SpanNode extends RichTextNode {
   private SpanNode(Context context, String instanceId, String componentRef) {
     super(context, instanceId, componentRef);
   }
+  private SpanNode(Context context, String instanceId, String componentRef, String ref, Map<String,Object> styles,Map<String,Object> attrs) {
+    super(context, instanceId, componentRef, ref, styles, attrs);
+  }
 
   @Override
   public String toString() {
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index 0f0ae47..ef98925 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -551,6 +551,22 @@
 		BA5F00F21FC5AFFE00F76B5C /* WXLocaleModule.m in Sources */ = {isa = PBXBuildFile; fileRef = BA5F00F01FC5AFFE00F76B5C /* WXLocaleModule.m */; };
 		BA5F00F31FC6834900F76B5C /* WXLocaleModule.h in Headers */ = {isa = PBXBuildFile; fileRef = BA5F00EF1FC5AFFE00F76B5C /* WXLocaleModule.h */; };
 		BA5F00F41FC6834C00F76B5C /* WXLocaleModule.m in Sources */ = {isa = PBXBuildFile; fileRef = BA5F00F01FC5AFFE00F76B5C /* WXLocaleModule.m */; };
+		BD88C13722F02101004467AA /* render_action_add_child_to_richtext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C13522F02101004467AA /* render_action_add_child_to_richtext.cpp */; };
+		BD88C13822F02101004467AA /* render_action_add_child_to_richtext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C13522F02101004467AA /* render_action_add_child_to_richtext.cpp */; };
+		BD88C13922F02101004467AA /* render_action_add_child_to_richtext.h in Headers */ = {isa = PBXBuildFile; fileRef = BD88C13622F02101004467AA /* render_action_add_child_to_richtext.h */; };
+		BD88C13A22F02101004467AA /* render_action_add_child_to_richtext.h in Headers */ = {isa = PBXBuildFile; fileRef = BD88C13622F02101004467AA /* render_action_add_child_to_richtext.h */; };
+		BD88C13D22F02111004467AA /* render_action_remove_child_from_richtext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C13B22F02111004467AA /* render_action_remove_child_from_richtext.cpp */; };
+		BD88C13E22F02111004467AA /* render_action_remove_child_from_richtext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C13B22F02111004467AA /* render_action_remove_child_from_richtext.cpp */; };
+		BD88C13F22F02111004467AA /* render_action_remove_child_from_richtext.h in Headers */ = {isa = PBXBuildFile; fileRef = BD88C13C22F02111004467AA /* render_action_remove_child_from_richtext.h */; };
+		BD88C14022F02111004467AA /* render_action_remove_child_from_richtext.h in Headers */ = {isa = PBXBuildFile; fileRef = BD88C13C22F02111004467AA /* render_action_remove_child_from_richtext.h */; };
+		BD88C14322F02120004467AA /* render_action_update_richtext_child_attr.h in Headers */ = {isa = PBXBuildFile; fileRef = BD88C14122F02120004467AA /* render_action_update_richtext_child_attr.h */; };
+		BD88C14422F02120004467AA /* render_action_update_richtext_child_attr.h in Headers */ = {isa = PBXBuildFile; fileRef = BD88C14122F02120004467AA /* render_action_update_richtext_child_attr.h */; };
+		BD88C14522F02120004467AA /* render_action_update_richtext_child_attr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C14222F02120004467AA /* render_action_update_richtext_child_attr.cpp */; };
+		BD88C14622F02120004467AA /* render_action_update_richtext_child_attr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C14222F02120004467AA /* render_action_update_richtext_child_attr.cpp */; };
+		BD88C14922F02128004467AA /* render_action_update_richtext_child_style.h in Headers */ = {isa = PBXBuildFile; fileRef = BD88C14722F02128004467AA /* render_action_update_richtext_child_style.h */; };
+		BD88C14A22F02128004467AA /* render_action_update_richtext_child_style.h in Headers */ = {isa = PBXBuildFile; fileRef = BD88C14722F02128004467AA /* render_action_update_richtext_child_style.h */; };
+		BD88C14B22F02128004467AA /* render_action_update_richtext_child_style.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C14822F02128004467AA /* render_action_update_richtext_child_style.cpp */; };
+		BD88C14C22F02128004467AA /* render_action_update_richtext_child_style.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD88C14822F02128004467AA /* render_action_update_richtext_child_style.cpp */; };
 		BD9205F82236518700EDF93D /* WXDataRenderHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = BD9205F72236518700EDF93D /* WXDataRenderHandler.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		BD9205FB223651D900EDF93D /* eagle_bridge.h in Headers */ = {isa = PBXBuildFile; fileRef = BD9205F9223651D800EDF93D /* eagle_bridge.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		BD9205FC223651D900EDF93D /* eagle_bridge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BD9205FA223651D800EDF93D /* eagle_bridge.cpp */; };
@@ -1279,6 +1295,14 @@
 		B8F3323B2141A4C500701BA0 /* string_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string_util.h; sourceTree = "<group>"; };
 		BA5F00EF1FC5AFFE00F76B5C /* WXLocaleModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WXLocaleModule.h; sourceTree = "<group>"; };
 		BA5F00F01FC5AFFE00F76B5C /* WXLocaleModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = WXLocaleModule.m; sourceTree = "<group>"; };
+		BD88C13522F02101004467AA /* render_action_add_child_to_richtext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = render_action_add_child_to_richtext.cpp; sourceTree = "<group>"; };
+		BD88C13622F02101004467AA /* render_action_add_child_to_richtext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = render_action_add_child_to_richtext.h; sourceTree = "<group>"; };
+		BD88C13B22F02111004467AA /* render_action_remove_child_from_richtext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = render_action_remove_child_from_richtext.cpp; sourceTree = "<group>"; };
+		BD88C13C22F02111004467AA /* render_action_remove_child_from_richtext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = render_action_remove_child_from_richtext.h; sourceTree = "<group>"; };
+		BD88C14122F02120004467AA /* render_action_update_richtext_child_attr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = render_action_update_richtext_child_attr.h; sourceTree = "<group>"; };
+		BD88C14222F02120004467AA /* render_action_update_richtext_child_attr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = render_action_update_richtext_child_attr.cpp; sourceTree = "<group>"; };
+		BD88C14722F02128004467AA /* render_action_update_richtext_child_style.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = render_action_update_richtext_child_style.h; sourceTree = "<group>"; };
+		BD88C14822F02128004467AA /* render_action_update_richtext_child_style.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = render_action_update_richtext_child_style.cpp; sourceTree = "<group>"; };
 		BD9205F72236518700EDF93D /* WXDataRenderHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXDataRenderHandler.h; sourceTree = "<group>"; };
 		BD9205F9223651D800EDF93D /* eagle_bridge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = eagle_bridge.h; sourceTree = "<group>"; };
 		BD9205FA223651D800EDF93D /* eagle_bridge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = eagle_bridge.cpp; sourceTree = "<group>"; };
@@ -2172,6 +2196,14 @@
 		B8D66B3D2125572F003960BD /* action */ = {
 			isa = PBXGroup;
 			children = (
+				BD88C14822F02128004467AA /* render_action_update_richtext_child_style.cpp */,
+				BD88C14722F02128004467AA /* render_action_update_richtext_child_style.h */,
+				BD88C14222F02120004467AA /* render_action_update_richtext_child_attr.cpp */,
+				BD88C14122F02120004467AA /* render_action_update_richtext_child_attr.h */,
+				BD88C13B22F02111004467AA /* render_action_remove_child_from_richtext.cpp */,
+				BD88C13C22F02111004467AA /* render_action_remove_child_from_richtext.h */,
+				BD88C13522F02101004467AA /* render_action_add_child_to_richtext.cpp */,
+				BD88C13622F02101004467AA /* render_action_add_child_to_richtext.h */,
 				B8394F3621468AF100CA1EFF /* render_action_trigger_vsync.cpp */,
 				B8394F3521468AF100CA1EFF /* render_action_trigger_vsync.h */,
 				B8D66B3E2125572F003960BD /* render_action_render_success.h */,
@@ -2378,6 +2410,7 @@
 				DCF087611DCAE161005CD6EB /* WXInvocationConfig.h in Headers */,
 				741081231CED6756001BC6E5 /* WXComponentFactory.h in Headers */,
 				45E0B4C121CB7B82005D1B3B /* WXConvertUtility.h in Headers */,
+				BD88C13F22F02111004467AA /* render_action_remove_child_from_richtext.h in Headers */,
 				BD9205FB223651D900EDF93D /* eagle_bridge.h in Headers */,
 				BD9205F82236518700EDF93D /* WXDataRenderHandler.h in Headers */,
 				7715EB6221A69DD9001F1108 /* WXRichText.h in Headers */,
@@ -2390,6 +2423,7 @@
 				B8D66C7521255730003960BD /* render_object.h in Headers */,
 				775BEE711C1BD977008D1629 /* WXModuleProtocol.h in Headers */,
 				7469869F1C4E2C000054A57E /* NSArray+Weex.h in Headers */,
+				BD88C14922F02128004467AA /* render_action_update_richtext_child_style.h in Headers */,
 				B8D66C4121255730003960BD /* render_action_add_event.h in Headers */,
 				74CC7A201C2BF9DC00829368 /* WXListComponent.h in Headers */,
 				17036A5320FDE7490029AE3D /* WXApmProtocol.h in Headers */,
@@ -2521,11 +2555,13 @@
 				742AD7311DF98C45007DC46C /* WXResourceRequestHandlerDefaultImpl.h in Headers */,
 				C4F0127D1E1502A6003378D0 /* WXWebSocketHandler.h in Headers */,
 				B8D66C9D21255730003960BD /* json11.hpp in Headers */,
+				BD88C13922F02101004467AA /* render_action_add_child_to_richtext.h in Headers */,
 				DC03ADBA1D508719003F76E7 /* WXTextAreaComponent.h in Headers */,
 				B8D66C5721255730003960BD /* render_action_layout.h in Headers */,
 				2AC750241C7565690041D390 /* WXIndicatorComponent.h in Headers */,
 				DCAB35FE1D658EB700C0EA70 /* WXRuleManager.h in Headers */,
 				748B25181C44A6F9005D491E /* WXSDKInstance_private.h in Headers */,
+				BD88C14322F02120004467AA /* render_action_update_richtext_child_attr.h in Headers */,
 				74862F7D1E03A0F300B7A041 /* WXModuleMethod.h in Headers */,
 				742AD7331DF98C45007DC46C /* WXResourceResponse.h in Headers */,
 				77E65A0D1C155E99008B8775 /* WXDivComponent.h in Headers */,
@@ -2620,6 +2656,7 @@
 				DCA445F41EFA5A2800D0CFA8 /* WXNavigationDefaultImpl.h in Headers */,
 				DCA445E21EFA59D700D0CFA8 /* WXRefreshComponent.h in Headers */,
 				B85ED3032126715100EBEC11 /* WXRecyclerComponent.h in Headers */,
+				BD88C14022F02111004467AA /* render_action_remove_child_from_richtext.h in Headers */,
 				7715EB6321A69DD9001F1108 /* WXRichText.h in Headers */,
 				B8D66C1C21255730003960BD /* style.h in Headers */,
 				B8D66C2421255730003960BD /* layout.h in Headers */,
@@ -2632,6 +2669,7 @@
 				B8D66C3621255730003960BD /* render_action_move_element.h in Headers */,
 				DCA445A31EFA570800D0CFA8 /* WXSDKManager.h in Headers */,
 				DCA445BE1EFA57BB00D0CFA8 /* WXComponentManager.h in Headers */,
+				BD88C14A22F02128004467AA /* render_action_update_richtext_child_style.h in Headers */,
 				7704894922AA358500E7606F /* WXConsoleLogModule.h in Headers */,
 				DCA4459E1EFA56E500D0CFA8 /* WXUtility.h in Headers */,
 				77A3D66F222F9F5B0078A6F5 /* WeexApiValue.h in Headers */,
@@ -2763,11 +2801,13 @@
 				B8D66C3421255730003960BD /* render_action_update_attr.h in Headers */,
 				DCA445F11EFA5A2000D0CFA8 /* WXCanvasComponent.h in Headers */,
 				B8D66CB021255730003960BD /* wson_parser.h in Headers */,
+				BD88C13A22F02101004467AA /* render_action_add_child_to_richtext.h in Headers */,
 				DCA445D51EFA598200D0CFA8 /* WXComponent+PseudoClassManagement.h in Headers */,
 				DCA4460E1EFA5A7E00D0CFA8 /* WXLength.h in Headers */,
 				DCA445FA1EFA5A3A00D0CFA8 /* WXNavigatorModule.h in Headers */,
 				841CD1061F974DFA0081196D /* WXExceptionUtils.h in Headers */,
 				DCA446081EFA5A6A00D0CFA8 /* NSArray+Weex.h in Headers */,
+				BD88C14422F02120004467AA /* render_action_update_richtext_child_attr.h in Headers */,
 				B8D66CAA21255730003960BD /* wson_util.h in Headers */,
 				74B81AE51F73C3E900D3A61D /* WXRecycleListDataManager.h in Headers */,
 				B8D66C3E21255730003960BD /* render_action_createfinish.h in Headers */,
@@ -3135,6 +3175,7 @@
 				D3FC0DF81C508B2A002B9E31 /* WXTimerModule.m in Sources */,
 				594C28921CF9E61A009793A4 /* WXAnimationModule.m in Sources */,
 				B8D66C6F21255730003960BD /* render_object.cpp in Sources */,
+				BD88C13D22F02111004467AA /* render_action_remove_child_from_richtext.cpp in Sources */,
 				59A5961D1CB630F10012CD52 /* WXComponent+Navigation.m in Sources */,
 				77D161631C02ED790010B15B /* WXLog.m in Sources */,
 				17C74F0D2072145100AB4CAB /* WXAnalyzerCenter.m in Sources */,
@@ -3157,6 +3198,7 @@
 				2AC750251C7565690041D390 /* WXIndicatorComponent.m in Sources */,
 				591DD3311D23AD5800BE8709 /* WXErrorView.m in Sources */,
 				7715EB6421A69DD9001F1108 /* WXRichText.mm in Sources */,
+				BD88C14B22F02128004467AA /* render_action_update_richtext_child_style.cpp in Sources */,
 				B8D66C1121255730003960BD /* core_side_in_script.cpp in Sources */,
 				B8D66C032125572F003960BD /* css_value_getter.cpp in Sources */,
 				B8394F3921468AF100CA1EFF /* render_action_trigger_vsync.cpp in Sources */,
@@ -3244,6 +3286,7 @@
 				745ED2DB1C5F2C7E002DB5A8 /* WXView.m in Sources */,
 				DC03ADB91D508719003F76E7 /* WXTextAreaComponent.mm in Sources */,
 				59A596231CB6311F0012CD52 /* WXNavigatorModule.m in Sources */,
+				BD88C13722F02101004467AA /* render_action_add_child_to_richtext.cpp in Sources */,
 				B8D66CA721255730003960BD /* wson.c in Sources */,
 				37B51EE51E97804D0040A743 /* WXCycleSliderComponent.mm in Sources */,
 				77D161211C02DDB40010B15B /* WXSDKEngine.m in Sources */,
@@ -3263,6 +3306,7 @@
 				742AD72F1DF98C45007DC46C /* WXResourceRequest.m in Sources */,
 				7461F8931CFB373100F62D44 /* WXLayer.m in Sources */,
 				74D205211E091B8000128F44 /* WXCallJSMethod.m in Sources */,
+				BD88C14522F02120004467AA /* render_action_update_richtext_child_attr.cpp in Sources */,
 				C41E1A981DC1FD15009C7F90 /* WXDatePickerManager.m in Sources */,
 				77D1614C1C02E3790010B15B /* WXConvert.m in Sources */,
 				749DC27C1D40827B009E1C91 /* WXMonitor.m in Sources */,
@@ -3321,6 +3365,7 @@
 				DCA4453F1EFA55B300D0CFA8 /* WXRootViewController.m in Sources */,
 				DCA445401EFA55B300D0CFA8 /* WXEditComponent.mm in Sources */,
 				B8D66C7421255730003960BD /* render_list.cpp in Sources */,
+				BD88C13E22F02111004467AA /* render_action_remove_child_from_richtext.cpp in Sources */,
 				773CB1DF227F0C92005C758A /* JsonPage.cpp in Sources */,
 				DCA445411EFA55B300D0CFA8 /* WXMultiColumnLayout.m in Sources */,
 				B8D66C6621255730003960BD /* render_mask.cpp in Sources */,
@@ -3343,6 +3388,7 @@
 				7715EB6521A69DD9001F1108 /* WXRichText.mm in Sources */,
 				DCA4454D1EFA55B300D0CFA8 /* WXDivComponent.m in Sources */,
 				DCA4454E1EFA55B300D0CFA8 /* WXImageComponent.m in Sources */,
+				BD88C14C22F02128004467AA /* render_action_update_richtext_child_style.cpp in Sources */,
 				DCA4454F1EFA55B300D0CFA8 /* WXTextComponent.mm in Sources */,
 				DCA445501EFA55B300D0CFA8 /* WXScrollerComponent.mm in Sources */,
 				DCA445511EFA55B300D0CFA8 /* WXCycleSliderComponent.mm in Sources */,
@@ -3430,6 +3476,7 @@
 				DCA445821EFA55B300D0CFA8 /* WXSDKEngine.m in Sources */,
 				DCA445831EFA55B300D0CFA8 /* WXBridgeMethod.m in Sources */,
 				DCA445841EFA55B300D0CFA8 /* WXModuleMethod.m in Sources */,
+				BD88C13822F02101004467AA /* render_action_add_child_to_richtext.cpp in Sources */,
 				B8D66CA821255730003960BD /* wson.c in Sources */,
 				DCA445851EFA55B300D0CFA8 /* WXComponentMethod.m in Sources */,
 				DCA445861EFA55B300D0CFA8 /* WXCallJSMethod.m in Sources */,
@@ -3449,6 +3496,7 @@
 				DCA445931EFA55B300D0CFA8 /* WXComponentManager.mm in Sources */,
 				DCA445941EFA55B300D0CFA8 /* WXComponentFactory.m in Sources */,
 				DCA445951EFA55B300D0CFA8 /* WXRuleManager.m in Sources */,
+				BD88C14622F02120004467AA /* render_action_update_richtext_child_attr.cpp in Sources */,
 				DCA445961EFA55B300D0CFA8 /* WXMonitor.m in Sources */,
 				DCA445971EFA55B300D0CFA8 /* WXComponent+Navigation.m in Sources */,
 				DCA445981EFA55B300D0CFA8 /* WXSDKInstance.m in Sources */,
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
index cdd4476..94efe17 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.h
@@ -90,6 +90,11 @@ namespace WeexCore
                            const WXCoreBorderWidth &borders,
                            bool willLayout= true) override;
         
+        int AddChildToRichtext(const char* pageId, const char *nodeType, const char* ref,
+                                 const char* parentRef, const char* richtextRef,
+                                 std::map<std::string, std::string> *styles,
+                                 std::map<std::string, std::string> *attributes) override;
+
         int Layout(const char* pageId, const char* ref,
                        float top, float bottom, float left, float right,
                        float height, float width, bool isRTL, int index) override;
@@ -100,15 +105,24 @@ namespace WeexCore
                             std::vector<std::pair<std::string, std::string>> *padding,
                             std::vector<std::pair<std::string, std::string>> *border) override;
         
+        int UpdateRichtextStyle(const char* pageId, const char* ref,
+                                         std::vector<std::pair<std::string, std::string>> *style,
+                                         const char* parent_ref, const char* richtext_ref) override;
+
         int UpdateAttr(const char* pageId, const char* ref,
                            std::vector<std::pair<std::string, std::string>> *attrs) override;
         
+        int UpdateRichtextChildAttr(const char* pageId, const char* ref,
+                       std::vector<std::pair<std::string, std::string>> *attrs,  const char* parent_ref, const char* richtext_ref) override;
+
         int CreateFinish(const char* pageId) override;
         
         int RenderSuccess(const char* pageId) override;
         
         int RemoveElement(const char* pageId, const char* ref) override;
         
+        int RemoveChildFromRichtext(const char* pageId, const char* ref, const char* parent_ref, const char* richtext_ref) override;
+
         int MoveElement(const char* pageId, const char* ref, const char* parentRef, int index) override;
         
         int AppendTreeCreateFinish(const char* pageId, const char* ref) override;
diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
index 5b9d9e3..b7bddd1 100644
--- a/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
+++ b/ios/sdk/WeexSDK/Sources/Bridge/WXCoreBridge.mm
@@ -35,6 +35,7 @@
 #import "WXExceptionUtils.h"
 #import "WXModuleFactory.h"
 #import "WXComponentFactory.h"
+#import "WXRichText.h"
 #include "base/core_constants.h"
 #include "base/time_utils.h"
 #include "core/manager/weex_core_manager.h"
@@ -624,6 +625,34 @@ break; \
         return 0;
     }
     
+    int IOSSide::AddChildToRichtext(const char* pageId, const char *nodeType, const char* ref,
+                            const char* parentRef, const char* richtextRef,
+                            std::map<std::string, std::string> *styles,
+                            std::map<std::string, std::string> *attributes)
+    {
+        RenderPageBase *page = RenderManager::GetInstance()->GetPage(pageId);
+        if (page == nullptr) {
+            return -1;
+        }
+        NSString* ns_richtextRef = NSSTRING(richtextRef);
+        NSString* ns_instanceId = NSSTRING(pageId);
+        NSString* ns_nodeType = NSSTRING(nodeType);
+        NSString* ns_ref = NSSTRING(ref);
+        NSString* ns_parentRef = NSSTRING(parentRef);
+        NSMutableDictionary* ns_styles = NSDICTIONARY(styles);
+        NSDictionary* ns_attributes = NSDICTIONARY(attributes);
+
+        WXSDKInstance* sdkInstance = [WXSDKManager instanceForID:ns_instanceId];
+        WXComponentManager* manager = sdkInstance.componentManager;
+        if (!manager.isValid) {
+            return -1;
+        }
+
+        WXRichText* richtext = (WXRichText*)[manager componentForRef:ns_richtextRef];
+        [richtext addChildNode:ns_nodeType ref:ns_ref styles:ns_styles attributes:ns_attributes toSuperNodeRef:ns_parentRef];
+        return 0;
+    }
+
     int IOSSide::Layout(const char* pageId, const char* ref,
                        float top, float bottom, float left, float right,
                        float height, float width, bool isRTL, int index)
@@ -682,6 +711,35 @@ break; \
         page->CallBridgeTime(getCurrentTime() - startTime);
     }
     
+    int IOSSide::UpdateRichtextStyle(const char* pageId, const char* ref,
+                             std::vector<std::pair<std::string, std::string>> *style,
+                             const char* parent_ref, const char* richtext_ref)
+    {
+        RenderPageBase *page = RenderManager::GetInstance()->GetPage(pageId);
+        if (page == nullptr) {
+            return -1;
+        }
+
+        NSString* ns_instanceId = NSSTRING(pageId);
+        NSString* ns_ref = NSSTRING(ref);
+        NSString* ns_richtextRef = NSSTRING(richtext_ref);
+        NSString* ns_parentRef = NSSTRING(parent_ref);
+        NSMutableDictionary* ns_style = NSDICTIONARY(style);
+
+        WXSDKInstance* sdkInstance = [WXSDKManager instanceForID:ns_instanceId];
+        if (!sdkInstance) {
+            return -1;
+        }
+        WXComponentManager* manager = sdkInstance.componentManager;
+        if (!manager.isValid) {
+            return -1;
+        }
+
+        WXRichText* richtext = (WXRichText*)[manager componentForRef:ns_richtextRef];
+        [richtext updateChildNodeStyles:ns_style ref:ns_ref parentRef:ns_parentRef];
+        return 0;
+    }
+
     int IOSSide::UpdateStyle(const char* pageId, const char* ref,
                             std::vector<std::pair<std::string, std::string>> *style,
                             std::vector<std::pair<std::string, std::string>> *margin,
@@ -753,6 +811,39 @@ break; \
         page->CallBridgeTime(getCurrentTime() - startTime);
         return 0;
     }
+
+    int IOSSide::UpdateRichtextChildAttr(const char* pageId, const char* ref,
+                            std::vector<std::pair<std::string, std::string>> *attrs, const char* parent_ref, const char* richtext_ref)
+    {
+        RenderPageBase *page = RenderManager::GetInstance()->GetPage(pageId);
+        if (page == nullptr) {
+            return -1;
+        }
+        if (attrs == nullptr) {
+            return 0;
+        }
+        if (attrs->size() == 0) {
+            return 0;
+        }
+
+        NSString* ns_instanceId = NSSTRING(pageId);
+        NSString* ns_ref = NSSTRING(ref);
+        NSString* ns_parentRef = NSSTRING(parent_ref);
+        NSString* ns_richtextRef = NSSTRING(richtext_ref);
+        NSDictionary* ns_attributes = NSDICTIONARY(attrs);
+        WXSDKInstance* sdkInstance = [WXSDKManager instanceForID:ns_instanceId];
+        if (!sdkInstance) {
+            return -1;
+        }
+        WXComponentManager* manager = sdkInstance.componentManager;
+        if (!manager.isValid) {
+            return -1;
+        }
+
+        WXRichText* richtext = (WXRichText*)[manager componentForRef:ns_richtextRef];
+        [richtext updateChildNodeAttributes:ns_attributes ref:ns_ref parentRef:ns_parentRef];
+        return 0;
+    }
         
     int IOSSide::CreateFinish(const char* pageId)
     {
@@ -803,7 +894,28 @@ break; \
         }
         return 0;
     }
+
+    int IOSSide::RemoveChildFromRichtext(const char* pageId, const char* ref, const char* parent_ref, const char* richtext_ref) {
+        RenderPageBase *page = RenderManager::GetInstance()->GetPage(pageId);
+        if (page == nullptr) {
+            return -1;
+        }
         
+        NSString* ns_instanceId = NSSTRING(pageId);
+        NSString* ns_richtextRef = NSSTRING(richtext_ref);
+        NSString* ns_ref = NSSTRING(ref);
+        NSString* ns_parentRef = NSSTRING(parent_ref);
+
+        WXSDKInstance* sdkInstance = [WXSDKManager instanceForID:ns_instanceId];
+        WXComponentManager* manager = sdkInstance.componentManager;
+        if (!manager.isValid) {
+            return -1;
+        }
+
+        WXRichText* richtext = (WXRichText*)[manager componentForRef:ns_richtextRef];
+        [richtext removeChildNode:ns_ref superNodeRef:ns_parentRef];
+        return 0;
+    }
     int IOSSide::RemoveElement(const char* pageId, const char* ref)
     {
         RenderPageBase *page = RenderManager::GetInstance()->GetPage(pageId);
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXRichText.h b/ios/sdk/WeexSDK/Sources/Component/WXRichText.h
index b0c768c..7beb8a5 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXRichText.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXRichText.h
@@ -20,5 +20,8 @@
 #import "WXComponent.h"
 
 @interface WXRichText : WXComponent<UITextViewDelegate>
-
+- (void)addChildNode:(NSString *)type ref:(NSString*)ref styles:(NSDictionary*)styles attributes:(NSDictionary*)attributes  toSuperNodeRef:(NSString *)superNodeRef;
+- (void)updateChildNodeAttributes:(NSDictionary *)attributes ref:(NSString*)ref parentRef:(NSString*)parentRef;
+- (void)updateChildNodeStyles:(NSDictionary *)styles ref:(NSString*)ref parentRef:(NSString*)parentRef;
+- (void)removeChildNode:(NSString*)ref superNodeRef:(NSString *)superNodeRef;
 @end
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXRichText.mm b/ios/sdk/WeexSDK/Sources/Component/WXRichText.mm
index aedafb3..8ffeaf3 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXRichText.mm
+++ b/ios/sdk/WeexSDK/Sources/Component/WXRichText.mm
@@ -32,6 +32,7 @@
 @interface WXRichNode : NSObject
 
 @property (nonatomic, strong) NSString  *type;
+@property (nonatomic, strong) NSString  *ref;
 @property (nonatomic, strong) NSString  *text;
 @property (nonatomic, strong) UIColor   *color;
 @property (nonatomic, strong) UIColor   *backgroundColor;
@@ -46,10 +47,18 @@
 @property (nonatomic, strong) NSURL *href;
 @property (nonatomic, strong) NSURL *src;
 @property (nonatomic, assign) NSRange range;
+@property (nonatomic, strong) NSMutableArray *childNodes;
 
 @end
 
 @implementation WXRichNode
+- (instancetype)init
+{
+    if (self = [super init]) {
+        _childNodes = [[NSMutableArray alloc] init];
+    }
+    return self;
+}
 
 @end
 
@@ -153,6 +162,9 @@ do {\
 - (void)fillAttributes:(NSDictionary *)attributes
 {
     id value = attributes[@"value"];
+    if (!value) {
+        return;
+    }
     if ([value isKindOfClass:[NSString class]]) {
         value = [WXUtility objectFromJSON:value];
     }
@@ -162,7 +174,6 @@ do {\
         WXRichNode *rootNode = [[WXRichNode alloc]init];
         [_richNodes addObject:rootNode];
         
-        //记录richtext根节点styles,仅用于子节点的样式继承
         rootNode.type = @"root";
         if (_styles) {
             [self fillCSSStyles:_styles toNode:rootNode superNode:nil];
@@ -252,6 +263,79 @@ do {\
     }
 }
 
+- (WXRichNode*)findRichNode:(NSString*)ref {
+    NSMutableArray *array = [NSMutableArray arrayWithArray:_richNodes];
+    for (WXRichNode* node in array) {
+        if ([node.ref isEqualToString:ref]) {
+            return node;
+        }
+    }
+    return nil;
+}
+
+- (NSInteger)indexOfRichNode:(WXRichNode*)node {
+    NSInteger index = -1;
+    NSMutableArray *array = [NSMutableArray arrayWithArray:_richNodes];
+    for (WXRichNode* item in array) {
+        if ([item.ref isEqualToString:node.ref]) {
+            return index+1;
+        }
+        index++;
+    }
+    return index;
+}
+
+- (void)removeChildNode:(NSString*)ref superNodeRef:(NSString *)superNodeRef {
+    WXRichNode* node = [self findRichNode:ref];
+    WXRichNode* superNode = [self findRichNode:@"_root"];
+    if (superNodeRef.length > 0) {
+        superNode = [self findRichNode:superNodeRef];
+    }
+    if (superNode) {
+         [superNode.childNodes removeObject:node];
+    }
+    [_richNodes removeObject:node];
+    [self setNeedsLayout];
+    [self innerLayout];
+}
+
+- (void)addChildNode:(NSString *)type ref:(NSString*)ref styles:(NSDictionary*)styles attributes:(NSDictionary*)attributes  toSuperNodeRef:(NSString *)superNodeRef {
+    if ([_richNodes count] == 0) {
+        WXRichNode *rootNode = [[WXRichNode alloc]init];
+        [_richNodes addObject:rootNode];
+        rootNode.type = @"root";
+        rootNode.ref = @"_root";
+        if (_styles) {
+            [self fillCSSStyles:_styles toNode:rootNode superNode:nil];
+        }
+        _backgroundColor = rootNode.backgroundColor?:[UIColor whiteColor];
+    }
+
+    WXRichNode* superNode = [self findRichNode:@"_root"];
+    if (superNodeRef.length > 0) {
+        superNode = [self findRichNode:superNodeRef];
+    }
+
+    WXRichNode *node = [[WXRichNode alloc]init];
+    node.ref = ref;
+    NSInteger index = [self indexOfRichNode:superNode];
+    if (index < 0) {
+        return;
+    }
+    if (index == 0) {
+        [_richNodes addObject:node];
+    } else {
+        [_richNodes insertObject:node atIndex:(index + superNode.childNodes.count + 1)];
+    }
+    [superNode.childNodes addObject:node];
+    node.type = type;
+
+    [self fillCSSStyles:styles toNode:node superNode:superNode];
+    [self fillAttributes:attributes toNode:node superNode:superNode];
+    [self setNeedsLayout];
+    [self innerLayout];
+}
+
 #pragma mark - Subclass
 
 - (UIView *)loadView
@@ -457,6 +541,22 @@ do {\
     });
 }
 
+- (void)updateChildNodeStyles:(NSDictionary *)styles ref:(NSString*)ref parentRef:(NSString*)parentRef {
+    WXPerformBlockOnComponentThread(^{
+        WXRichNode* node =  [self findRichNode:ref];
+        if (node) {
+            WXRichNode* superNode = [self findRichNode:@"_root"];
+            if (parentRef.length > 0) {
+                superNode = [self findRichNode:parentRef];
+            }
+            if (superNode) {
+                [self fillCSSStyles:styles toNode:node superNode:superNode];
+                [self syncTextStorageForView];
+            }
+        }
+    });
+}
+
 - (void)updateAttributes:(NSDictionary *)attributes {
     WXPerformBlockOnComponentThread(^{
         _attributes = [NSMutableDictionary dictionaryWithDictionary:attributes];
@@ -464,6 +564,22 @@ do {\
     });
 }
 
+- (void)updateChildNodeAttributes:(NSDictionary *)attributes ref:(NSString*)ref parentRef:(NSString*)parentRef {
+    WXPerformBlockOnComponentThread(^{
+        WXRichNode* node =  [self findRichNode:ref];
+        if (node) {
+            WXRichNode* superNode = [self findRichNode:@"_root"];
+            if (parentRef.length > 0) {
+                superNode = [self findRichNode:parentRef];
+            }
+            if (superNode) {
+                [self fillAttributes:attributes toNode:node superNode:superNode];
+                [self syncTextStorageForView];
+            }
+        }
+    });
+}
+
 - (void)syncTextStorageForView {
     pthread_mutex_lock(&(_attributedStringMutex));
     [self fillAttributes:_attributes];
diff --git a/weex_core/Source/CMakeLists.txt b/weex_core/Source/CMakeLists.txt
old mode 100644
new mode 100755
index ba42a89..5016d66
--- a/weex_core/Source/CMakeLists.txt
+++ b/weex_core/Source/CMakeLists.txt
@@ -81,11 +81,12 @@ set(COMMON_SRCS
   ./core/render/action/render_action_update_style.cpp
   ./core/render/action/render_action_render_success.cpp
   ./core/render/action/render_action_trigger_vsync.cpp
-
   ./core/json/JsonRenderManager.cpp
   ./core/json/JsonPage.cpp
-
-
+  ./core/render/action/render_action_add_child_to_richtext.cpp
+  ./core/render/action/render_action_remove_child_from_richtext.cpp
+  ./core/render/action/render_action_update_richtext_child_style.cpp
+  ./core/render/action/render_action_update_richtext_child_attr.cpp
   ./core/layout/layout.cpp
   ./core/layout/style.cpp
 
diff --git a/weex_core/Source/android/bridge/platform/android_side.cpp b/weex_core/Source/android/bridge/platform/android_side.cpp
old mode 100644
new mode 100755
index 5f3dbe4..17057a7
--- a/weex_core/Source/android/bridge/platform/android_side.cpp
+++ b/weex_core/Source/android/bridge/platform/android_side.cpp
@@ -120,6 +120,56 @@ int AndroidSide::CallNative(const char *page_id, const char *task,
   }
   return flag;
 }
+int AndroidSide::AddChildToRichtext(const char *pageId, const char *nodeType, const char *ref, const char *parentRef,
+                                    const char *richtextRef, std::map<std::string, std::string> *styles,
+                                    std::map<std::string, std::string> *attributes) {
+    JNIEnv *env = base::android::AttachCurrentThread();
+    if (env == nullptr)
+        return -1;
+    int flag = wx_bridge_->AddChildToRichtext(env, pageId, nodeType, ref, parentRef, richtextRef, styles ,attributes);
+    if (flag == -1) {
+        LOGE("instance destroy JFM must stop AddChildToRichtext");
+    }
+    return flag;
+}
+int AndroidSide::RemoveChildFromRichtext(const char *pageId, const char *ref, const char *parent_ref,
+                                         const char *richtext_ref) {
+    JNIEnv *env = base::android::AttachCurrentThread();
+    if (env == nullptr)
+        return -1;
+
+    int flag = wx_bridge_->RemoveChildFromRichtext(env, pageId, ref, parent_ref, richtext_ref);
+    if (flag == -1) {
+        LOGE("instance destroy JFM must stop RemoveChildFromRichtext");
+    }
+    return flag;
+}
+int AndroidSide::UpdateRichtextStyle(const char *pageId, const char *ref,
+                                     std::vector<std::pair<std::string, std::string>> *styles, const char *parent_ref,
+                                     const char *richtext_ref) {
+    JNIEnv *env = base::android::AttachCurrentThread();
+    if (env == nullptr)
+        return -1;
+
+    int flag = wx_bridge_->UpdateRichtextStyle(env, pageId, ref, styles, parent_ref, richtext_ref);
+    if (flag == -1) {
+        LOGE("instance destroy JFM must stop UpdateRichtextStyle");
+    }
+    return flag;
+}
+int AndroidSide::UpdateRichtextChildAttr(const char *pageId, const char *ref,
+                                         std::vector<std::pair<std::string, std::string>> *attributes,
+                                         const char *parent_ref, const char *richtext_ref) {
+    JNIEnv *env = base::android::AttachCurrentThread();
+    if (env == nullptr)
+        return -1;
+
+    int flag = wx_bridge_->UpdateRichtextChildAttr(env, pageId, ref, attributes, parent_ref, richtext_ref);
+    if (flag == -1) {
+        LOGE("instance destroy JFM must stop UpdateRichtextChildAttr");
+    }
+    return flag;
+}
 
 std::unique_ptr<ValueWithType> AndroidSide::CallNativeModule(
     const char *page_id, const char *module, const char *method,
diff --git a/weex_core/Source/android/bridge/platform/android_side.h b/weex_core/Source/android/bridge/platform/android_side.h
old mode 100644
new mode 100755
index 1593e90..550e50a
--- a/weex_core/Source/android/bridge/platform/android_side.h
+++ b/weex_core/Source/android/bridge/platform/android_side.h
@@ -79,6 +79,17 @@ class AndroidSide : public PlatformBridge::PlatformSide {
                  std::set<std::string>* events, const WXCoreMargin& margins,
                  const WXCorePadding& paddings,
                  const WXCoreBorderWidth& borders, bool willLayout) override;
+  int AddChildToRichtext(const char *pageId, const char *nodeType, const char *ref, const char *parentRef,
+                         const char *richtextRef, std::map<std::string, std::string> *styles,
+                         std::map<std::string, std::string> *attributes) override;
+  int RemoveChildFromRichtext(const char *pageId, const char *ref, const char *parent_ref,
+                              const char *richtext_ref) override;
+  int UpdateRichtextStyle(const char *pageId, const char *ref,
+                          std::vector<std::pair<std::string, std::string>> *style, const char *parent_ref,
+                          const char *richtext_ref) override;
+  int UpdateRichtextChildAttr(const char *pageId, const char *ref,
+                              std::vector<std::pair<std::string, std::string>> *attrs,
+                              const char *parent_ref, const char *richtext_ref) override;
   int Layout(const char* page_id, const char* ref, float top, float bottom,
              float left, float right, float height, float width, bool isRTL,
              int index) override;
diff --git a/weex_core/Source/android/wrap/wx_bridge.cpp b/weex_core/Source/android/wrap/wx_bridge.cpp
old mode 100644
new mode 100755
index 0ac8277..01fd2b0
--- a/weex_core/Source/android/wrap/wx_bridge.cpp
+++ b/weex_core/Source/android/wrap/wx_bridge.cpp
@@ -1014,6 +1014,57 @@ int WXBridge::AddEvent(JNIEnv* env, const char* page_id, const char* ref,
                                     jEventId.Get());
 }
 
+int WXBridge::AddChildToRichtext(JNIEnv* env, const char *pageId, const char *nodeType,
+        const char *ref,const char *parentRef,const char *richtextRef,
+        std::map<std::string, std::string> *styles,std::map<std::string, std::string> *attributes) {
+    auto jPageId = base::android::ScopedLocalJavaRef<jstring>(env, env->NewStringUTF(pageId));
+    auto jParentPef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(parentRef));
+    auto jRef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(ref));
+    auto jRichtextRef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(richtextRef));
+    auto jNodeType =
+                base::android::ScopedLocalJavaRef<jstring>(env, env->NewStringUTF(nodeType));
+    auto styles_map = std::unique_ptr<WXMap>(new WXMap);
+    styles_map->Put(env, *styles);
+    auto attributes_map = std::unique_ptr<WXMap>(new WXMap);
+    attributes_map->Put(env, *attributes);
+    return Java_WXBridge_callAddChildToRichtext(env, jni_object(), jPageId.Get(), jNodeType.Get(), jRef.Get(),
+            jParentPef.Get(),jRichtextRef.Get(),styles_map->jni_object(), attributes_map->jni_object());
+}
+
+int WXBridge::RemoveChildFromRichtext(JNIEnv* env, const char *pageId, const char *ref, const char *parent_ref,
+                                          const char *richtext_ref) {
+    auto jPageId = base::android::ScopedLocalJavaRef<jstring>(env, env->NewStringUTF(pageId));
+    auto jParentPef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(parent_ref));
+    auto jRef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(ref));
+    auto jRichtextRef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(richtext_ref));
+    return Java_WXBridge_callRemoveChildFromRichtext(env, jni_object(), jPageId.Get(),jRef.Get(),
+                                                    jParentPef.Get(),jRichtextRef.Get());
+}
+int WXBridge::UpdateRichtextStyle(JNIEnv* env, const char *pageId, const char *ref,
+                                      std::vector<std::pair<std::string, std::string>> *styles, const char *parent_ref,
+                                      const char *richtext_ref) {
+    auto jPageId = base::android::ScopedLocalJavaRef<jstring>(env, env->NewStringUTF(pageId));
+    auto jParentPef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(parent_ref));
+    auto jRef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(ref));
+    auto jRichtextRef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(richtext_ref));
+    auto styles_map = std::unique_ptr<WXMap>(new WXMap);
+    styles_map->Put(env, *styles);
+    return Java_WXBridge_callUpdateRichtextStyle(env, jni_object(), jPageId.Get(), jRef.Get(),
+                                                    styles_map->jni_object(), jParentPef.Get(), jRichtextRef.Get());
+}
+int WXBridge::UpdateRichtextChildAttr(JNIEnv* env, const char *pageId, const char *ref,
+                                      std::vector<std::pair<std::string, std::string>> *attributes,
+                                      const char *parent_ref, const char *richtext_ref) {
+    auto jPageId = base::android::ScopedLocalJavaRef<jstring>(env, env->NewStringUTF(pageId));
+    auto jParentPef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(parent_ref));
+    auto jRef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(ref));
+    auto jRichtextRef = base::android::ScopedLocalJavaRef<jstring >(env, env->NewStringUTF(richtext_ref));
+    auto attributes_map = std::unique_ptr<WXMap>(new WXMap);
+    attributes_map->Put(env, *attributes);
+    return Java_WXBridge_callUpdateRichtextChildAttr(env, jni_object(), jPageId.Get(), jRef.Get(),
+                                                 attributes_map->jni_object(), jParentPef.Get(), jRichtextRef.Get());
+}
+
 int WXBridge::RefreshFinish(JNIEnv* env, const char* page_id, const char* task,
                             const char* callback) {
   auto jTask = base::android::ScopedLocalJavaRef<jbyteArray>(
diff --git a/weex_core/Source/android/wrap/wx_bridge.h b/weex_core/Source/android/wrap/wx_bridge.h
old mode 100644
new mode 100755
index 59738b9..579bdb6
--- a/weex_core/Source/android/wrap/wx_bridge.h
+++ b/weex_core/Source/android/wrap/wx_bridge.h
@@ -62,6 +62,17 @@ class WXBridge : public JNIObjectWrap {
                   std::vector<std::pair<std::string, std::string>> *margin,
                   std::vector<std::pair<std::string, std::string>> *padding,
                   std::vector<std::pair<std::string, std::string>> *border);
+  int AddChildToRichtext(JNIEnv* env, const char *pageId, const char *nodeType,
+          const char *ref,const char *parentRef,const char *richtextRef,
+          std::map<std::string, std::string> *styles,std::map<std::string, std::string> *attributes);
+  int RemoveChildFromRichtext(JNIEnv* env, const char *pageId, const char *ref, const char *parent_ref,
+                                          const char *richtext_ref);
+  int UpdateRichtextStyle(JNIEnv* env, const char *pageId, const char *ref,
+                                      std::vector<std::pair<std::string, std::string>> *styles, const char *parent_ref,
+                                      const char *richtext_ref);
+  int UpdateRichtextChildAttr(JNIEnv* env, const char *pageId, const char *ref,
+                                          std::vector<std::pair<std::string, std::string>> *attributes,
+                                          const char *parent_ref, const char *richtext_ref);
   int Layout(JNIEnv *env, const char *page_id, const char *ref, int top,
              int bottom, int left, int right, int height, int width,
              bool isRTL, int index);
diff --git a/weex_core/Source/base/android/jniprebuild/jniheader/WXBridge_jni.h b/weex_core/Source/base/android/jniprebuild/jniheader/WXBridge_jni.h
old mode 100644
new mode 100755
index eb8aa93..e53e07e
--- a/weex_core/Source/base/android/jniprebuild/jniheader/WXBridge_jni.h
+++ b/weex_core/Source/base/android/jniprebuild/jniheader/WXBridge_jni.h
@@ -761,6 +761,133 @@ static jint Java_WXBridge_callUpdateAttrs(JNIEnv* env, jobject obj, jstring
   return ret;
 }
 
+static intptr_t g_WXBridge_callAddChildToRichtext = 0;
+static jint Java_WXBridge_callAddChildToRichtext(JNIEnv* env, jobject obj, jstring instanceId, jstring nodeType,
+                                          jstring ref,
+                                          jstring parentRef,
+                                          jstring richtextRef,
+                                          jobject styles,
+                                          jobject attrs) {
+    /* Must call RegisterNativesImpl()  */
+    //CHECK_CLAZZ(env, obj,
+    //    WXBridge_clazz(env), 0);
+    jmethodID method_id =
+            base::android::GetMethod(
+                    env, WXBridge_clazz(env),
+                    base::android::INSTANCE_METHOD,
+                    "callAddChildToRichtext",
+
+                    "("
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    "Ljava/util/HashMap;"
+                    "Ljava/util/HashMap;"
+                    ")"
+                    "I",
+                    &g_WXBridge_callAddChildToRichtext);
+
+    jint ret =
+            env->CallIntMethod(obj,
+                               method_id, instanceId, nodeType, ref,  parentRef, richtextRef, styles, attrs);
+    base::android::CheckException(env);
+    return ret;
+}
+
+static intptr_t g_WXBridge_callRemoveChildFromRichtext = 0;
+static jint Java_WXBridge_callRemoveChildFromRichtext(JNIEnv* env, jobject obj, jstring instanceId,
+                                                 jstring ref,
+                                                 jstring parentRef,
+                                                 jstring richtextRef) {
+    /* Must call RegisterNativesImpl()  */
+    //CHECK_CLAZZ(env, obj,
+    //    WXBridge_clazz(env), 0);
+    jmethodID method_id =
+            base::android::GetMethod(
+                    env, WXBridge_clazz(env),
+                    base::android::INSTANCE_METHOD,
+                    "callRemoveChildFromRichtext",
+
+                    "("
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    ")"
+                    "I",
+                    &g_WXBridge_callRemoveChildFromRichtext);
+
+    jint ret =
+            env->CallIntMethod(obj,
+                               method_id, instanceId, ref,  parentRef, richtextRef);
+    base::android::CheckException(env);
+    return ret;
+}
+
+static intptr_t g_WXBridge_callUpdateRichtextStyle = 0;
+static jint Java_WXBridge_callUpdateRichtextStyle(JNIEnv* env, jobject obj, jstring instanceId,
+                                                 jstring ref,
+                                                 jobject styles,
+                                                 jstring parentRef,
+                                                 jstring richtextRef) {
+    /* Must call RegisterNativesImpl()  */
+    //CHECK_CLAZZ(env, obj,
+    //    WXBridge_clazz(env), 0);
+    jmethodID method_id =
+            base::android::GetMethod(
+                    env, WXBridge_clazz(env),
+                    base::android::INSTANCE_METHOD,
+                    "callUpdateRichtextStyle",
+                    "("
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    "Ljava/util/HashMap;"
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    ")"
+                    "I",
+                    &g_WXBridge_callUpdateRichtextStyle);
+
+    jint ret =
+            env->CallIntMethod(obj,
+                               method_id, instanceId, ref, styles, parentRef, richtextRef);
+    base::android::CheckException(env);
+    return ret;
+}
+
+static intptr_t g_WXBridge_callUpdateRichtextChildAttr = 0;
+static jint Java_WXBridge_callUpdateRichtextChildAttr(JNIEnv* env, jobject obj, jstring instanceId,
+                                                  jstring ref,
+                                                  jobject attrs,
+                                                  jstring parentRef,
+                                                  jstring richtextRef) {
+    /* Must call RegisterNativesImpl()  */
+    //CHECK_CLAZZ(env, obj,
+    //    WXBridge_clazz(env), 0);
+    jmethodID method_id =
+            base::android::GetMethod(
+                    env, WXBridge_clazz(env),
+                    base::android::INSTANCE_METHOD,
+                    "callUpdateRichtextChildAttr",
+                    "("
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    "Ljava/util/HashMap;"
+                    "Ljava/lang/String;"
+                    "Ljava/lang/String;"
+                    ")"
+                    "I",
+                    &g_WXBridge_callUpdateRichtextChildAttr);
+
+    jint ret =
+            env->CallIntMethod(obj,
+                               method_id, instanceId, ref, attrs, parentRef, richtextRef);
+    base::android::CheckException(env);
+    return ret;
+}
+
 static intptr_t g_WXBridge_callLayout = 0;
 static jint Java_WXBridge_callLayout(JNIEnv* env, jobject obj, jstring
     instanceId,
diff --git a/weex_core/Source/core/bridge/eagle_bridge.cpp b/weex_core/Source/core/bridge/eagle_bridge.cpp
index c7272ba..61a9356 100644
--- a/weex_core/Source/core/bridge/eagle_bridge.cpp
+++ b/weex_core/Source/core/bridge/eagle_bridge.cpp
@@ -39,7 +39,11 @@ namespace WeexCore {
     }
     
     void EagleRenderObject::AddStyle(std::string key, std::string value) {
-        render_object_impl_->AddStyle(key, value, false);
+        if (render_object_impl_->is_richtext_child()) {
+            render_object_impl_->MapInsertOrAssign(render_object_impl_->styles(), key, value);
+        } else {
+            render_object_impl_->AddStyle(key, value, false);
+        }
     }
 
     void EagleRenderObject::UpdateAttr(std::string key, std::string value) {
@@ -93,6 +97,10 @@ namespace WeexCore {
         return render_object_impl_->GetChild(index);
     }
 
+    void EagleRenderObject::set_is_richtext_child(const bool is_richtext_child) {
+        render_object_impl_->set_is_richtext_child(is_richtext_child);
+    }
+
     EagleRenderObject EagleRenderObject::parent_render(){
         return render_object_impl_->parent_render();
     }
diff --git a/weex_core/Source/core/bridge/eagle_bridge.h b/weex_core/Source/core/bridge/eagle_bridge.h
index f7b0478..80e5630 100644
--- a/weex_core/Source/core/bridge/eagle_bridge.h
+++ b/weex_core/Source/core/bridge/eagle_bridge.h
@@ -41,6 +41,7 @@ namespace WeexCore {
         void UpdateStyle(std::string key, std::string value);
         void AddEvent(std::string event);
         void RemoveEvent(std::string event);
+        void set_is_richtext_child(const bool is_richtext_child);
         std::set<std::string> *events();
         
         void set_page_id(const std::string& page_id);
diff --git a/weex_core/Source/core/bridge/platform_bridge.h b/weex_core/Source/core/bridge/platform_bridge.h
index e613bd4..ba6ab7c 100644
--- a/weex_core/Source/core/bridge/platform_bridge.h
+++ b/weex_core/Source/core/bridge/platform_bridge.h
@@ -215,6 +215,12 @@ class PlatformBridge {
                            const WXCorePadding& paddings,
                            const WXCoreBorderWidth& borders,
                            bool willLayout = true) = 0;
+
+      virtual int AddChildToRichtext(const char* pageId, const char *nodeType, const char* ref,
+                                       const char* parentRef, const char* richtextRef,
+                                       std::map<std::string, std::string> *styles,
+                                       std::map<std::string, std::string> *attributes) = 0;
+
     virtual int Layout(const char* page_id, const char* ref, float top,
                        float bottom, float left, float right, float height,
                        float width, bool isRTL, int index) = 0;
@@ -225,16 +231,27 @@ class PlatformBridge {
         std::vector<std::pair<std::string, std::string>>* margin,
         std::vector<std::pair<std::string, std::string>>* padding,
         std::vector<std::pair<std::string, std::string>>* border) = 0;
+
     virtual int UpdateAttr(
         const char* pageId, const char* ref,
         std::vector<std::pair<std::string, std::string>>* attrs) = 0;
 
+    virtual int UpdateRichtextChildAttr(
+                                          const char* pageId, const char* ref,
+                                          std::vector<std::pair<std::string, std::string>>* attrs, const char* parent_ref, const char* richtext_ref) = 0;
+
+    virtual int UpdateRichtextStyle(const char* pageId, const char* ref,
+                                      std::vector<std::pair<std::string, std::string>> *style,
+                                      const char* parent_ref, const char* richtext_ref) = 0;
+
     virtual int CreateFinish(const char* pageId) = 0;
 
     virtual int RenderSuccess(const char* pageId) = 0;
 
     virtual int RemoveElement(const char* pageId, const char* ref) = 0;
 
+    virtual int RemoveChildFromRichtext(const char* pageId, const char* ref, const char* parent_ref, const char* richtext_ref) = 0;
+
     virtual int MoveElement(const char* pageId, const char* ref,
                             const char* parentRef, int index) = 0;
 
diff --git a/weex_core/Source/core/layout/layout.h b/weex_core/Source/core/layout/layout.h
index d552063..6217972 100644
--- a/weex_core/Source/core/layout/layout.h
+++ b/weex_core/Source/core/layout/layout.h
@@ -183,6 +183,9 @@ namespace WeexCore {
         }
       }
 
+      const std::vector<WXCoreLayoutNode *>& get_child_list() const {return mChildList;}
+
+      void removeAllChildren() {mChildList.clear();}
   private:
 
     /**
diff --git a/weex_core/Source/core/render/action/render_action_add_child_to_richtext.cpp b/weex_core/Source/core/render/action/render_action_add_child_to_richtext.cpp
new file mode 100644
index 0000000..1d11ab0
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_add_child_to_richtext.cpp
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "core/render/action/render_action_add_child_to_richtext.h"
+#include "core/manager/weex_core_manager.h"
+#include "core/render/node/render_object.h"
+
+namespace WeexCore {
+    RenderActionAddChildToRichtext::RenderActionAddChildToRichtext(const std::string &page_id, const RenderObject *render, const RenderObject *parent, const RenderObject *richtext) {
+        this->attributes_ = render->attributes();
+        this->styles_ = render->styles();
+        this->page_id_ = page_id;
+        this->node_type_ = render->type();
+        this->ref_ = render->ref();
+        this->parent_ref_ = parent ? parent->ref() : "";
+        this->richtext_ref_ = richtext->ref();
+    }
+
+    void RenderActionAddChildToRichtext::ExecuteAction() {
+        WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->AddChildToRichtext(
+                                                                                      this->page_id_.c_str(), this->node_type_.c_str(), this->ref_.c_str(),
+                                                                                      this->parent_ref_.c_str(), this->richtext_ref_.c_str(), this->styles_, this->attributes_);
+    }
+}  // namespace WeexCore
diff --git a/weex_core/Source/core/render/action/render_action_add_child_to_richtext.h b/weex_core/Source/core/render/action/render_action_add_child_to_richtext.h
new file mode 100644
index 0000000..f07a4ed
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_add_child_to_richtext.h
@@ -0,0 +1,53 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef CORE_RENDER_ACTION_RENDER_ACTION_ADD_CHILD_TO_RICHTEXT_H_
+#define CORE_RENDER_ACTION_RENDER_ACTION_ADD_CHILD_TO_RICHTEXT_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "core/layout/style.h"
+#include "core/render/action/render_action_interface.h"
+
+namespace WeexCore {
+
+class RenderObject;
+
+class RenderActionAddChildToRichtext : public RenderAction {
+ public:
+  explicit RenderActionAddChildToRichtext(const std::string &page_id,
+                                  const RenderObject *render,
+                                  const RenderObject *parent,
+                                  const RenderObject *richtext);
+
+  void ExecuteAction();
+
+ public:
+  std::map<std::string, std::string> *styles_;
+  std::map<std::string, std::string> *attributes_;
+  std::string page_id_;
+  std::string parent_ref_;
+  std::string node_type_;
+  std::string ref_;
+  std::string richtext_ref_;
+};
+}  // namespace WeexCore
+
+#endif  // CORE_RENDER_ACTION_RENDER_ACTION_ADD_CHILD_TO_RICHTEXT_H_
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java b/weex_core/Source/core/render/action/render_action_remove_child_from_richtext.cpp
similarity index 50%
copy from android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java
copy to weex_core/Source/core/render/action/render_action_remove_child_from_richtext.cpp
index 26e3055..8bfde5d 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java
+++ b/weex_core/Source/core/render/action/render_action_remove_child_from_richtext.cpp
@@ -16,11 +16,24 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package com.taobao.weex.ui.component.richtext.node;
 
-import android.content.Context;
+#include "core/render/action/render_action_remove_child_from_richtext.h"
+#include "core/manager/weex_core_manager.h"
+#include "core/render/node/render_object.h"
 
-public interface RichTextNodeCreator<T extends RichTextNode> {
+namespace WeexCore {
 
-  T createRichTextNode(Context context, String instanceId, String componentRef);
+RenderActionRemoveChildFromRichtext::RenderActionRemoveChildFromRichtext(const std::string &page_id, const std::string &ref, const RenderObject* parent, RenderObject* richtext) {
+  this->page_id_ = page_id;
+  this->ref_ = ref;
+  this->parent_ref_ = parent ? parent->ref() : "";
+  this->richtext_ref_ = richtext->ref();
 }
+
+void RenderActionRemoveChildFromRichtext::ExecuteAction() {
+  WeexCoreManager::Instance()
+      ->getPlatformBridge()
+      ->platform_side()
+      ->RemoveChildFromRichtext(this->page_id_.c_str(), this->ref_.c_str(), this->parent_ref_.c_str(), this->richtext_ref_.c_str());
+}
+}  // namespace WeexCore
diff --git a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java b/weex_core/Source/core/render/action/render_action_remove_child_from_richtext.h
similarity index 52%
copy from android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java
copy to weex_core/Source/core/render/action/render_action_remove_child_from_richtext.h
index 26e3055..584d9ca 100644
--- a/android/sdk/src/main/java/com/taobao/weex/ui/component/richtext/node/RichTextNodeCreator.java
+++ b/weex_core/Source/core/render/action/render_action_remove_child_from_richtext.h
@@ -16,11 +16,26 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package com.taobao.weex.ui.component.richtext.node;
+#ifndef CORE_RENDER_ACTION_RENDER_ACTION_REMOVE_CHILD_FROM_RICHTEXT_H_
+#define CORE_RENDER_ACTION_RENDER_ACTION_REMOVE_CHILD_FROM_RICHTEXT_H_
 
-import android.content.Context;
+#include <string>
+#include "core/render/action/render_action_interface.h"
 
-public interface RichTextNodeCreator<T extends RichTextNode> {
+namespace WeexCore {
+class RenderObject;
+class RenderActionRemoveChildFromRichtext : public RenderAction {
+ public:
+  explicit RenderActionRemoveChildFromRichtext(const std::string &page_id, const std::string &ref, const RenderObject* parent, RenderObject* richtext);
 
-  T createRichTextNode(Context context, String instanceId, String componentRef);
-}
+  void ExecuteAction();
+
+ public:
+  std::string page_id_;
+  std::string ref_;
+  std::string parent_ref_;
+  std::string richtext_ref_;
+};
+}  // namespace WeexCore
+
+#endif  // CORE_RENDER_ACTION_RENDER_ACTION_REMOVE_CHILD_FROM_RICHTEXT_H_
diff --git a/weex_core/Source/core/render/action/render_action_update_richtext_child_attr.cpp b/weex_core/Source/core/render/action/render_action_update_richtext_child_attr.cpp
new file mode 100644
index 0000000..efefe65
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_update_richtext_child_attr.cpp
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "core/render/action/render_action_update_richtext_child_attr.h"
+#include "core/manager/weex_core_manager.h"
+#include "core/render/node/render_object.h"
+
+namespace WeexCore {
+
+RenderActionUpdateRichtextChildAttr::RenderActionUpdateRichtextChildAttr(
+    const std::string &page_id, const std::string &ref,
+    std::vector<std::pair<std::string, std::string>> *attrs, RenderObject *parent, RenderObject *richtext) {
+  this->page_id_ = page_id;
+  this->ref_ = ref;
+  this->attrs_ = attrs;
+  this->richtext_ref_ = richtext->ref();
+  this->parent_ref_ = parent ? parent->ref() : "";
+}
+
+void RenderActionUpdateRichtextChildAttr::ExecuteAction() {
+    WeexCoreManager::Instance()->getPlatformBridge()->platform_side()->UpdateRichtextChildAttr(this->page_id_.c_str(), this->ref_.c_str(), this->attrs_, this->parent_ref_.c_str(), this->richtext_ref_.c_str());
+}
+}  // namespace WeexCore
+
diff --git a/weex_core/Source/core/render/action/render_action_update_richtext_child_attr.h b/weex_core/Source/core/render/action/render_action_update_richtext_child_attr.h
new file mode 100644
index 0000000..43bbac6
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_update_richtext_child_attr.h
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef CORE_RENDER_ACTION_RENDER_ACTION_UPDATE_RICHTEXT_CHILD_ATTR_H_
+#define CORE_RENDER_ACTION_RENDER_ACTION_UPDATE_RICHTEXT_CHILD_ATTR_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+#include "core/render/action/render_action_interface.h"
+
+namespace WeexCore {
+class RenderObject;
+class RenderActionUpdateRichtextChildAttr : public RenderAction {
+ public:
+  explicit RenderActionUpdateRichtextChildAttr(
+      const std::string &page_id, const std::string &ref,
+      std::vector<std::pair<std::string, std::string>> *attrs, RenderObject *parent, RenderObject *richtext);
+
+  void ExecuteAction();
+
+ public:
+  std::string page_id_;
+  std::string ref_;
+  std::string parent_ref_;
+  std::vector<std::pair<std::string, std::string>> *attrs_;
+  std::string richtext_ref_;
+};
+}  // namespace WeexCore
+
+#endif  // CORE_RENDER_ACTION_RENDER_ACTION_UPDATE_RICHTEXT_CHILD_ATTR_H_
diff --git a/weex_core/Source/core/render/action/render_action_update_richtext_child_style.cpp b/weex_core/Source/core/render/action/render_action_update_richtext_child_style.cpp
new file mode 100644
index 0000000..66a6503
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_update_richtext_child_style.cpp
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include "core/render/action/render_action_update_richtext_child_style.h"
+#include "core/manager/weex_core_manager.h"
+#include "core/render/node/render_object.h"
+
+namespace WeexCore {
+
+RenderActionUpdateRichtextChildStyle::RenderActionUpdateRichtextChildStyle(
+    const std::string &page_id, const std::string &ref,
+    std::vector<std::pair<std::string, std::string>> *style,
+   RenderObject *parent, RenderObject *richtext) {
+  this->page_id_ = page_id;
+  this->ref_ = ref;
+  this->style_ = style;
+  this->parent_ref_ = parent ? parent->ref() : "";
+  this->richtext_ref_ = richtext->ref();
+}
+
+void RenderActionUpdateRichtextChildStyle::ExecuteAction() {
+  WeexCoreManager::Instance()
+      ->getPlatformBridge()
+      ->platform_side()
+      ->UpdateRichtextStyle(this->page_id_.c_str(), this->ref_.c_str(), this->style_, this->parent_ref_.c_str(), this->richtext_ref_.c_str());
+}
+}  // namespace WeexCore
diff --git a/weex_core/Source/core/render/action/render_action_update_richtext_child_style.h b/weex_core/Source/core/render/action/render_action_update_richtext_child_style.h
new file mode 100644
index 0000000..60297d7
--- /dev/null
+++ b/weex_core/Source/core/render/action/render_action_update_richtext_child_style.h
@@ -0,0 +1,47 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef CORE_RENDER_ACTION_RENDER_ACTION_UPDATE_RICHTEXT_CHILD_STYLE_H_
+#define CORE_RENDER_ACTION_RENDER_ACTION_UPDATE_RICHTEXT_CHILD_STYLE_H_
+
+#include <string>
+#include <utility>
+#include <vector>
+#include "core/render/action/render_action_interface.h"
+
+namespace WeexCore {
+class RenderObject;
+class RenderActionUpdateRichtextChildStyle : public RenderAction {
+ public:
+  explicit RenderActionUpdateRichtextChildStyle(
+      const std::string &page_id, const std::string &ref,
+      std::vector<std::pair<std::string, std::string>> *style,
+      RenderObject *parent, RenderObject *richtext);
+
+  void ExecuteAction();
+
+ public:
+  std::string page_id_;
+  std::string ref_;
+  std::string parent_ref_;
+  std::vector<std::pair<std::string, std::string>> *style_;
+  std::string richtext_ref_;
+};
+}  // namespace WeexCore
+
+#endif  // CORE_RENDER_ACTION_RENDER_ACTION_UPDATE_RICHTEXT_CHILD_STYLE_H_
diff --git a/weex_core/Source/core/render/node/render_object.cpp b/weex_core/Source/core/render/node/render_object.cpp
index ff03197..cbeec28 100644
--- a/weex_core/Source/core/render/node/render_object.cpp
+++ b/weex_core/Source/core/render/node/render_object.cpp
@@ -62,6 +62,10 @@ RenderObject::~RenderObject() {
       delete child;
     }
   }
+
+  for (auto it : shadow_objects_) {
+      delete it;
+  }
 }
 
 void RenderObject::ApplyDefaultStyle(bool reserve) {
@@ -77,6 +81,15 @@ void RenderObject::ApplyDefaultStyle(bool reserve) {
   }
 }
 
+RenderObject* RenderObject::RichtextParent() {
+    if (parent_render_ && parent_render_->type() == "richtext") {
+        return parent_render_;
+    } else if (parent_render_) {
+        return parent_render_->RichtextParent();
+    }
+    return nullptr;
+}
+
 void RenderObject::ApplyDefaultAttr() {
   std::map<std::string, std::string> *attrs = GetDefaultAttr();
 
@@ -326,11 +339,27 @@ const std::string RenderObject::GetAttr(const std::string &key) {
   }
 }
 
+bool RenderObject::hasShadow(const RenderObject* shadow) const {
+    if(std::find(shadow_objects_.begin(), shadow_objects_.end(), shadow) != shadow_objects_.end()){
+        return true;
+    }else{
+        return false;
+    }
+}
+
 int RenderObject::AddRenderObject(int index, RenderObject *child) {
   if (child == nullptr || index < -1) {
     return index;
   }
 
+  if (type() == "richtext") {
+      if (!hasShadow(child)) {
+          shadow_objects_.push_back(child);
+          child->set_parent_render(this);
+      }
+      return index;
+  }
+
   Index count = getChildCount();
   index = index >= count ? -1 : index;
   if (index == -1) {
@@ -482,7 +511,18 @@ RenderObject *RenderObject::GetChild(const Index &index) {
 }
 
 void RenderObject::RemoveRenderObject(RenderObject *child) {
-  removeChild(child);
+    if (type() == "richtext") {
+        int index = 0;
+        for (auto it : shadow_objects_) {
+            if (it == child) {
+                shadow_objects_.erase(shadow_objects_.begin() + index);
+                return;
+            }
+            index++;
+        }
+    } else {
+          removeChild(child);
+    }
 }
 
 void RenderObject::AddAttr(std::string key, std::string value) {
diff --git a/weex_core/Source/core/render/node/render_object.h b/weex_core/Source/core/render/node/render_object.h
index 2123027..357a454 100644
--- a/weex_core/Source/core/render/node/render_object.h
+++ b/weex_core/Source/core/render/node/render_object.h
@@ -60,6 +60,10 @@ class RenderObject : public IRenderObject {
 
   void CopyFrom(RenderObject *src);
 
+  RenderObject* RichtextParent();
+
+  bool hasShadow(const RenderObject* shadow) const;
+
   void MapInsertOrAssign(std::map<std::string, std::string> *targetMap,
                          const std::string &key, const std::string &value);
 
@@ -136,6 +140,8 @@ class RenderObject : public IRenderObject {
 
   inline RenderObject *parent_render() { return this->parent_render_; }
 
+  const std::vector<RenderObject*>& get_shadow_objects() const {return shadow_objects_;}
+
   inline std::map<std::string, std::string> *styles() const {
     return this->styles_;
   }
@@ -152,13 +158,19 @@ class RenderObject : public IRenderObject {
 
   inline bool is_sticky() { return this->is_sticky_; }
 
+  bool is_richtext_child() const {return is_richtext_child_;}
+
+  void set_is_richtext_child(const bool is_richtext_child) {is_richtext_child_ = is_richtext_child;}
+
  private:
   RenderObject *parent_render_;
+  std::vector<RenderObject*> shadow_objects_;
   std::map<std::string, std::string> *styles_;
   std::map<std::string, std::string> *attributes_;
   std::set<std::string> *events_;
   bool is_root_render_;
   bool is_sticky_ = false;
+  bool is_richtext_child_ = false;
 };
 }  // namespace WeexCore
 #endif  // CORE_RENDER_NODE_RENDER_OBJECT_H_
diff --git a/weex_core/Source/core/render/page/render_page.cpp b/weex_core/Source/core/render/page/render_page.cpp
old mode 100644
new mode 100755
index 6768f14..f13b271
--- a/weex_core/Source/core/render/page/render_page.cpp
+++ b/weex_core/Source/core/render/page/render_page.cpp
@@ -28,6 +28,7 @@
 #include "core/moniter/render_performance.h"
 #include "core/render/page/render_page.h"
 #include "core/render/action/render_action_add_element.h"
+#include "core/render/action/render_action_add_child_to_richtext.h"
 #include "core/render/action/render_action_add_event.h"
 #include "core/render/action/render_action_appendtree_createfinish.h"
 #include "core/render/action/render_action_createbody.h"
@@ -35,10 +36,13 @@
 #include "core/render/action/render_action_layout.h"
 #include "core/render/action/render_action_move_element.h"
 #include "core/render/action/render_action_remove_element.h"
+#include "core/render/action/render_action_remove_child_from_richtext.h"
 #include "core/render/action/render_action_remove_event.h"
 #include "core/render/action/render_action_render_success.h"
 #include "core/render/action/render_action_update_attr.h"
+#include "core/render/action/render_action_update_richtext_child_attr.h"
 #include "core/render/action/render_action_update_style.h"
+#include "core/render/action/render_action_update_richtext_child_style.h"
 #include "core/render/action/render_action_trigger_vsync.h"
 #include "core/render/manager/render_manager.h"
 #include "core/render/node/factory/render_type.h"
@@ -187,8 +191,15 @@ bool RenderPage::RemoveRenderObject(const std::string &ref) {
   parent->RemoveRenderObject(child);
 
   RemoveRenderFromRegisterMap(child);
-  SendRemoveElementAction(ref);
-    
+  RenderObject* richtext = child->RichtextParent();
+  if (richtext) {
+      RenderObject* parent = child->parent_render();
+      SendRemoveChildFromRichtextAction(ref, parent->type() == "richtext" ? nullptr : parent, richtext);
+      richtext->markDirty();
+      Batch();
+  } else {
+      SendRemoveElementAction(ref);
+  }
   delete child;
   return true;
 }
@@ -233,77 +244,85 @@ bool RenderPage::UpdateStyle(
   bool inheriableLayout = false;
     
   bool flag = false;
-  int result =
-      WeexCoreManager::Instance()
-          ->getPlatformBridge()
-          ->platform_side()
-          ->HasTransitionPros(this->page_id_.c_str(), ref.c_str(), src);
-  // int result =
-  // Bridge_Impl_Android::getInstance()->callHasTransitionPros(mPageId.c_str(),
-  // ref.c_str(), src);
-
-  if (result == 1) {
-    SendUpdateStyleAction(render, src, margin, padding, border);
+  RenderObject* richtext = render->RichtextParent();
+
+  if (richtext) {
+      richtext->markDirty();
+      style = new std::vector<std::pair<std::string, std::string>>();
+      for (auto it : *src) {
+          style->push_back(it);
+      }
+      flag = true;
+      RenderObject* parent = render->parent_render();
+      SendUpdateRichtextChildStyleAction(render, style, parent->type() == "richtext" ? nullptr : parent, richtext);
   } else {
-    for (auto iter = src->begin(); iter != src->end(); iter++) {
-      switch (render->UpdateStyle((*iter).first, (*iter).second)) {
-        case kTypeStyle:
-          if (style == nullptr) {
-            style = new std::vector<std::pair<std::string, std::string>>();
-          }
-          style->insert(style->end(), (*iter));
-          flag = true;
-          break;
-        case kTypeMargin:
-          if (margin == nullptr) {
-            margin = new std::vector<std::pair<std::string, std::string>>();
-          }
-          render->UpdateStyleInternal(
-              (*iter).first, (*iter).second, 0, [=, &flag](float foo) {
-                  (*iter).second = to_string(foo);
-                  margin->insert(margin->end(), (*iter));
-                  flag = true;
-              });
-          break;
-        case kTypePadding:
-          if (padding == nullptr) {
-            padding = new std::vector<std::pair<std::string, std::string>>();
-          }
-          render->UpdateStyleInternal(
-              (*iter).first, (*iter).second, 0, [=, &flag](float foo) {
-                  (*iter).second = to_string(foo);
-                  padding->insert(padding->end(), (*iter));
-                  flag = true;
-              });
-          break;
-        case kTypeBorder:
-          if (border == nullptr) {
-            border = new std::vector<std::pair<std::string, std::string>>();
-          }
-          render->UpdateStyleInternal(
-              (*iter).first, (*iter).second, 0, [=, &flag](float foo) {
-                  (*iter).second = to_string(foo);
-                  border->insert(border->end(), (*iter));
-                  flag = true;
-              });
-          break;
-          case kTypeInheritableLayout:
-              inheriableLayout = true;
+      int result = WeexCoreManager::Instance()
+        ->getPlatformBridge()
+        ->platform_side()
+        ->HasTransitionPros(this->page_id_.c_str(), ref.c_str(), src);
+
+      if (result == 1) {
+        SendUpdateStyleAction(render, src, margin, padding, border);
+      } else {
+        for (auto iter = src->begin(); iter != src->end(); iter++) {
+          switch (render->UpdateStyle((*iter).first, (*iter).second)) {
+            case kTypeStyle:
+              if (style == nullptr) {
+                style = new std::vector<std::pair<std::string, std::string>>();
+              }
+              style->insert(style->end(), (*iter));
+              flag = true;
+              break;
+            case kTypeMargin:
+              if (margin == nullptr) {
+                margin = new std::vector<std::pair<std::string, std::string>>();
+              }
+              render->UpdateStyleInternal(
+                  (*iter).first, (*iter).second, 0, [=, &flag](float foo) {
+                      (*iter).second = to_string(foo);
+                      margin->insert(margin->end(), (*iter));
+                      flag = true;
+                  });
+              break;
+            case kTypePadding:
+              if (padding == nullptr) {
+                padding = new std::vector<std::pair<std::string, std::string>>();
+              }
+              render->UpdateStyleInternal(
+                  (*iter).first, (*iter).second, 0, [=, &flag](float foo) {
+                      (*iter).second = to_string(foo);
+                      padding->insert(padding->end(), (*iter));
+                      flag = true;
+                  });
+              break;
+            case kTypeBorder:
+              if (border == nullptr) {
+                border = new std::vector<std::pair<std::string, std::string>>();
+              }
+              render->UpdateStyleInternal(
+                  (*iter).first, (*iter).second, 0, [=, &flag](float foo) {
+                      (*iter).second = to_string(foo);
+                      border->insert(border->end(), (*iter));
+                      flag = true;
+                  });
               break;
+              case kTypeInheritableLayout:
+                  inheriableLayout = true;
+                  break;
         default: break;
+          }
+        }
+      }
+      if (reserve_css_styles_ || render == render_root_) {
+          // If a page requires that all raw css styles saved, we merge to RenderObject's styles map
+          render->MergeStyles(src);
       }
-    }
-  }
-  
-  if (reserve_css_styles_ || render == render_root_) {
-    // If a page requires that all raw css styles saved, we merge to RenderObject's styles map
-    render->MergeStyles(src);
-  }
-
-  if (style != nullptr || margin != nullptr || padding != nullptr ||
-      border != nullptr || inheriableLayout)
-    SendUpdateStyleAction(render, style, margin, padding, border);
 
+     if (style != nullptr || margin != nullptr || padding != nullptr ||
+         border != nullptr || inheriableLayout) {
+         SendUpdateStyleAction(render, style, margin, padding, border);
+     }
+  }
   Batch();
 
   if (src != nullptr) {
@@ -350,11 +369,17 @@ bool RenderPage::UpdateAttr(
   RenderObject *render = GetRenderObject(ref);
   if (render == nullptr || attrs == nullptr || attrs->empty()) return false;
 
-  set_is_dirty(true);
-  SendUpdateAttrAction(render, attrs);
-
-  for (auto iter = attrs->cbegin(); iter != attrs->cend(); iter++) {
-    render->UpdateAttr((*iter).first, (*iter).second);
+  RenderObject* richtext = render->RichtextParent();
+  if (richtext) {
+      RenderObject* parent = render->parent_render();
+      SendUpdateRichtextChildAttrAction(render, attrs, parent->type() == "richtext" ? nullptr : parent, richtext);
+      richtext->markDirty();
+  } else {
+      set_is_dirty(true);
+      SendUpdateAttrAction(render, attrs);
+      for (auto iter = attrs->cbegin(); iter != attrs->cend(); iter++) {
+          render->UpdateAttr((*iter).first, (*iter).second);
+      }
   }
   Batch();
   if (attrs != nullptr) {
@@ -461,6 +486,10 @@ void RenderPage::PushRenderToRegisterMap(RenderObject *render) {
       PushRenderToRegisterMap(child);
     }
   }
+
+  for (auto it : render->shadow_objects_) {
+      PushRenderToRegisterMap(it);
+  }
 }
 
 void RenderPage::RemoveRenderFromRegisterMap(RenderObject *render) {
@@ -505,10 +534,25 @@ void RenderPage::SendAddElementAction(RenderObject *child, RenderObject *parent,
   if (parent != nullptr && parent->type() == WeexCore::kRenderRecycleList) {
     will_layout = false;
   }
-
-  RenderAction *action =
-      new RenderActionAddElement(page_id(), child, parent, index, will_layout);
-  PostRenderAction(action);
+    RenderObject* richtext = child->RichtextParent();
+    if (!richtext) {
+        RenderAction *action =
+        new RenderActionAddElement(page_id(), child, parent, index, will_layout);
+        PostRenderAction(action);
+    } else {
+        SendAddChildToRichtextAction(child, parent->type() == "richtext" ? nullptr : parent, richtext);
+        richtext->markDirty();
+        return;
+    }
+    if (child->type() == "richtext") {
+        for (auto it : child->get_shadow_objects()) {
+            if (it) {
+                SendAddChildToRichtextAction(it, nullptr, child);
+            }
+        }
+        child->markDirty();
+        return;
+  }
 
   int i = 0;
   for (auto it = child->ChildListIterBegin(); it != child->ChildListIterEnd();
@@ -531,12 +575,28 @@ void RenderPage::SendAddElementAction(RenderObject *child, RenderObject *parent,
       ++i;
     }
   }
-
   if (!is_recursion && i > 0 && child->IsAppendTree()) {
     SendAppendTreeCreateFinish(child->ref());
   }
 }
 
+void RenderPage::SendAddChildToRichtextAction(RenderObject *child, RenderObject *parent, RenderObject *richtext) {
+    RenderAction *action =   new RenderActionAddChildToRichtext(page_id(), child, parent, richtext);
+    PostRenderAction(action);
+
+    for (auto it : child->get_child_list()) {
+        RenderObject *grandson = static_cast<RenderObject *>(it);
+        if (grandson) {
+            SendAddChildToRichtextAction(grandson, child, richtext);
+        }
+    }
+}
+
+void RenderPage::SendRemoveChildFromRichtextAction(const std::string &ref, RenderObject *parent, RenderObject *richtext) {
+    RenderAction *action = new RenderActionRemoveChildFromRichtext(page_id(), ref, parent, richtext);
+    PostRenderAction(action);
+}
+
 void RenderPage::SendRemoveElementAction(const std::string &ref) {
   RenderAction *action = new RenderActionRemoveElement(page_id(), ref);
   PostRenderAction(action);
@@ -568,6 +628,13 @@ void RenderPage::SendUpdateStyleAction(
   PostRenderAction(action);
 }
 
+void RenderPage::SendUpdateRichtextChildStyleAction(RenderObject *render, std::vector<std::pair<std::string, std::string>> *style, RenderObject *parent, RenderObject *richtext) {
+    RenderAction *action = new RenderActionUpdateRichtextChildStyle(
+                                                       page_id(), render->ref(), style, parent, richtext);
+    PostRenderAction(action);
+
+}
+
 void RenderPage::SendUpdateAttrAction(
     RenderObject *render,
     std::vector<std::pair<std::string, std::string>> *attrs) {
@@ -576,6 +643,14 @@ void RenderPage::SendUpdateAttrAction(
   PostRenderAction(action);
 }
 
+void RenderPage::SendUpdateRichtextChildAttrAction(
+                                      RenderObject *render,
+                                      std::vector<std::pair<std::string, std::string>> *attrs, RenderObject *parent, RenderObject *richtext) {
+    RenderAction *action =
+    new RenderActionUpdateRichtextChildAttr(page_id(), render->ref(), attrs, parent, richtext);
+    PostRenderAction(action);
+}
+
 void RenderPage::SendUpdateAttrAction(
     RenderObject *render, std::map<std::string, std::string> *attrs) {
   std::vector<std::pair<std::string, std::string>> *vAttrs =
diff --git a/weex_core/Source/core/render/page/render_page.h b/weex_core/Source/core/render/page/render_page.h
index d0a2dcb..10f67b4 100644
--- a/weex_core/Source/core/render/page/render_page.h
+++ b/weex_core/Source/core/render/page/render_page.h
@@ -43,9 +43,12 @@ class RenderPage: public RenderPageBase {
   void SendAddElementAction(RenderObject *child, RenderObject *parent,
                             int index, bool is_recursion,
                             bool will_layout = true);
+  void SendAddChildToRichtextAction(RenderObject *child, RenderObject *parent, RenderObject *richtext);
 
   void SendRemoveElementAction(const std::string &ref);
 
+  void SendRemoveChildFromRichtextAction(const std::string &ref, RenderObject *parent, RenderObject *richtext);
+
   void SendMoveElementAction(const std::string &ref,
                              const std::string &parent_ref, int index);
 
@@ -58,10 +61,15 @@ class RenderPage: public RenderPageBase {
       std::vector<std::pair<std::string, std::string>> *padding,
       std::vector<std::pair<std::string, std::string>> *border);
 
+  void SendUpdateRichtextChildStyleAction(RenderObject *render, std::vector<std::pair<std::string, std::string>> *style, RenderObject *parent, RenderObject *richtext);
+
   void SendUpdateAttrAction(
       RenderObject *render,
       std::vector<std::pair<std::string, std::string>> *attrs);
 
+ void SendUpdateRichtextChildAttrAction(
+                              RenderObject *render,
+                              std::vector<std::pair<std::string, std::string>> *attrs, RenderObject *parent, RenderObject *richtext);
   void SendAppendTreeCreateFinish(const std::string &ref);
   
   void LayoutInner();