├── .gitignore ├── HtmlText.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── HtmlText.xccheckout │ └── xcuserdata │ │ └── siuying.xcuserdatad │ │ └── UserInterfaceState.xcuserstate ├── xcshareddata │ └── xcschemes │ │ └── HtmlText.xcscheme └── xcuserdata │ └── siuying.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── README.md ├── example1.png ├── example2.png ├── iOS ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ └── LaunchScreen.xib ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist └── main.m ├── index.ios.js ├── lib └── HtmlText.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /HtmlText.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */; }; 11 | 00481BEA1AC0C89D00671115 /* libicucore.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 00481BE91AC0C89D00671115 /* libicucore.dylib */; }; 12 | 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; 13 | 00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */; }; 14 | 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; }; 15 | 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */; }; 16 | 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */; }; 17 | 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */; }; 18 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 19 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB11A68108700A75B9A /* LaunchScreen.xib */; }; 20 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 21 | 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; 22 | 146834051AC3E58100842450 /* libReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 146834041AC3E56700842450 /* libReact.a */; }; 23 | 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 832341B51AAA6A8300B99B32 /* libRCTText.a */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | 00481BE51AC0C7FA00671115 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */; 30 | proxyType = 2; 31 | remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; 32 | remoteInfo = RCTWebSocketDebugger; 33 | }; 34 | 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; 37 | proxyType = 2; 38 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 39 | remoteInfo = RCTActionSheet; 40 | }; 41 | 00C302B31ABCB8E700DB3ED1 /* PBXContainerItemProxy */ = { 42 | isa = PBXContainerItemProxy; 43 | containerPortal = 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */; 44 | proxyType = 2; 45 | remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; 46 | remoteInfo = RCTAdSupport; 47 | }; 48 | 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */ = { 49 | isa = PBXContainerItemProxy; 50 | containerPortal = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; 51 | proxyType = 2; 52 | remoteGlobalIDString = 134814201AA4EA6300B7C361; 53 | remoteInfo = RCTGeolocation; 54 | }; 55 | 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */ = { 56 | isa = PBXContainerItemProxy; 57 | containerPortal = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; 58 | proxyType = 2; 59 | remoteGlobalIDString = 58B5115D1A9E6B3D00147676; 60 | remoteInfo = RCTImage; 61 | }; 62 | 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */ = { 63 | isa = PBXContainerItemProxy; 64 | containerPortal = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; 65 | proxyType = 2; 66 | remoteGlobalIDString = 58B511DB1A9E6C8500147676; 67 | remoteInfo = RCTNetwork; 68 | }; 69 | 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */ = { 70 | isa = PBXContainerItemProxy; 71 | containerPortal = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; 72 | proxyType = 2; 73 | remoteGlobalIDString = 832C81801AAF6DEF007FA2F7; 74 | remoteInfo = RCTVibration; 75 | }; 76 | 146834031AC3E56700842450 /* PBXContainerItemProxy */ = { 77 | isa = PBXContainerItemProxy; 78 | containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */; 79 | proxyType = 2; 80 | remoteGlobalIDString = 83CBBA2E1A601D0E00E9B192; 81 | remoteInfo = React; 82 | }; 83 | 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */ = { 84 | isa = PBXContainerItemProxy; 85 | containerPortal = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; 86 | proxyType = 2; 87 | remoteGlobalIDString = 58B5119B1A9E6C1200147676; 88 | remoteInfo = RCTText; 89 | }; 90 | /* End PBXContainerItemProxy section */ 91 | 92 | /* Begin PBXFileReference section */ 93 | 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTWebSocketDebugger.xcodeproj; path = node_modules/react-native/Libraries/RCTWebSocketDebugger/RCTWebSocketDebugger.xcodeproj; sourceTree = ""; }; 94 | 00481BE91AC0C89D00671115 /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = usr/lib/libicucore.dylib; sourceTree = SDKROOT; }; 95 | 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTActionSheet.xcodeproj; path = node_modules/react-native/Libraries/ActionSheetIOS/RCTActionSheet.xcodeproj; sourceTree = ""; }; 96 | 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAdSupport.xcodeproj; path = node_modules/react-native/Libraries/AdSupport/RCTAdSupport.xcodeproj; sourceTree = ""; }; 97 | 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTGeolocation.xcodeproj; path = node_modules/react-native/Libraries/Geolocation/RCTGeolocation.xcodeproj; sourceTree = ""; }; 98 | 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTImage.xcodeproj; path = node_modules/react-native/Libraries/Image/RCTImage.xcodeproj; sourceTree = ""; }; 99 | 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTNetwork.xcodeproj; path = node_modules/react-native/Libraries/Network/RCTNetwork.xcodeproj; sourceTree = ""; }; 100 | 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTVibration.xcodeproj; path = node_modules/react-native/Libraries/Vibration/RCTVibration.xcodeproj; sourceTree = ""; }; 101 | 13B07F961A680F5B00A75B9A /* HtmlText.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HtmlText.app; sourceTree = BUILT_PRODUCTS_DIR; }; 102 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = iOS/AppDelegate.h; sourceTree = ""; }; 103 | 13B07FB01A68108700A75B9A /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = iOS/AppDelegate.m; sourceTree = ""; }; 104 | 13B07FB21A68108700A75B9A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 105 | 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = iOS/Images.xcassets; sourceTree = ""; }; 106 | 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = iOS/Info.plist; sourceTree = ""; }; 107 | 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = iOS/main.m; sourceTree = ""; }; 108 | 146833FF1AC3E56700842450 /* React.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = React.xcodeproj; path = node_modules/react-native/React/React.xcodeproj; sourceTree = ""; }; 109 | 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTText.xcodeproj; path = node_modules/react-native/Libraries/Text/RCTText.xcodeproj; sourceTree = ""; }; 110 | /* End PBXFileReference section */ 111 | 112 | /* Begin PBXFrameworksBuildPhase section */ 113 | 13B07F8C1A680F5B00A75B9A /* Frameworks */ = { 114 | isa = PBXFrameworksBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | 00481BEA1AC0C89D00671115 /* libicucore.dylib in Frameworks */, 118 | 146834051AC3E58100842450 /* libReact.a in Frameworks */, 119 | 00481BE81AC0C86700671115 /* libRCTWebSocketDebugger.a in Frameworks */, 120 | 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */, 121 | 00C302E61ABCBA2D00DB3ED1 /* libRCTAdSupport.a in Frameworks */, 122 | 00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */, 123 | 00C302E81ABCBA2D00DB3ED1 /* libRCTImage.a in Frameworks */, 124 | 00C302E91ABCBA2D00DB3ED1 /* libRCTNetwork.a in Frameworks */, 125 | 00C302EA1ABCBA2D00DB3ED1 /* libRCTVibration.a in Frameworks */, 126 | 832341BD1AAA6AB300B99B32 /* libRCTText.a in Frameworks */, 127 | ); 128 | runOnlyForDeploymentPostprocessing = 0; 129 | }; 130 | /* End PBXFrameworksBuildPhase section */ 131 | 132 | /* Begin PBXGroup section */ 133 | 00481BDC1AC0C7FA00671115 /* Products */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */, 137 | ); 138 | name = Products; 139 | sourceTree = ""; 140 | }; 141 | 00C302A81ABCB8CE00DB3ED1 /* Products */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */, 145 | ); 146 | name = Products; 147 | sourceTree = ""; 148 | }; 149 | 00C302B01ABCB8E700DB3ED1 /* Products */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | 00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */, 153 | ); 154 | name = Products; 155 | sourceTree = ""; 156 | }; 157 | 00C302B61ABCB90400DB3ED1 /* Products */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */, 161 | ); 162 | name = Products; 163 | sourceTree = ""; 164 | }; 165 | 00C302BC1ABCB91800DB3ED1 /* Products */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */, 169 | ); 170 | name = Products; 171 | sourceTree = ""; 172 | }; 173 | 00C302D41ABCB9D200DB3ED1 /* Products */ = { 174 | isa = PBXGroup; 175 | children = ( 176 | 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */, 177 | ); 178 | name = Products; 179 | sourceTree = ""; 180 | }; 181 | 00C302E01ABCB9EE00DB3ED1 /* Products */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */, 185 | ); 186 | name = Products; 187 | sourceTree = ""; 188 | }; 189 | 13B07FAE1A68108700A75B9A /* HtmlText */ = { 190 | isa = PBXGroup; 191 | children = ( 192 | 13B07FAF1A68108700A75B9A /* AppDelegate.h */, 193 | 13B07FB01A68108700A75B9A /* AppDelegate.m */, 194 | 13B07FB51A68108700A75B9A /* Images.xcassets */, 195 | 13B07FB61A68108700A75B9A /* Info.plist */, 196 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */, 197 | 13B07FB71A68108700A75B9A /* main.m */, 198 | ); 199 | name = HtmlText; 200 | sourceTree = ""; 201 | }; 202 | 146834001AC3E56700842450 /* Products */ = { 203 | isa = PBXGroup; 204 | children = ( 205 | 146834041AC3E56700842450 /* libReact.a */, 206 | ); 207 | name = Products; 208 | sourceTree = ""; 209 | }; 210 | 832341AE1AAA6A7D00B99B32 /* Libraries */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | 146833FF1AC3E56700842450 /* React.xcodeproj */, 214 | 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */, 215 | 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */, 216 | 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */, 217 | 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */, 218 | 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */, 219 | 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */, 220 | 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */, 221 | 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */, 222 | 00481BE91AC0C89D00671115 /* libicucore.dylib */, 223 | ); 224 | name = Libraries; 225 | sourceTree = ""; 226 | }; 227 | 832341B11AAA6A8300B99B32 /* Products */ = { 228 | isa = PBXGroup; 229 | children = ( 230 | 832341B51AAA6A8300B99B32 /* libRCTText.a */, 231 | ); 232 | name = Products; 233 | sourceTree = ""; 234 | }; 235 | 83CBB9F61A601CBA00E9B192 = { 236 | isa = PBXGroup; 237 | children = ( 238 | 13B07FAE1A68108700A75B9A /* HtmlText */, 239 | 832341AE1AAA6A7D00B99B32 /* Libraries */, 240 | 83CBBA001A601CBA00E9B192 /* Products */, 241 | ); 242 | sourceTree = ""; 243 | }; 244 | 83CBBA001A601CBA00E9B192 /* Products */ = { 245 | isa = PBXGroup; 246 | children = ( 247 | 13B07F961A680F5B00A75B9A /* HtmlText.app */, 248 | ); 249 | name = Products; 250 | sourceTree = ""; 251 | }; 252 | /* End PBXGroup section */ 253 | 254 | /* Begin PBXNativeTarget section */ 255 | 13B07F861A680F5B00A75B9A /* HtmlText */ = { 256 | isa = PBXNativeTarget; 257 | buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HtmlText" */; 258 | buildPhases = ( 259 | 13B07F871A680F5B00A75B9A /* Sources */, 260 | 13B07F8C1A680F5B00A75B9A /* Frameworks */, 261 | 13B07F8E1A680F5B00A75B9A /* Resources */, 262 | ); 263 | buildRules = ( 264 | ); 265 | dependencies = ( 266 | ); 267 | name = HtmlText; 268 | productName = "Hello World"; 269 | productReference = 13B07F961A680F5B00A75B9A /* HtmlText.app */; 270 | productType = "com.apple.product-type.application"; 271 | }; 272 | /* End PBXNativeTarget section */ 273 | 274 | /* Begin PBXProject section */ 275 | 83CBB9F71A601CBA00E9B192 /* Project object */ = { 276 | isa = PBXProject; 277 | attributes = { 278 | LastUpgradeCheck = 0610; 279 | ORGANIZATIONNAME = Facebook; 280 | }; 281 | buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HtmlText" */; 282 | compatibilityVersion = "Xcode 3.2"; 283 | developmentRegion = English; 284 | hasScannedForEncodings = 0; 285 | knownRegions = ( 286 | en, 287 | Base, 288 | ); 289 | mainGroup = 83CBB9F61A601CBA00E9B192; 290 | productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */; 291 | projectDirPath = ""; 292 | projectReferences = ( 293 | { 294 | ProductGroup = 00C302A81ABCB8CE00DB3ED1 /* Products */; 295 | ProjectRef = 00C302A71ABCB8CE00DB3ED1 /* RCTActionSheet.xcodeproj */; 296 | }, 297 | { 298 | ProductGroup = 00C302B01ABCB8E700DB3ED1 /* Products */; 299 | ProjectRef = 00C302AF1ABCB8E700DB3ED1 /* RCTAdSupport.xcodeproj */; 300 | }, 301 | { 302 | ProductGroup = 00C302B61ABCB90400DB3ED1 /* Products */; 303 | ProjectRef = 00C302B51ABCB90400DB3ED1 /* RCTGeolocation.xcodeproj */; 304 | }, 305 | { 306 | ProductGroup = 00C302BC1ABCB91800DB3ED1 /* Products */; 307 | ProjectRef = 00C302BB1ABCB91800DB3ED1 /* RCTImage.xcodeproj */; 308 | }, 309 | { 310 | ProductGroup = 00C302D41ABCB9D200DB3ED1 /* Products */; 311 | ProjectRef = 00C302D31ABCB9D200DB3ED1 /* RCTNetwork.xcodeproj */; 312 | }, 313 | { 314 | ProductGroup = 832341B11AAA6A8300B99B32 /* Products */; 315 | ProjectRef = 832341B01AAA6A8300B99B32 /* RCTText.xcodeproj */; 316 | }, 317 | { 318 | ProductGroup = 00C302E01ABCB9EE00DB3ED1 /* Products */; 319 | ProjectRef = 00C302DF1ABCB9EE00DB3ED1 /* RCTVibration.xcodeproj */; 320 | }, 321 | { 322 | ProductGroup = 00481BDC1AC0C7FA00671115 /* Products */; 323 | ProjectRef = 00481BDB1AC0C7FA00671115 /* RCTWebSocketDebugger.xcodeproj */; 324 | }, 325 | { 326 | ProductGroup = 146834001AC3E56700842450 /* Products */; 327 | ProjectRef = 146833FF1AC3E56700842450 /* React.xcodeproj */; 328 | }, 329 | ); 330 | projectRoot = ""; 331 | targets = ( 332 | 13B07F861A680F5B00A75B9A /* HtmlText */, 333 | ); 334 | }; 335 | /* End PBXProject section */ 336 | 337 | /* Begin PBXReferenceProxy section */ 338 | 00481BE61AC0C7FA00671115 /* libRCTWebSocketDebugger.a */ = { 339 | isa = PBXReferenceProxy; 340 | fileType = archive.ar; 341 | path = libRCTWebSocketDebugger.a; 342 | remoteRef = 00481BE51AC0C7FA00671115 /* PBXContainerItemProxy */; 343 | sourceTree = BUILT_PRODUCTS_DIR; 344 | }; 345 | 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */ = { 346 | isa = PBXReferenceProxy; 347 | fileType = archive.ar; 348 | path = libRCTActionSheet.a; 349 | remoteRef = 00C302AB1ABCB8CE00DB3ED1 /* PBXContainerItemProxy */; 350 | sourceTree = BUILT_PRODUCTS_DIR; 351 | }; 352 | 00C302B41ABCB8E700DB3ED1 /* libRCTAdSupport.a */ = { 353 | isa = PBXReferenceProxy; 354 | fileType = archive.ar; 355 | path = libRCTAdSupport.a; 356 | remoteRef = 00C302B31ABCB8E700DB3ED1 /* PBXContainerItemProxy */; 357 | sourceTree = BUILT_PRODUCTS_DIR; 358 | }; 359 | 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */ = { 360 | isa = PBXReferenceProxy; 361 | fileType = archive.ar; 362 | path = libRCTGeolocation.a; 363 | remoteRef = 00C302B91ABCB90400DB3ED1 /* PBXContainerItemProxy */; 364 | sourceTree = BUILT_PRODUCTS_DIR; 365 | }; 366 | 00C302C01ABCB91800DB3ED1 /* libRCTImage.a */ = { 367 | isa = PBXReferenceProxy; 368 | fileType = archive.ar; 369 | path = libRCTImage.a; 370 | remoteRef = 00C302BF1ABCB91800DB3ED1 /* PBXContainerItemProxy */; 371 | sourceTree = BUILT_PRODUCTS_DIR; 372 | }; 373 | 00C302DC1ABCB9D200DB3ED1 /* libRCTNetwork.a */ = { 374 | isa = PBXReferenceProxy; 375 | fileType = archive.ar; 376 | path = libRCTNetwork.a; 377 | remoteRef = 00C302DB1ABCB9D200DB3ED1 /* PBXContainerItemProxy */; 378 | sourceTree = BUILT_PRODUCTS_DIR; 379 | }; 380 | 00C302E41ABCB9EE00DB3ED1 /* libRCTVibration.a */ = { 381 | isa = PBXReferenceProxy; 382 | fileType = archive.ar; 383 | path = libRCTVibration.a; 384 | remoteRef = 00C302E31ABCB9EE00DB3ED1 /* PBXContainerItemProxy */; 385 | sourceTree = BUILT_PRODUCTS_DIR; 386 | }; 387 | 146834041AC3E56700842450 /* libReact.a */ = { 388 | isa = PBXReferenceProxy; 389 | fileType = archive.ar; 390 | path = libReact.a; 391 | remoteRef = 146834031AC3E56700842450 /* PBXContainerItemProxy */; 392 | sourceTree = BUILT_PRODUCTS_DIR; 393 | }; 394 | 832341B51AAA6A8300B99B32 /* libRCTText.a */ = { 395 | isa = PBXReferenceProxy; 396 | fileType = archive.ar; 397 | path = libRCTText.a; 398 | remoteRef = 832341B41AAA6A8300B99B32 /* PBXContainerItemProxy */; 399 | sourceTree = BUILT_PRODUCTS_DIR; 400 | }; 401 | /* End PBXReferenceProxy section */ 402 | 403 | /* Begin PBXResourcesBuildPhase section */ 404 | 13B07F8E1A680F5B00A75B9A /* Resources */ = { 405 | isa = PBXResourcesBuildPhase; 406 | buildActionMask = 2147483647; 407 | files = ( 408 | 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, 409 | 13B07FBD1A68108700A75B9A /* LaunchScreen.xib in Resources */, 410 | ); 411 | runOnlyForDeploymentPostprocessing = 0; 412 | }; 413 | /* End PBXResourcesBuildPhase section */ 414 | 415 | /* Begin PBXSourcesBuildPhase section */ 416 | 13B07F871A680F5B00A75B9A /* Sources */ = { 417 | isa = PBXSourcesBuildPhase; 418 | buildActionMask = 2147483647; 419 | files = ( 420 | 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */, 421 | 13B07FC11A68108700A75B9A /* main.m in Sources */, 422 | ); 423 | runOnlyForDeploymentPostprocessing = 0; 424 | }; 425 | /* End PBXSourcesBuildPhase section */ 426 | 427 | /* Begin PBXVariantGroup section */ 428 | 13B07FB11A68108700A75B9A /* LaunchScreen.xib */ = { 429 | isa = PBXVariantGroup; 430 | children = ( 431 | 13B07FB21A68108700A75B9A /* Base */, 432 | ); 433 | name = LaunchScreen.xib; 434 | path = iOS; 435 | sourceTree = ""; 436 | }; 437 | /* End PBXVariantGroup section */ 438 | 439 | /* Begin XCBuildConfiguration section */ 440 | 13B07F941A680F5B00A75B9A /* Debug */ = { 441 | isa = XCBuildConfiguration; 442 | buildSettings = { 443 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 444 | HEADER_SEARCH_PATHS = ( 445 | "$(inherited)", 446 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 447 | "$(SRCROOT)/node_modules/react-native/React/**", 448 | ); 449 | INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; 450 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 451 | OTHER_LDFLAGS = "-ObjC"; 452 | PRODUCT_NAME = HtmlText; 453 | }; 454 | name = Debug; 455 | }; 456 | 13B07F951A680F5B00A75B9A /* Release */ = { 457 | isa = XCBuildConfiguration; 458 | buildSettings = { 459 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 460 | HEADER_SEARCH_PATHS = ( 461 | "$(inherited)", 462 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 463 | "$(SRCROOT)/node_modules/react-native/React/**", 464 | ); 465 | INFOPLIST_FILE = "$(SRCROOT)/iOS/Info.plist"; 466 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 467 | OTHER_LDFLAGS = "-ObjC"; 468 | PRODUCT_NAME = HtmlText; 469 | }; 470 | name = Release; 471 | }; 472 | 83CBBA201A601CBA00E9B192 /* Debug */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | ALWAYS_SEARCH_USER_PATHS = NO; 476 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 477 | CLANG_CXX_LIBRARY = "libc++"; 478 | CLANG_ENABLE_MODULES = YES; 479 | CLANG_ENABLE_OBJC_ARC = YES; 480 | CLANG_WARN_BOOL_CONVERSION = YES; 481 | CLANG_WARN_CONSTANT_CONVERSION = YES; 482 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 483 | CLANG_WARN_EMPTY_BODY = YES; 484 | CLANG_WARN_ENUM_CONVERSION = YES; 485 | CLANG_WARN_INT_CONVERSION = YES; 486 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 487 | CLANG_WARN_UNREACHABLE_CODE = YES; 488 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 489 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 490 | COPY_PHASE_STRIP = NO; 491 | ENABLE_STRICT_OBJC_MSGSEND = YES; 492 | GCC_C_LANGUAGE_STANDARD = gnu99; 493 | GCC_DYNAMIC_NO_PIC = NO; 494 | GCC_OPTIMIZATION_LEVEL = 0; 495 | GCC_PREPROCESSOR_DEFINITIONS = ( 496 | "DEBUG=1", 497 | "$(inherited)", 498 | ); 499 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 500 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 501 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 502 | GCC_WARN_UNDECLARED_SELECTOR = YES; 503 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 504 | GCC_WARN_UNUSED_FUNCTION = YES; 505 | GCC_WARN_UNUSED_VARIABLE = YES; 506 | HEADER_SEARCH_PATHS = ( 507 | "$(inherited)", 508 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 509 | "$(SRCROOT)/node_modules/react-native/React/**", 510 | ); 511 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 512 | MTL_ENABLE_DEBUG_INFO = YES; 513 | ONLY_ACTIVE_ARCH = YES; 514 | SDKROOT = iphoneos; 515 | }; 516 | name = Debug; 517 | }; 518 | 83CBBA211A601CBA00E9B192 /* Release */ = { 519 | isa = XCBuildConfiguration; 520 | buildSettings = { 521 | ALWAYS_SEARCH_USER_PATHS = NO; 522 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 523 | CLANG_CXX_LIBRARY = "libc++"; 524 | CLANG_ENABLE_MODULES = YES; 525 | CLANG_ENABLE_OBJC_ARC = YES; 526 | CLANG_WARN_BOOL_CONVERSION = YES; 527 | CLANG_WARN_CONSTANT_CONVERSION = YES; 528 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 529 | CLANG_WARN_EMPTY_BODY = YES; 530 | CLANG_WARN_ENUM_CONVERSION = YES; 531 | CLANG_WARN_INT_CONVERSION = YES; 532 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 533 | CLANG_WARN_UNREACHABLE_CODE = YES; 534 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 535 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 536 | COPY_PHASE_STRIP = YES; 537 | ENABLE_NS_ASSERTIONS = NO; 538 | ENABLE_STRICT_OBJC_MSGSEND = YES; 539 | GCC_C_LANGUAGE_STANDARD = gnu99; 540 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 541 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 542 | GCC_WARN_UNDECLARED_SELECTOR = YES; 543 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 544 | GCC_WARN_UNUSED_FUNCTION = YES; 545 | GCC_WARN_UNUSED_VARIABLE = YES; 546 | HEADER_SEARCH_PATHS = ( 547 | "$(inherited)", 548 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 549 | "$(SRCROOT)/node_modules/react-native/React/**", 550 | ); 551 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 552 | MTL_ENABLE_DEBUG_INFO = NO; 553 | SDKROOT = iphoneos; 554 | VALIDATE_PRODUCT = YES; 555 | }; 556 | name = Release; 557 | }; 558 | /* End XCBuildConfiguration section */ 559 | 560 | /* Begin XCConfigurationList section */ 561 | 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "HtmlText" */ = { 562 | isa = XCConfigurationList; 563 | buildConfigurations = ( 564 | 13B07F941A680F5B00A75B9A /* Debug */, 565 | 13B07F951A680F5B00A75B9A /* Release */, 566 | ); 567 | defaultConfigurationIsVisible = 0; 568 | defaultConfigurationName = Release; 569 | }; 570 | 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "HtmlText" */ = { 571 | isa = XCConfigurationList; 572 | buildConfigurations = ( 573 | 83CBBA201A601CBA00E9B192 /* Debug */, 574 | 83CBBA211A601CBA00E9B192 /* Release */, 575 | ); 576 | defaultConfigurationIsVisible = 0; 577 | defaultConfigurationName = Release; 578 | }; 579 | /* End XCConfigurationList section */ 580 | }; 581 | rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */; 582 | } 583 | -------------------------------------------------------------------------------- /HtmlText.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HtmlText.xcodeproj/project.xcworkspace/xcshareddata/HtmlText.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 4EA40225-03B9-4990-891F-0285646A2873 9 | IDESourceControlProjectName 10 | HtmlText 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 39B0080154FFACEE647E0D8139A0CE48049FF597 14 | git.ignition.hk:francis/HtmlText.git 15 | 16 | IDESourceControlProjectPath 17 | HtmlText.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 39B0080154FFACEE647E0D8139A0CE48049FF597 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | git.ignition.hk:francis/HtmlText.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 39B0080154FFACEE647E0D8139A0CE48049FF597 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 39B0080154FFACEE647E0D8139A0CE48049FF597 36 | IDESourceControlWCCName 37 | HtmlText 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /HtmlText.xcodeproj/project.xcworkspace/xcuserdata/siuying.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siuying/react-native-htmltext/173e2f33a2fb6ae124f4a4168071fc108d9c8d9f/HtmlText.xcodeproj/project.xcworkspace/xcuserdata/siuying.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HtmlText.xcodeproj/xcshareddata/xcschemes/HtmlText.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /HtmlText.xcodeproj/xcuserdata/siuying.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HtmlText.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 13B07F861A680F5B00A75B9A 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-native-htmltext 2 | 3 | WIP: Experiment to use HTML like markup to create stylized text in react-native. 4 | 5 | ## Why? 6 | 7 | React Native provide a Text element for stylized text. Instead of using ``NSAttributedString``, 8 | you creat nested Text: 9 | 10 | ``` 11 | 12 | I am bold 13 | and red 14 | 15 | ``` 16 | 17 | While this approach is excellent for static interface text, what if we have dynamic text with format we 18 | do not know until we use it? ``HtmlText`` is a component to present a limited subset of HTML as 19 | React Native views. 20 | 21 | **Important**: This is not going to replace your ``WebView`` for HTML rendering, instead it use a 22 | limited subset of HTML and try to present it using native ``Text`` elements in a reasonable way. 23 | 24 | ## Example 25 | 26 | ### Input 27 | 28 | ```javascript 29 | render: function() { 30 | var html = `

Hello world world foo bar hahh

` 31 | return ( 32 | 33 | 34 | 35 | ); 36 | } 37 | ``` 38 | 39 | 40 | ### Input 41 | 42 | ```javascript 43 | render: function() { 44 | var html = `

Hello world world foo

bar hahh

` 45 | return ( 46 | 47 | 48 | 49 | ); 50 | } 51 | ``` 52 | 53 | 54 | -------------------------------------------------------------------------------- /example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siuying/react-native-htmltext/173e2f33a2fb6ae124f4a4168071fc108d9c8d9f/example1.png -------------------------------------------------------------------------------- /example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/siuying/react-native-htmltext/173e2f33a2fb6ae124f4a4168071fc108d9c8d9f/example2.png -------------------------------------------------------------------------------- /iOS/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (nonatomic, strong) UIWindow *window; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /iOS/AppDelegate.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import "AppDelegate.h" 11 | 12 | #import "RCTRootView.h" 13 | 14 | @implementation AppDelegate 15 | 16 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 17 | { 18 | NSURL *jsCodeLocation; 19 | 20 | // Loading JavaScript code - uncomment the one you want. 21 | 22 | // OPTION 1 23 | // Load from development server. Start the server from the repository root: 24 | // 25 | // $ npm start 26 | // 27 | // To run on device, change `localhost` to the IP address of your computer, and make sure your computer and 28 | // iOS device are on the same Wi-Fi network. 29 | jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle"]; 30 | 31 | // OPTION 2 32 | // Load from pre-bundled file on disk. To re-generate the static bundle, run 33 | // 34 | // $ curl http://localhost:8081/index.ios.bundle -o main.jsbundle 35 | // 36 | // and uncomment the next following line 37 | // jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 38 | 39 | RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation 40 | moduleName:@"HtmlTextApp" 41 | launchOptions:launchOptions]; 42 | 43 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 44 | UIViewController *rootViewController = [[UIViewController alloc] init]; 45 | rootViewController.view = rootView; 46 | self.window.rootViewController = rootViewController; 47 | [self.window makeKeyAndVisible]; 48 | return YES; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /iOS/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /iOS/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UIViewControllerBasedStatusBarAppearance 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /iOS/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | #import 11 | 12 | #import "AppDelegate.h" 13 | 14 | int main(int argc, char * argv[]) { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /index.ios.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Sample React Native App 3 | * https://github.com/facebook/react-native 4 | */ 5 | 'use strict'; 6 | 7 | var React = require('react-native'); 8 | var { 9 | AppRegistry, 10 | StyleSheet, 11 | Text, 12 | View, 13 | } = React; 14 | var HtmlText = require('./lib/HtmlText') 15 | 16 | var HtmlTextApp = React.createClass({ 17 | render: function() { 18 | var html = `

Hello world world foo bar hahh

` 19 | 20 | return ( 21 | 22 | 23 | 24 | ); 25 | } 26 | }); 27 | 28 | var styles = StyleSheet.create({ 29 | container: { 30 | flex: 1, 31 | justifyContent: 'center', 32 | alignItems: 'stretch', 33 | backgroundColor: '#ffffff', 34 | margin: 10, 35 | 36 | }, 37 | welcome: { 38 | } 39 | }); 40 | 41 | AppRegistry.registerComponent('HtmlTextApp', () => HtmlTextApp); 42 | -------------------------------------------------------------------------------- /lib/HtmlText.js: -------------------------------------------------------------------------------- 1 | var parse5 = require('parse5'); 2 | var React = require('react-native') 3 | var { 4 | AppRegistry, 5 | StyleSheet, 6 | Text, 7 | View, 8 | } = React 9 | 10 | var BLOCK_ELEMENTS = ["blockquote", "div", "h1", "h2", "h3", "h4", "h5", "h6", "hr", "ol", "p", "pre", "ul", "li"] 11 | 12 | var INLINE_ELEMENTS = ["b", "i", "em", "strong", "a", "br", "q", "span", "sub", "sup"] 13 | 14 | var DEFAULT_STYLES = StyleSheet.create({ 15 | a: { 16 | 17 | }, 18 | b: { 19 | fontWeight: 'bold' 20 | }, 21 | blockquote: { 22 | paddingLeft: 12, 23 | borderLeftWidth: 4, 24 | borderLeftColor: '#cccccc', 25 | marginBottom: 12 26 | }, 27 | br: { 28 | 29 | }, 30 | div: { 31 | 32 | }, 33 | em: { 34 | fontStyle: 'italic' 35 | }, 36 | h1: { 37 | fontWeight: 'bold', 38 | }, 39 | h2: { 40 | fontWeight: 'bold', 41 | }, 42 | h3: { 43 | fontWeight: 'bold', 44 | }, 45 | h4: { 46 | fontWeight: 'bold', 47 | }, 48 | h5: { 49 | fontWeight: 'bold', 50 | }, 51 | h6: { 52 | fontWeight: 'bold', 53 | }, 54 | i: { 55 | fontStyle: 'italic' 56 | }, 57 | p: { 58 | marginBottom: 12, 59 | }, 60 | pre: { 61 | 62 | }, 63 | strong: { 64 | fontWeight: 'bold' 65 | }, 66 | q: { 67 | 68 | }, 69 | span: { 70 | 71 | }, 72 | sub: { 73 | 74 | }, 75 | sup: { 76 | 77 | }, 78 | ol:{ 79 | marginLeft: 24, 80 | }, 81 | ul: { 82 | marginLeft: 24, 83 | }, 84 | default: { 85 | 86 | } 87 | }); 88 | 89 | function isText(tagName) : Boolean { 90 | return tagName === "#text" 91 | } 92 | 93 | function isBlockElement(tagName) : Boolean { 94 | return BLOCK_ELEMENTS.indexOf(tagName) != -1 95 | } 96 | 97 | function isInlineElement(tagName) : Boolean { 98 | return INLINE_ELEMENTS.indexOf(tagName) != -1 99 | } 100 | 101 | function styleForTag(tagName) { 102 | var style = DEFAULT_STYLES[tagName] ? DEFAULT_STYLES[tagName] : DEFAULT_STYLES["default"] 103 | return style 104 | } 105 | 106 | function processNode(node, parentKey) { 107 | var nodeName = node.nodeName 108 | 109 | if (isText(nodeName)) { 110 | var key = `${parentKey}_text` 111 | return ({node.value}) 112 | } 113 | 114 | if (isInlineElement(nodeName)) { 115 | var key = `${parentKey}_${nodeName}` 116 | var children = [] 117 | node.childNodes.forEach((child, index) => { 118 | if (isInlineElement(child.nodeName) || isText(child.nodeName)) { 119 | children.push(processNode(child, `${key}_${index}`)) 120 | } else { 121 | console.error(`Inline element ${nodeName} can only have inline children, ${child} is invalid!`) 122 | } 123 | }) 124 | return ({children}) 125 | } 126 | 127 | if (isBlockElement(nodeName)) { 128 | var key = `${parentKey}_${nodeName}` 129 | var children = [] 130 | var lastInlineNodes = [] 131 | 132 | node.childNodes.forEach((childNode, index) => { 133 | var child = processNode(childNode, `${key}_${index}`) 134 | if (isInlineElement(childNode.nodeName) || isText(childNode.nodeName)) { 135 | lastInlineNodes.push(child) 136 | 137 | } else if (isBlockElement(childNode.nodeName)) { 138 | if (lastInlineNodes.length > 0) { 139 | children.push({lastInlineNodes}) 140 | lastInlineNodes = [] 141 | } 142 | children.push(child) 143 | } 144 | }) 145 | 146 | if (lastInlineNodes.length > 0) { 147 | children.push(({lastInlineNodes})) 148 | } 149 | return ( 150 | 151 | {children} 152 | 153 | ) 154 | } 155 | 156 | console.warn(`unsupported node: ${nodeName}`) 157 | return null; 158 | } 159 | 160 | class HtmlText extends React.Component { 161 | parse(html) { 162 | var parser = new parse5.Parser() 163 | var fragment = parser.parseFragment(html) 164 | return fragment 165 | } 166 | 167 | 168 | render() { 169 | var html = this.props.html 170 | var fragment = this.parse(html) 171 | var rootKey = "ht_" 172 | 173 | var children = [] 174 | fragment.childNodes.forEach((node, index) => { 175 | children.push(processNode(node, `${rootKey}_${index}`)) 176 | }) 177 | 178 | console.log(children) 179 | return ( 180 | 181 | {children} 182 | 183 | ) 184 | } 185 | } 186 | 187 | module.exports = HtmlText -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-htmltext", 3 | "version": "0.0.1", 4 | "description": "Use HTML like markup to create stylized text in react-native.", 5 | "private": true, 6 | "scripts": { 7 | "start": "react-native start" 8 | }, 9 | "main": "lib/HtmlText.js", 10 | "dependencies": { 11 | "parse5": "^1.4.1", 12 | "react-native": "git://github.com/facebook/react-native.git" 13 | } 14 | } 15 | --------------------------------------------------------------------------------