())
override init (){
super.init()
self.dataArray.append(MainCellViewModel(
title: "一个简单的登陆页面",
subTitle: "UIScrollView的使用Demo",
srcUrl: "http://d.hiphotos.baidu.com/zhidao/pic/item/562c11dfa9ec8a13e028c4c0f603918fa0ecc0e4.jpg",
link:"demo://login"))
self.dataArray.append(MainCellViewModel(
title: "还是登陆界面不过是加密版本",
subTitle: "UIScrollView的使用Demo",
srcUrl: "http://d.hiphotos.baidu.com/zhidao/pic/item/562c11dfa9ec8a13e028c4c0f603918fa0ecc0e4.jpg",
link:"demo://encodelogin"))
self.dataArray.append(MainCellViewModel(
title: "Collection+网络请求+下拉控件",
subTitle: "UICollectionView的使用Demo,包含了网络请求",
srcUrl: "http://d.hiphotos.baidu.com/zhidao/pic/item/562c11dfa9ec8a13e028c4c0f603918fa0ecc0e4.jpg",
link:"demo://collection"))
self.dataArray.append(MainCellViewModel(
title: "HTML版的Label,采用TTTAttributeLabel",
subTitle: "Hello World!
",
srcUrl: "http://d.hiphotos.baidu.com/zhidao/pic/item/562c11dfa9ec8a13e028c4c0f603918fa0ecc0e4.jpg",
link:"demo://LabelScene"))
self.dataArray.append(MainCellViewModel(
title: "native版本的flex模型演示",
subTitle: "native版本的flex模型演示",
srcUrl: "http://d.hiphotos.baidu.com/zhidao/pic/item/562c11dfa9ec8a13e028c4c0f603918fa0ecc0e4.jpg",
link:"demo://flex"))
self.dataArray.append(MainCellViewModel(
title: "xml版本的flex模型演示",
subTitle: "xml版本的flex模型演示",
srcUrl: "http://d.hiphotos.baidu.com/zhidao/pic/item/562c11dfa9ec8a13e028c4c0f603918fa0ecc0e4.jpg",
link:"demo://flexml"))
self.sectionArray.append(MainSectionViewModel(
title: "section 1"))
self.sectionArray.append(MainSectionViewModel(
title: "section 2"))
self.sectionArray.append(MainSectionViewModel(
title: "section 3"))
}
}
================================================
FILE: Demo/Demo/url.plist
================================================
demo
demo://flexml
FlexXmlScene
demo://flex
FlexScene
demo://encodelogin
EncodeLoginScene
demo://collection
CollectionScene
demo://login
LoginScene
================================================
FILE: Demo/Demo/xml.bundle/CollectionScene.xml
================================================
================================================
FILE: Demo/Demo/xml.bundle/EncodeLoginScene.crypto
================================================
VTWWEpHde9NHKxqWASruTqqmlAB2w6yrgF3k4/6aH5xLCWW09IBo0wCd/XDQTXFG
H/fTwKRPrtiF85H9augC+XEcQ2BavK7sIbi99qwL0TaJOnmMoEt8n65i/BpOuCXe
U/uYXAQTOc8L43XQMRQ5o6bd0928uEK8tm/khgYB7ho2nc/LnSyk387N+7fVWasI
7ygbDY1yzWsbLYXdBju9fKvku6rqyRFUTLR3Y0LyyhNaqcK3QWkPGf0C1SpEvZN5
f/XX8+YL0sf/bMngbrOaNKQtZVQJfxJUSP4BUOHXql9Bca7o1hGERQ2JJRhBtfis
o/YWFO58QO16gHRrkqmXzHndkOknrBB0lalewwMathppGCUztFS3+D4c4Bxb8kzD
eBHwU/e5V/NWTKbje0EpX2aTLl1jHarGLqsybsEb2xACBoumJrdcATPdnXl/Ouou
NiKoS2h8muGLO46oFyusalX+/1o7wIQDG3rwhwsMKpZvTatpaAhRJlvY5/yHUDUN
iLTu0JO73PctuRI8nTpx6D9+nlw2zo/OmsuvvxldLmv9FhAs5XvcJnrnMr4z6S8o
4ohBH79i9UJfDaYxAaofMrI5szIYu3DG4qCM8NyNFQc7YoeKN1wQjat41Wenxx5B
RrtMke5dKlE0ATstakRmdNa4zqzPFkhxtVPuK4gVn7n5EPUDaz/flC3VA4zxxD7k
uo0FfD4uEREvM9UcKIXuaV+8Riu26ly2khMbPznGkKxTVeu2SWecu/HHQRPANz5S
ueyPZvELpAbiR7usH4IY37IUWz2vteVOYmwHPV+09E74YfRsoHtOEO8r4YAi+OyO
ZsXa2wn5+TSUFODny6k7y7XWpp4XIcQBDW+08lg+eLuXfoEUttw/JzqSgxxcs/F+
R9tbVIW0MAVXThjVcaD3IHnvRYeZsdj3JUDpeGOv9WbIqcYz0Fgwkg7Lav4QOy+U
SNPXnuCDw7OhsCfbifmxTCTuDPZ6HjGtFauiGEN83EpJzQGAYEktvyyEXhhS8LKk
eL/JRag25fR0VLQPCNk/5e2SP/dOI7ReR5y4l9NR5oFteKDuQytUrDiHm9f6Bn+T
MMuK4jhQ3QpmuaT1Ps8jSW3hnK6zUXStFmOgRzmDTQnGqkzHybo9W9Ewj9nWINEO
PIz/wPpVO4ok7PuxP+sLo6xdUCY6oZFhRCU4k03SQhyk6jari2PxHD4DuiyjcLLU
IW+dFxscF5dhPi0TTdSZfrD6T53NsHeLDXBECmabKT+mugc2IsV+GG9N3rhwXhyO
4mduo2v0XsNLaYAqJdZue6zcw/o40mWoPCpK37ZfSeaABEey5UUVlc+fJR6+ct20
wRlvazYrOqWKW8C5I/ZXD/ei0v7hB+KB87Q40RBEJ27uDH8mITgWqg/pwMqBAs30
7+5lrddB79wuRRHIbE907uad8seRXT8CA0QBpSER9aXfet5SK6YkhP6Ve/p7OIt5
Ym4ZhtR377+YV3dLh08xNlFJ4Fd8iE/NSvRFoVFUb0s5DPQaUL42Sd2hH3WFz3U4
W2dMZ4Cnj89i56XNnA+Gwe+eaqrQmHpLVIeAfTlnmXjUWaOFHj6Xg91drLPPyFTH
64olhQImSa6xGN3wVdDDUEN6Oz3D2YBI5gV7YQVQkMZyqV7fgjUwY7uDCStgvHDc
b64/PrtWlDCqGN79ncTKomuHhUszIhnrRxspp4u5dPim2nd45/34LEvVMF7+exZ5
RUXRKIlg4wXznUhmuAwjCuRgH88dk3UWbIfYFt52sOC1rTm5mMNcF15jRgvxZHua
89/jcEJoTfelbMTqgoJoNQ7ZiOldxHyseqxjVHaZg/yVUgWaK+yl9n/8vXC+eGsn
Bm86QHd3JCwlaKoW8hvo2R7ntnLlyp6to+gzq//o3h/wzoQJehkubFyYug7cq1xd
7pMf/OFSiTulbDK8NzGqU+JN1EHalRgoNLZMKsrHgwlW0CVDDq1TO2WLjrk+cZXB
jBbiQqW35gUK81vkqFm01BFUd/vWWG1X+cGfRgLPcMNYNHUdkYhR2MXE13o+yVUf
chDkfRgiif68lYAoP74njGQcXwAugTB9bkQIYyQCuMIxaT1W+rgieCX4ieqaa+hw
HmSd9D96UVPbhhISqZINkbmzoKsEA+iD4qqWl9/L7Kt9QESiTnRZvQW9Pi3hkEcU
d79thZ8DwCkS/1KeFJonFxe59adBZyL5d6ttXDoTBNfGrfVNEntzkj/fmTWpNYpx
LuDrc92OEylJs7Z0Utz3XX9dGU24qBCfQeEVoAK78eggtBwFxRgJmZ9f8acBI5tP
ezLDkl9eioV0hoSI1Pgfdgc38QzNJJIG98zh4mPeOmOB/aumVW1iT/cZpEPK09XH
n7vAcQxhQL6ksZdKXSqEXcDQPgrUro19qqW6fwCZcNvuvZQOA9PKmg==
================================================
FILE: Demo/Demo/xml.bundle/FlexXmlScene.xml
================================================
================================================
FILE: Demo/Demo/xml.bundle/LabelHtml.xml
================================================
EasyIOS For Swift
Star is the Best Way to Support EasyIOS !
Features
- MVVM :
Model-View-ViewModel inspired by Functional Reactive Programming
- HTML To Native : Transform HTML&CSS to Native Control,
- Reflect Cocoa Touch : Reflect all the Cocoa Touch Api ,we can use the Cocoa Touch Api via HTML
- AutoLayout : The HTML layout based on the
AutoLayout
- Live Load : Edit the HTML and the view in smulator will update automaticly without rebuild your app
- Cryptographic HTML : To make the HTML be safety,we provide the
AES Encryption to encrypt the HTML
- URLManager : Push or Present the Controller by the custom URL
- Elegant PullToRefresh : Add PullToRefresh or InfiniteScrolling by HTML
Usage
To run the example project, clone the repo, and run pod install from the Demo directory first.
Requirements
Author
zhuchao, zhuchao@iosx.me
License
EasyIOS-Swift is available under the MIT license. See the LICENSE file for more info.
================================================
FILE: Demo/Demo/xml.bundle/LabelScene.xml
================================================
================================================
FILE: Demo/Demo/xml.bundle/LoginScene.xml
================================================
================================================
FILE: Demo/Demo/xml.bundle/MainScene.xml
================================================
{{title}}
{{subTitle}}
{{title}}
================================================
FILE: Demo/Demo.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
5B3FCA9A1BCDF6AB00AF20CD /* FlexScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B3FCA991BCDF6AB00AF20CD /* FlexScene.swift */; settings = {ASSET_TAGS = (); }; };
5B4C52211BCE2E91003E0016 /* FlexXmlScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B4C52201BCE2E91003E0016 /* FlexXmlScene.swift */; settings = {ASSET_TAGS = (); }; };
5B4C52291BCE547A003E0016 /* Chinese.md in Sources */ = {isa = PBXBuildFile; fileRef = 5B4C52271BCE547A003E0016 /* Chinese.md */; settings = {ASSET_TAGS = (); }; };
5B4C522A1BCE547A003E0016 /* flexbox.png in Resources */ = {isa = PBXBuildFile; fileRef = 5B4C52281BCE547A003E0016 /* flexbox.png */; settings = {ASSET_TAGS = (); }; };
5B6512B11B141A9E00B1BA89 /* EncodeLoginScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6512B01B141A9E00B1BA89 /* EncodeLoginScene.swift */; };
5B7B80C51B08D8E00059CAEF /* MainLabelDeleage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B7B80C41B08D8E00059CAEF /* MainLabelDeleage.swift */; };
5B7B80DB1B0A0B2A0059CAEF /* LabelScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B7B80DA1B0A0B2A0059CAEF /* LabelScene.swift */; };
5B8240C01B03715600D58574 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8240BF1B03715600D58574 /* AppDelegate.swift */; };
5B8240C21B03715600D58574 /* LoginScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8240C11B03715600D58574 /* LoginScene.swift */; };
5B8240C71B03715600D58574 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5B8240C61B03715600D58574 /* Images.xcassets */; };
5B8240CA1B03715600D58574 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5B8240C81B03715600D58574 /* LaunchScreen.xib */; };
5B8240D61B03715600D58574 /* DemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B8240D51B03715600D58574 /* DemoTests.swift */; };
5B8240E91B0377FC00D58574 /* EasyIOS-Swift.podspec in Resources */ = {isa = PBXBuildFile; fileRef = 5B8240E61B0377FC00D58574 /* EasyIOS-Swift.podspec */; };
5B8240EA1B0377FC00D58574 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 5B8240E71B0377FC00D58574 /* LICENSE */; };
5B8240EB1B0377FC00D58574 /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = 5B8240E81B0377FC00D58574 /* README.md */; };
5B90B5CD1B04BFF8000C848D /* FeedRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B90B5CC1B04BFF8000C848D /* FeedRequest.swift */; };
5BBC33DA1BB3DFE00030B054 /* xml.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 5BBC33D91BB3DFE00030B054 /* xml.bundle */; settings = {ASSET_TAGS = (); }; };
5BDBF0CE1B038B7300E95ACF /* login-logo@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 5BDBF0CD1B038B7300E95ACF /* login-logo@2x.png */; };
5BDBF0D01B038C1700E95ACF /* MainScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDBF0CF1B038C1700E95ACF /* MainScene.swift */; };
5BDBF0D51B038C7800E95ACF /* MainSceneModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDBF0D41B038C7800E95ACF /* MainSceneModel.swift */; };
5BDBF0D91B038F0D00E95ACF /* url.plist in Resources */ = {isa = PBXBuildFile; fileRef = 5BDBF0D81B038F0D00E95ACF /* url.plist */; };
5BDC06BB1B0394C200C486E0 /* CollectionScene.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC06BA1B0394C200C486E0 /* CollectionScene.swift */; };
5BDC06BD1B03950500C486E0 /* CollectionSceneModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC06BC1B03950500C486E0 /* CollectionSceneModel.swift */; };
5BDC06BF1B03955A00C486E0 /* CollectionCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5BDC06BE1B03955A00C486E0 /* CollectionCellViewModel.swift */; };
87D67298D115B9D5014DB706 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 55CB89BDD03972BB5036E6DF /* Pods.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
5B8240D01B03715600D58574 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 5B8240B21B03715600D58574 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 5B8240B91B03715600D58574;
remoteInfo = Demo;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
0BAFEE4C5E077414790C2042 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; };
55CB89BDD03972BB5036E6DF /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
5B3FCA991BCDF6AB00AF20CD /* FlexScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlexScene.swift; sourceTree = ""; };
5B4C52201BCE2E91003E0016 /* FlexXmlScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlexXmlScene.swift; sourceTree = ""; };
5B4C52271BCE547A003E0016 /* Chinese.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = Chinese.md; sourceTree = ""; };
5B4C52281BCE547A003E0016 /* flexbox.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flexbox.png; sourceTree = ""; };
5B6512B01B141A9E00B1BA89 /* EncodeLoginScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EncodeLoginScene.swift; sourceTree = ""; };
5B7B80C41B08D8E00059CAEF /* MainLabelDeleage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainLabelDeleage.swift; sourceTree = ""; };
5B7B80DA1B0A0B2A0059CAEF /* LabelScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelScene.swift; sourceTree = ""; };
5B8240BA1B03715600D58574 /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; };
5B8240BE1B03715600D58574 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
5B8240BF1B03715600D58574 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
5B8240C11B03715600D58574 /* LoginScene.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginScene.swift; sourceTree = ""; };
5B8240C61B03715600D58574 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
5B8240C91B03715600D58574 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
5B8240CF1B03715600D58574 /* DemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
5B8240D41B03715600D58574 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
5B8240D51B03715600D58574 /* DemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoTests.swift; sourceTree = ""; };
5B8240E61B0377FC00D58574 /* EasyIOS-Swift.podspec */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "EasyIOS-Swift.podspec"; path = "../EasyIOS-Swift.podspec"; sourceTree = ""; };
5B8240E71B0377FC00D58574 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; };
5B8240E81B0377FC00D58574 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; };
5B90B5CC1B04BFF8000C848D /* FeedRequest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedRequest.swift; sourceTree = ""; };
5BBC33D91BB3DFE00030B054 /* xml.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = xml.bundle; sourceTree = ""; };
5BDBF0CD1B038B7300E95ACF /* login-logo@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "login-logo@2x.png"; sourceTree = ""; };
5BDBF0CF1B038C1700E95ACF /* MainScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainScene.swift; sourceTree = ""; };
5BDBF0D41B038C7800E95ACF /* MainSceneModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainSceneModel.swift; sourceTree = ""; };
5BDBF0D81B038F0D00E95ACF /* url.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = url.plist; sourceTree = ""; };
5BDC06BA1B0394C200C486E0 /* CollectionScene.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionScene.swift; sourceTree = ""; };
5BDC06BC1B03950500C486E0 /* CollectionSceneModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionSceneModel.swift; sourceTree = ""; };
5BDC06BE1B03955A00C486E0 /* CollectionCellViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CollectionCellViewModel.swift; sourceTree = ""; };
6FA5AECAF1463C83BB66DE59 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
5B8240B71B03715600D58574 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
87D67298D115B9D5014DB706 /* Pods.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
5B8240CC1B03715600D58574 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
1729A45EA55A2C898A1E3A6F /* Pods */ = {
isa = PBXGroup;
children = (
6FA5AECAF1463C83BB66DE59 /* Pods.debug.xcconfig */,
0BAFEE4C5E077414790C2042 /* Pods.release.xcconfig */,
);
name = Pods;
sourceTree = "";
};
5B3FCA981BCDF68B00AF20CD /* FlexScene */ = {
isa = PBXGroup;
children = (
5B3FCA991BCDF6AB00AF20CD /* FlexScene.swift */,
5B4C52201BCE2E91003E0016 /* FlexXmlScene.swift */,
);
name = FlexScene;
sourceTree = "";
};
5B4C52261BCE547A003E0016 /* README */ = {
isa = PBXGroup;
children = (
5B4C52271BCE547A003E0016 /* Chinese.md */,
5B4C52281BCE547A003E0016 /* flexbox.png */,
);
name = README;
path = ../README;
sourceTree = "";
};
5B7B80D91B0A0B0F0059CAEF /* LabelScene */ = {
isa = PBXGroup;
children = (
5B7B80DA1B0A0B2A0059CAEF /* LabelScene.swift */,
);
name = LabelScene;
sourceTree = "";
};
5B8240B11B03715600D58574 = {
isa = PBXGroup;
children = (
5B8240DF1B0372B500D58574 /* PodMeta */,
5B8240BC1B03715600D58574 /* Demo */,
5B8240D21B03715600D58574 /* DemoTests */,
5B8240BB1B03715600D58574 /* Products */,
1729A45EA55A2C898A1E3A6F /* Pods */,
82578B0764B5D4425C7B4BC5 /* Frameworks */,
);
sourceTree = "";
};
5B8240BB1B03715600D58574 /* Products */ = {
isa = PBXGroup;
children = (
5B8240BA1B03715600D58574 /* Demo.app */,
5B8240CF1B03715600D58574 /* DemoTests.xctest */,
);
name = Products;
sourceTree = "";
};
5B8240BC1B03715600D58574 /* Demo */ = {
isa = PBXGroup;
children = (
5B3FCA981BCDF68B00AF20CD /* FlexScene */,
5B7B80D91B0A0B0F0059CAEF /* LabelScene */,
5B90B5C11B043889000C848D /* LoginScene */,
5BDC06B91B03949900C486E0 /* CollectionScene */,
5BDBF0D31B038C6400E95ACF /* MainScene */,
5BDBF0CC1B038B6800E95ACF /* Rescource */,
5B8240BF1B03715600D58574 /* AppDelegate.swift */,
5B8240C61B03715600D58574 /* Images.xcassets */,
5B8240C81B03715600D58574 /* LaunchScreen.xib */,
5B8240BD1B03715600D58574 /* Supporting Files */,
5BBC33D91BB3DFE00030B054 /* xml.bundle */,
);
path = Demo;
sourceTree = "";
};
5B8240BD1B03715600D58574 /* Supporting Files */ = {
isa = PBXGroup;
children = (
5B8240BE1B03715600D58574 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "";
};
5B8240D21B03715600D58574 /* DemoTests */ = {
isa = PBXGroup;
children = (
5B8240D51B03715600D58574 /* DemoTests.swift */,
5B8240D31B03715600D58574 /* Supporting Files */,
);
path = DemoTests;
sourceTree = "";
};
5B8240D31B03715600D58574 /* Supporting Files */ = {
isa = PBXGroup;
children = (
5B8240D41B03715600D58574 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "";
};
5B8240DF1B0372B500D58574 /* PodMeta */ = {
isa = PBXGroup;
children = (
5B4C52261BCE547A003E0016 /* README */,
5B8240E61B0377FC00D58574 /* EasyIOS-Swift.podspec */,
5B8240E71B0377FC00D58574 /* LICENSE */,
5B8240E81B0377FC00D58574 /* README.md */,
);
name = PodMeta;
sourceTree = "";
};
5B90B5C11B043889000C848D /* LoginScene */ = {
isa = PBXGroup;
children = (
5B8240C11B03715600D58574 /* LoginScene.swift */,
5B6512B01B141A9E00B1BA89 /* EncodeLoginScene.swift */,
);
name = LoginScene;
sourceTree = "";
};
5BDBF0CC1B038B6800E95ACF /* Rescource */ = {
isa = PBXGroup;
children = (
5BDBF0D81B038F0D00E95ACF /* url.plist */,
5BDBF0CD1B038B7300E95ACF /* login-logo@2x.png */,
);
name = Rescource;
sourceTree = "";
};
5BDBF0D31B038C6400E95ACF /* MainScene */ = {
isa = PBXGroup;
children = (
5BDBF0CF1B038C1700E95ACF /* MainScene.swift */,
5BDBF0D41B038C7800E95ACF /* MainSceneModel.swift */,
5B7B80C41B08D8E00059CAEF /* MainLabelDeleage.swift */,
);
name = MainScene;
sourceTree = "";
};
5BDC06B91B03949900C486E0 /* CollectionScene */ = {
isa = PBXGroup;
children = (
5BDC06BA1B0394C200C486E0 /* CollectionScene.swift */,
5BDC06BC1B03950500C486E0 /* CollectionSceneModel.swift */,
5BDC06BE1B03955A00C486E0 /* CollectionCellViewModel.swift */,
5B90B5CC1B04BFF8000C848D /* FeedRequest.swift */,
);
name = CollectionScene;
sourceTree = "";
};
82578B0764B5D4425C7B4BC5 /* Frameworks */ = {
isa = PBXGroup;
children = (
55CB89BDD03972BB5036E6DF /* Pods.framework */,
);
name = Frameworks;
sourceTree = "";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
5B8240B91B03715600D58574 /* Demo */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5B8240D91B03715600D58574 /* Build configuration list for PBXNativeTarget "Demo" */;
buildPhases = (
58FFA88B0BBAEE141CD3F935 /* Check Pods Manifest.lock */,
5B8240B61B03715600D58574 /* Sources */,
5B8240B71B03715600D58574 /* Frameworks */,
5B8240B81B03715600D58574 /* Resources */,
B9036220CE63B1B76499B1DF /* Embed Pods Frameworks */,
B0EA13793EF213CED106EF77 /* Copy Pods Resources */,
);
buildRules = (
);
dependencies = (
);
name = Demo;
productName = Demo;
productReference = 5B8240BA1B03715600D58574 /* Demo.app */;
productType = "com.apple.product-type.application";
};
5B8240CE1B03715600D58574 /* DemoTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 5B8240DC1B03715600D58574 /* Build configuration list for PBXNativeTarget "DemoTests" */;
buildPhases = (
5B8240CB1B03715600D58574 /* Sources */,
5B8240CC1B03715600D58574 /* Frameworks */,
5B8240CD1B03715600D58574 /* Resources */,
);
buildRules = (
);
dependencies = (
5B8240D11B03715600D58574 /* PBXTargetDependency */,
);
name = DemoTests;
productName = DemoTests;
productReference = 5B8240CF1B03715600D58574 /* DemoTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
5B8240B21B03715600D58574 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftMigration = 0700;
LastSwiftUpdateCheck = 0700;
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = zhuchao;
TargetAttributes = {
5B8240B91B03715600D58574 = {
CreatedOnToolsVersion = 6.3.1;
};
5B8240CE1B03715600D58574 = {
CreatedOnToolsVersion = 6.3.1;
TestTargetID = 5B8240B91B03715600D58574;
};
};
};
buildConfigurationList = 5B8240B51B03715600D58574 /* Build configuration list for PBXProject "Demo" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 5B8240B11B03715600D58574;
productRefGroup = 5B8240BB1B03715600D58574 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
5B8240B91B03715600D58574 /* Demo */,
5B8240CE1B03715600D58574 /* DemoTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
5B8240B81B03715600D58574 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5BBC33DA1BB3DFE00030B054 /* xml.bundle in Resources */,
5B8240CA1B03715600D58574 /* LaunchScreen.xib in Resources */,
5B8240E91B0377FC00D58574 /* EasyIOS-Swift.podspec in Resources */,
5BDBF0CE1B038B7300E95ACF /* login-logo@2x.png in Resources */,
5B8240C71B03715600D58574 /* Images.xcassets in Resources */,
5BDBF0D91B038F0D00E95ACF /* url.plist in Resources */,
5B4C522A1BCE547A003E0016 /* flexbox.png in Resources */,
5B8240EA1B0377FC00D58574 /* LICENSE in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
5B8240CD1B03715600D58574 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
58FFA88B0BBAEE141CD3F935 /* Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
B0EA13793EF213CED106EF77 /* Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
showEnvVarsInLog = 0;
};
B9036220CE63B1B76499B1DF /* Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
5B8240B61B03715600D58574 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5BDC06BD1B03950500C486E0 /* CollectionSceneModel.swift in Sources */,
5B90B5CD1B04BFF8000C848D /* FeedRequest.swift in Sources */,
5B6512B11B141A9E00B1BA89 /* EncodeLoginScene.swift in Sources */,
5B4C52291BCE547A003E0016 /* Chinese.md in Sources */,
5B4C52211BCE2E91003E0016 /* FlexXmlScene.swift in Sources */,
5BDBF0D51B038C7800E95ACF /* MainSceneModel.swift in Sources */,
5BDC06BF1B03955A00C486E0 /* CollectionCellViewModel.swift in Sources */,
5B3FCA9A1BCDF6AB00AF20CD /* FlexScene.swift in Sources */,
5BDC06BB1B0394C200C486E0 /* CollectionScene.swift in Sources */,
5B7B80DB1B0A0B2A0059CAEF /* LabelScene.swift in Sources */,
5B8240EB1B0377FC00D58574 /* README.md in Sources */,
5BDBF0D01B038C1700E95ACF /* MainScene.swift in Sources */,
5B8240C21B03715600D58574 /* LoginScene.swift in Sources */,
5B8240C01B03715600D58574 /* AppDelegate.swift in Sources */,
5B7B80C51B08D8E00059CAEF /* MainLabelDeleage.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
5B8240CB1B03715600D58574 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
5B8240D61B03715600D58574 /* DemoTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
5B8240D11B03715600D58574 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 5B8240B91B03715600D58574 /* Demo */;
targetProxy = 5B8240D01B03715600D58574 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
5B8240C81B03715600D58574 /* LaunchScreen.xib */ = {
isa = PBXVariantGroup;
children = (
5B8240C91B03715600D58574 /* Base */,
);
name = LaunchScreen.xib;
sourceTree = "";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
5B8240D71B03715600D58574 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
5B8240D81B03715600D58574 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
5B8240DA1B03715600D58574 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 6FA5AECAF1463C83BB66DE59 /* Pods.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = Demo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.iosx.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_INSTALL_OBJC_HEADER = NO;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
5B8240DB1B03715600D58574 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0BAFEE4C5E077414790C2042 /* Pods.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
INFOPLIST_FILE = Demo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.iosx.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_INSTALL_OBJC_HEADER = NO;
SWIFT_OBJC_BRIDGING_HEADER = "";
};
name = Release;
};
5B8240DD1B03715600D58574 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = DemoTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.iosx.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo";
};
name = Debug;
};
5B8240DE1B03715600D58574 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
);
INFOPLIST_FILE = DemoTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "me.iosx.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
5B8240B51B03715600D58574 /* Build configuration list for PBXProject "Demo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5B8240D71B03715600D58574 /* Debug */,
5B8240D81B03715600D58574 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5B8240D91B03715600D58574 /* Build configuration list for PBXNativeTarget "Demo" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5B8240DA1B03715600D58574 /* Debug */,
5B8240DB1B03715600D58574 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
5B8240DC1B03715600D58574 /* Build configuration list for PBXNativeTarget "DemoTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
5B8240DD1B03715600D58574 /* Debug */,
5B8240DE1B03715600D58574 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 5B8240B21B03715600D58574 /* Project object */;
}
================================================
FILE: Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: Demo/Demo.xcworkspace/contents.xcworkspacedata
================================================
================================================
FILE: Demo/DemoTests/DemoTests.swift
================================================
//
// DemoTests.swift
// DemoTests
//
// Created by zhuchao on 15/5/13.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import XCTest
class DemoTests: XCTestCase {
override func setUp() {
super.setUp()
// Put setup code here. This method is called before the invocation of each test method in the class.
}
override func tearDown() {
// Put teardown code here. This method is called after the invocation of each test method in the class.
super.tearDown()
}
func testExample() {
// This is an example of a functional test case.
XCTAssert(true, "Pass")
}
func testPerformanceExample() {
// This is an example of a performance test case.
self.measureBlock() {
// Put the code you want to measure the time of here.
}
}
}
================================================
FILE: Demo/DemoTests/Info.plist
================================================
CFBundleDevelopmentRegion
en
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
$(PRODUCT_NAME)
CFBundlePackageType
BNDL
CFBundleShortVersionString
1.0
CFBundleSignature
????
CFBundleVersion
1
================================================
FILE: Demo/Podfile
================================================
platform :ios, '8.0'
use_frameworks!
pod "EasyIOS-Swift", :path => "../"
pod 'SVProgressHUD', '~> 1.1.3'
================================================
FILE: EasyIOS-Swift.podspec
================================================
#
# Be sure to run `pod lib lint EasyIOS-Swift.podspec' to ensure this is a
# valid spec and remove all comments before submitting the spec.
#
# Any lines starting with a # are optional, but encouraged
#
# To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html
#
Pod::Spec.new do |s|
s.name = "EasyIOS-Swift"
s.version = "2.0.1"
s.summary = "The Swift version of EasyIOS"
s.description = <<-DESC
EasyIOS is a new generation of development framework based on `Model-View-ViewModel`,`HTML To Native`,`Live Load`,`FlexBox`.
DESC
s.homepage = "https://github.com/EasyIOS/EasyIOS-Swift"
# s.screenshots = "www.example.com/screenshots_1", "www.example.com/screenshots_2"
s.license = 'MIT'
s.author = { "zhuchao" => "zhuchao@iosx.me" }
s.source = { :git => "https://github.com/EasyIOS/EasyIOS-Swift.git", :tag => s.version.to_s }
#s.source = { :git => "/Users/zhuchao/Documents/EasyIOS-Swift"}
s.social_media_url = 'https://twitter.com/zhuchaowe'
s.platform = :ios, '8.0'
s.requires_arc = true
s.module_name = "EasyIOS"
s.source_files = 'Pod/Classes/**/*'
s.resource_bundles = {'EasyIOS-Swift' => ['Pod/Assets/*.png']}
s.dependency 'HanekeSwift'
s.dependency 'Bond'
s.dependency 'Alamofire'
s.dependency 'SnapKit'
s.dependency 'Kingfisher'
s.dependency 'ObjectMapper'
s.dependency 'ReachabilitySwift'
s.dependency 'TTTAttributedLabel'
s.public_header_files = 'Pod/Classes/Easy/**/*.h','Pod/Classes/Extend/**/*.h','Pod/Classes/Private/**/*.h'
s.frameworks = 'UIKit','JavaScriptCore'
end
================================================
FILE: LICENSE
================================================
Copyright (c) 2015 zhuchao
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: Pod/Assets/.gitkeep
================================================
================================================
FILE: Pod/Classes/.gitkeep
================================================
================================================
FILE: Pod/Classes/Easy/Core/EZAction.swift
================================================
//
// Action.swift
// medical
//
// Created by zhuchao on 15/4/25.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import Alamofire
import Haneke
import Bond
import ReachabilitySwift
public var HOST_URL = "" //服务端域名:端口
public var CODE_KEY = "" //错误码key,暂不支持路径 如 code
public var RIGHT_CODE = 0 //正确校验码
public var MSG_KEY = "" //消息提示msg,暂不支持路径 如 msg
private var networkReachabilityHandle: UInt8 = 2;
public class EZAction: NSObject {
//使用缓存策略 仅首次读取缓存
public class func SEND_IQ_CACHE (req:EZRequest) {
req.useCache = true
req.dataFromCache = req.isFirstRequest
self.Send(req)
}
//使用缓存策略 优先从缓存读取
public class func SEND_CACHE (req:EZRequest) {
req.useCache = true
req.dataFromCache = true
self.Send(req)
}
//不使用缓存策略
public class func SEND (req:EZRequest) {
req.useCache = false
req.dataFromCache = false
self.Send(req)
}
public class func Send (req :EZRequest){
var url = ""
var requestParams = Dictionary()
if !req.staticPath.characters.isEmpty {
url = req.staticPath
}else{
if req.scheme.characters.isEmpty {
req.scheme = "http"
}
if req.host.characters.isEmpty {
req.host = HOST_URL
}
url = req.scheme + "://" + req.host + req.path
if req.appendPathInfo.characters.isEmpty {
requestParams = req.requestParams
}else{
url = url + req.appendPathInfo
}
}
req.state.value = RequestState.Sending
req.op = req.manager
.request(req.method, url, parameters: requestParams, encoding: req.parameterEncoding)
.validate(statusCode: 200..<300)
.validate(contentType: req.acceptableContentTypes)
.responseJSON { response in
req.response = response
if response.result.isFailure{
req.error = response.result.error
self.failed(req)
}else{
req.output = response.result.value as! Dictionary
self.checkCode(req)
}
}
req.url = req.op?.request!.URL
self.getCacheJson(req)
}
public class func Upload (req :EZRequest){
req.state.value = RequestState.Sending
req.op = req.manager
.upload(.POST, req.uploadUrl, data: req.uploadData!)
.validate(statusCode: 200..<300)
.validate(contentType: req.acceptableContentTypes)
.progress { (bytesWritten, totalBytesWritten, totalBytesExpectedToWrite) in
req.totalBytesWritten = Double(totalBytesWritten)
req.totalBytesExpectedToWrite = Double(totalBytesExpectedToWrite)
req.progress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)
}.responseJSON { response in
req.response = response
if response.result.isFailure{
req.error = response.result.error
self.failed(req)
}else{
req.output = response.result.value as! Dictionary
self.checkCode(req)
}
}
req.url = req.op?.request!.URL
}
public class func Download (req :EZRequest){
req.state.value = RequestState.Sending
req.op = req.manager
.download(.GET, req.downloadUrl, destination: { (temporaryURL, response) in
let directoryURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,
inDomains: .UserDomainMask)[0]
return directoryURL.URLByAppendingPathComponent(req.targetPath + response.suggestedFilename!)
})
.validate(statusCode: 200..<300)
.progress { (bytesRead, totalBytesRead, totalBytesExpectedToRead) in
req.totalBytesRead = Double(totalBytesRead)
req.totalBytesExpectedToRead = Double(totalBytesExpectedToRead)
req.progress = Double(totalBytesRead) / Double(totalBytesExpectedToRead)
}
.response { (request, response, _, error) in
if error != nil{
req.error = error
self.failed(req)
}else{
req.state.value = RequestState.Success
}
}
req.url = req.op?.request!.URL
}
private class func cacheJson (req: EZRequest) {
if req.useCache {
let cache = Shared.JSONCache
cache.set(value: .Dictionary(req.output), key: req.cacheKey, formatName: HanekeGlobals.Cache.OriginalFormatName){ JSON in
EZPrintln("Cache Success for key: \(req.cacheKey)")
}
}
}
private class func getCacheJson (req: EZRequest) {
let cache = Shared.JSONCache
cache.fetch(key: req.cacheKey).onSuccess { JSON in
req.output = JSON.dictionary
if req.dataFromCache && !isEmpty(req.output) {
let delayTime = dispatch_time(DISPATCH_TIME_NOW,
Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {
self.loadFromCache(req)
}
}
}
}
private class func loadFromCache (req: EZRequest){
if req.needCheckCode && req.state.value != .Success {
req.codeKey = req.output[CODE_KEY] as? Int
if req.codeKey == RIGHT_CODE {
req.message = req.output[MSG_KEY] as? String
req.state.value = RequestState.SuccessFromCache
EZPrintln("Fetch Success from Cache by key: \(req.cacheKey)")
}else{
req.message = req.output[MSG_KEY] as? String
req.state.value = RequestState.ErrorFromCache
EZPrintln(req.message)
}
}
}
private class func checkCode (req: EZRequest) {
if req.needCheckCode {
req.codeKey = req.output[CODE_KEY] as? Int
if req.codeKey == RIGHT_CODE {
self.success(req)
self.cacheJson(req)
}else{
self.error(req)
}
}else{
req.state.value = RequestState.Success
self.cacheJson(req)
}
}
private class func success (req: EZRequest) {
req.isFirstRequest = false
req.message = req.output[MSG_KEY] as? String
if req.output.isEmpty {
req.state.value = RequestState.Error
}else{
req.state.value = RequestState.Success
}
}
private class func failed (req: EZRequest) {
req.message = req.error.debugDescription
req.state.value = RequestState.Failed
EZPrintln(req.message)
}
private class func error (req: EZRequest) {
req.message = req.output[MSG_KEY] as? String
req.state.value = RequestState.Error
EZPrintln(req.message)
}
/* Usage
EZAction.networkReachability *->> Bond{ status in
switch (status) {
case .NotReachable:
EZPrintln("NotReachable")
case .ReachableViaWiFi:
EZPrintln("ReachableViaWiFi")
case .ReachableViaWWAN:
EZPrintln("ReachableViaWWAN")
default:
EZPrintln("default")
}
}
*/
public class var networkReachability: Observable? {
if let d: AnyObject = objc_getAssociatedObject(self, &networkReachabilityHandle) {
return d as? Observable
} else {
do {
let reachability = try Reachability.reachabilityForInternetConnection()
let d = Observable(reachability.currentReachabilityStatus)
reachability.whenReachable = { reachability in
dispatch_async(dispatch_get_main_queue()) {
d.value = reachability.currentReachabilityStatus
}
}
reachability.whenUnreachable = { reachability in
dispatch_async(dispatch_get_main_queue()) {
d.value = reachability.currentReachabilityStatus
}
}
try reachability.startNotifier()
objc_setAssociatedObject(self, &networkReachabilityHandle, d, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return d
} catch {
print("Unable to create Reachability")
return nil
}
}
}
}
================================================
FILE: Pod/Classes/Easy/Core/EZCollectionView.swift
================================================
//
// EZCollectionView.swift
// medical
//
// Created by zhuchao on 15/4/26.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
public class EZCollectionView: UICollectionView {
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
}
================================================
FILE: Pod/Classes/Easy/Core/EZNavigationController.swift
================================================
//
// EZNavigationController.swift
// medical
//
// Created by zhuchao on 15/4/24.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
public class EZNavigationController: UINavigationController,UINavigationControllerDelegate,UIGestureRecognizerDelegate{
public var popGestureRecognizerEnabled = true
override public func viewDidLoad() {
super.viewDidLoad()
self.configGestureRecognizer()
// Do any additional setup after loading the view.
}
override public func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
public func configGestureRecognizer() {
if let target = self.interactivePopGestureRecognizer?.delegate {
let pan = UIPanGestureRecognizer(target: target, action: Selector("handleNavigationTransition:"))
pan.delegate = self
self.view.addGestureRecognizer(pan)
}
//禁掉系统的侧滑手势
weak var weekSelf = self
self.interactivePopGestureRecognizer?.enabled = false;
self.interactivePopGestureRecognizer?.delegate = weekSelf;
}
public func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer != self.interactivePopGestureRecognizer && self.viewControllers.count > 1 && self.popGestureRecognizerEnabled{
return true
}else{
return false
}
}
override public func pushViewController(viewController: UIViewController, animated: Bool) {
self.interactivePopGestureRecognizer?.enabled = false
super.pushViewController(viewController, animated: animated)
}
//UINavigationControllerDelegate
public func navigationController(navigationController: UINavigationController, didShowViewController viewController: UIViewController, animated: Bool) {
if self.popGestureRecognizerEnabled {
self.interactivePopGestureRecognizer?.enabled = true
}
}
}
================================================
FILE: Pod/Classes/Easy/Core/EZRequest.swift
================================================
//
// Request.swift
// medical
//
// Created by zhuchao on 15/4/24.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import Bond
import Alamofire
public enum RequestState : Int {
case Default //初始化状态
case Success
case Failed
case Sending
case Error
case Cancle
case Suspend
case SuccessFromCache
case ErrorFromCache
}
private var enabledDynamicHandleRequest: UInt8 = 0
private var stateDynamicHandleRequest: UInt8 = 1
private var managerHandle: UInt8 = 2
public class EZRequest: NSObject {
public var output = Dictionary() // 序列化后的数据
public var params = Dictionary() //使用字典参数
public var response:Response? // 获取字符串数据
public var error:ErrorType? //请求的错误
public var state = Observable(.Default) //Request状态
public var url:NSURL? //请求的链接
public var message:String? //错误消息或者服务器返回的MSG
public var codeKey:Int? // 错误码返回
//upload上传相关参数
public var uploadUrl:URLStringConvertible = "" //上传图片到这个URL协议
public var uploadData:NSData? //上传文件
public var progress = 0.0 //上传进度
public var totalBytesWritten = 0.0 //已上传数据大小
public var totalBytesExpectedToWrite = 0.0 //全部需要上传的数据大小
// download下载相关参数
public var downloadUrl:URLStringConvertible = ""//下载图片URL
public var targetPath = "" //下载到路径
public var totalBytesRead = 0.0 //已下载传数据大小
public var totalBytesExpectedToRead = 0.0 //全部需要下载的数据大小
public var scheme = "http" //协议
public var host = "" //域名
public var path = "" //请求路径
public var staticPath = "" //其他路径
public var method = Method.GET //提交方式
public var parameterEncoding = ParameterEncoding.URL //编码方式 Http头参数设置
public var needCheckCode = true //是否需要检查错误码
public var acceptableContentTypes = ["application/json","text/plain"] //可接受的序列化返回数据的格式
public var requestBlock:(Void->())?
public var isFirstRequest = false
//HttpHeader timeoutInterval Cookies 等都在这里设置
public var sessionConfiguration:NSURLSessionConfiguration?
public var op:Request?
public var requestNeedActive: Observable {
if let d: AnyObject = objc_getAssociatedObject(self, &enabledDynamicHandleRequest) {
return (d as? Observable)!
} else {
let d = Observable(false)
d.observe{ [weak self] v in if let s = self {
if v {
d.value = false
s.requestBlock?()
}
}}
objc_setAssociatedObject(self, &enabledDynamicHandleRequest, d, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return d
}
}
var useCache = false
var dataFromCache = false
public var requestKey :String {
return self.nameOfClass
}
public class var requestKey:String {
return self.nameOfClass
}
public var requestParams :Dictionary{
return self.listProperties()
}
public var appendPathInfo :String {
var pathInfo = self.pathInfo
if pathInfo != nil && !(pathInfo!).characters.isEmpty {
for (key,nsValue) in self.requestParams {
let par = "(\\{\(key)\\})"
let str = "\(nsValue)"
pathInfo = (try? NSRegularExpression(pattern: par, options: NSRegularExpressionOptions.CaseInsensitive))?.stringByReplacingMatchesInString(str, options: NSMatchingOptions.ReportCompletion, range: NSMakeRange(0, (pathInfo!).characters.count), withTemplate: str)
}
}
if pathInfo == nil {
pathInfo = ""
}
return pathInfo!
}
public var pathInfo :String?{
return nil
}
//the key for cache
public var cacheKey :String{
if self.method == .GET {
return self.url!.absoluteString.MD5
}else if !isEmpty(self.requestParams) {
return (self.url!.absoluteString + self.requestParams.joinPath).MD5
}else{
return self.url!.absoluteString.MD5
}
}
public func suspend() {
self.op?.suspend()
self.state.value = .Suspend
}
public func resume() {
self.op?.resume()
self.state.value = .Sending
}
public func cancel() {
self.op?.cancel()
self.state.value = .Cancle
}
public var manager:Manager {
get{
if let reqManager = objc_getAssociatedObject(self, &managerHandle) as? Manager {
return reqManager
}else if let configuration = sessionConfiguration{
let aManager = Alamofire.Manager(configuration: configuration)
objc_setAssociatedObject(self, &managerHandle, aManager, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return aManager
}else{
return Alamofire.Manager.sharedInstance
}
}set(aManager){
objc_setAssociatedObject(self, &managerHandle, aManager, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
}
================================================
FILE: Pod/Classes/Easy/Core/EZScene.swift
================================================
//
// Scene.swift
// medical
//
// Created by zhuchao on 15/4/22.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import SnapKit
public enum NAV : Int {
case LEFT
case RIGHT
}
public enum EXTEND : Int{
case NONE
case TOP
case BOTTOM
case TOP_BOTTOM
}
public enum INSET : Int{
case NONE
case TOP
case BOTTOM
case TOP_BOTTOM
}
public class EZScene: UIViewController {
//parentScene 保留设计,必要的时候保存parentScene
public weak var parentScene:EZScene?
//导航条左右按钮设置 NAV是一个枚举值:.LEFT,.RIGHT
public func showBarButton(position:NAV,title:String,fontColor:UIColor){
self.showBarButton(position, button: UIButton(navTitle: title, color: fontColor))
}
public func showBarButton(position:NAV,imageName:String) -> Void{
self.showBarButton(position, button: UIButton(navImage: UIImage(named: imageName)!))
}
public func showBarButton(position:NAV,button:UIButton?){
if position == .LEFT {
button?.addTarget(self, action: Selector("leftButtonTouch"), forControlEvents: UIControlEvents.TouchUpInside)
self.navigationItem.leftBarButtonItem = nil
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: button!)
self.navigationController?.interactivePopGestureRecognizer?.delegate = nil
}else if position == .RIGHT {
button?.addTarget(self, action: Selector("rightButtonTouch"), forControlEvents: UIControlEvents.TouchUpInside)
self.navigationItem.rightBarButtonItem = nil
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: button!)
}
}
public func leftButtonTouch(){
self.navigationController?.popViewControllerAnimated(true)
}
public func rightButtonTouch(){
}
public func setTitleView(titleView:UIView){
self.navigationItem.titleView = titleView
}
public func addSubView(view:UIView,extend:EXTEND){
self.view.addSubview(view)
self.view.sendSubviewToBack(view)
self.automaticallyAdjustsScrollViewInsets = false
self.extendedLayoutIncludesOpaqueBars = true
self.edgesForExtendedLayout = UIRectEdge.All
view.snp_makeConstraints { (make) -> Void in
//TODO
// make.edges.equalTo(view.superview!).inset(
// EdgeInsetsMake((extend == EXTEND.TOP||extend == EXTEND.TOP_BOTTOM) ? 64:0, left:0,bottom:(extend == EXTEND.BOTTOM||extend == EXTEND.TOP_BOTTOM) ? 49:0, right: 0)
// )
}
}
public func addScrollView(view:UIScrollView,extend:EXTEND,inset:INSET){
self.addSubView(view, extend: extend)
// view.contentInset = UIEdgeInsetsMake((inset == INSET.TOP || inset == INSET.TOP_BOTTOM) ? 64:0, 0,
// (inset == INSET.BOTTOM || inset == INSET.TOP_BOTTOM) ? 49:0, 0)
}
}
================================================
FILE: Pod/Classes/Easy/Core/EZSceneModel.swift
================================================
//
// SceneModel.swift
// medical
//
// Created by zhuchao on 15/4/26.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import Bond
public class EZSceneModel: NSObject {
}
================================================
FILE: Pod/Classes/Easy/Core/EZTableView.swift
================================================
//
// EZTableView.swift
// medical
//
// Created by zhuchao on 15/4/26.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
public class EZTableView: UITableView {
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
}
================================================
FILE: Pod/Classes/Easy/Core/EZViewModel.swift
================================================
//
// EZViewModel.swift
// medical
//
// Created by zhuchao on 15/5/11.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import Bond
public class EZData:NSObject {
public var dym:Observable?
public var value:NSData?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ data:NSData) {
self.dym = Observable(data)
}
}
public class EZString:NSObject {
public var dym:Observable?
public var value:String?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ str:String) {
self.dym = Observable(str)
}
}
public class EZURL:NSObject {
public var dym:Observable?
public var value:NSURL?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ url:NSURL?) {
self.dym = Observable(url)
}
}
public class EZAttributedString:NSObject {
public var dym:Observable?
public var value:NSAttributedString?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ str:NSAttributedString) {
self.dym = Observable(str)
}
}
public class EZImage:NSObject {
public var dym:Observable?
public var value:UIImage?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ image:UIImage?) {
self.dym = Observable(image)
}
}
public class EZColor:NSObject {
public var dym:Observable?
public var value:UIColor?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ color:UIColor) {
self.dym = Observable(color)
}
}
public class EZBool:NSObject {
public var dym:Observable?
public var value:Bool?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ b:Bool) {
self.dym = Observable(b)
}
}
public class EZFloat:NSObject {
public var dym:Observable?
public var value:CGFloat?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ fl:CGFloat) {
self.dym = Observable(fl)
}
}
public class EZInt:NSObject {
public var dym:Observable?
public var value:Int?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ i:Int) {
self.dym = Observable(i)
}
}
public class EZNumber:NSObject {
public var dym:Observable?
public var value:NSNumber?{
get{
return self.dym?.value
}set(value){
self.dym?.value = value!
}
}
public init(_ i:NSNumber) {
self.dym = Observable(i)
}
}
extension NSObject{
public var model_properyies :Dictionary{
return self.listProperties()
}
public func model_hasKey(key:String) -> Bool{
return self.model_properyies.keys.contains(key)
}
}
public class EZViewModel:NSObject {
}
================================================
FILE: Pod/Classes/Easy/Lib/EZCoreDataManager.swift
================================================
//
// EZCoreDataManager.swift
// medical
//
// Created by zhuchao on 15/5/31.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
import CoreData
private var managedObjectContextHandle:UInt8 = 0
private var persistentStoreCoordinatorHandle:UInt8 = 1
private var databaseNameHandle:UInt8 = 2
private var modelNameHandle:UInt8 = 3
private var managedObjectModelHandle:UInt8 = 4
public class EZCoreDataManager {
private static let appName = NSBundle.mainBundle().infoDictionary!["CFBundleName"] as! String
public var databaseName: String {
get {
if let db = objc_getAssociatedObject(self, &databaseNameHandle) as? String {
return db
} else {
return EZCoreDataManager.appName + ".sqlite"
}
}
set(value){
objc_setAssociatedObject(self, &databaseNameHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_setAssociatedObject(self, &managedObjectContextHandle, nil, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_setAssociatedObject(self, &persistentStoreCoordinatorHandle, nil, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public var modelName: String {
get {
if let model = objc_getAssociatedObject(self, &modelNameHandle) as? String {
return model
} else {
return EZCoreDataManager.appName
}
}
set(value) {
objc_setAssociatedObject(self, &modelNameHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_setAssociatedObject(self, &managedObjectContextHandle, nil, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_setAssociatedObject(self, &persistentStoreCoordinatorHandle, nil, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public var managedObjectContext: NSManagedObjectContext {
get {
if let context = objc_getAssociatedObject(self, &managedObjectContextHandle) as? NSManagedObjectContext {
return context
} else {
let c = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)
c.persistentStoreCoordinator = persistentStoreCoordinator
objc_setAssociatedObject(self, &managedObjectContextHandle, c, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return c
}
}
set (value){
objc_setAssociatedObject(self, &managedObjectContextHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public var persistentStoreCoordinator: NSPersistentStoreCoordinator {
get {
if let store = objc_getAssociatedObject(self, &persistentStoreCoordinatorHandle) as? NSPersistentStoreCoordinator {
return store
} else {
let p = self.persistentStoreCoordinator(NSSQLiteStoreType, storeURL: self.sqliteStoreURL)
objc_setAssociatedObject(self, &persistentStoreCoordinatorHandle, p, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return p
}
}set(value){
objc_setAssociatedObject(self, &persistentStoreCoordinatorHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public var managedObjectModel: NSManagedObjectModel {
if let m = objc_getAssociatedObject(self, &managedObjectModelHandle) as? NSManagedObjectModel {
return m
} else {
let modelURL = NSBundle.mainBundle().URLForResource(self.modelName, withExtension: "momd")
let model = NSManagedObjectModel(contentsOfURL: modelURL!)
objc_setAssociatedObject(self, &managedObjectModelHandle, model, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return model!
}
}
public func useInMemoryStore() {
persistentStoreCoordinator = self.persistentStoreCoordinator(NSInMemoryStoreType, storeURL: nil)
}
public func saveContext() -> Bool {
return self.managedObjectContext.saveData()
}
private var sqliteStoreURL: NSURL {
#if os(iOS)
let dir = EZCoreDataManager.applicationDocumentsDirectory
#else
let dir = EZCoreDataManager.applicationSupportDirectory
self.createApplicationSupportDirIfNeeded(dir)
#endif
return dir!.URLByAppendingPathComponent(self.databaseName)
}
private func persistentStoreCoordinator(storeType: String, storeURL: NSURL?) -> NSPersistentStoreCoordinator {
let c = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let error = NSErrorPointer()
do {
try c.addPersistentStoreWithType(storeType, configuration: nil, URL: storeURL, options: [NSMigratePersistentStoresAutomaticallyOption:true,NSInferMappingModelAutomaticallyOption:true])
} catch let error1 as NSError {
error.memory = error1
print("ERROR WHILE CREATING PERSISTENT STORE COORDINATOR! " + error.debugDescription)
}
return c
}
private static var applicationDocumentsDirectory:NSURL? {
return NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).last
}
private static var applicationSupportDirectory:NSURL? {
return NSFileManager.defaultManager().URLsForDirectory(NSSearchPathDirectory.ApplicationSupportDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask).last?.URLByAppendingPathComponent(EZCoreDataManager.appName)
}
private static func createApplicationSupportDirIfNeeded(dir: NSURL) {
if NSFileManager.defaultManager().fileExistsAtPath(dir.absoluteString) {
return
}
do {
try NSFileManager.defaultManager().createDirectoryAtURL(dir, withIntermediateDirectories: true, attributes: nil)
} catch _ {
}
}
// singleton
public static let sharedManager = EZCoreDataManager()
}
public extension NSManagedObjectContext {
public static var defaultContext: NSManagedObjectContext {
return EZCoreDataManager.sharedManager.managedObjectContext
}
func createFetchRequest(entityName:String) -> NSFetchRequest {
let request = NSFetchRequest()
request.entity = NSEntityDescription.entityForName(entityName, inManagedObjectContext: self)
return request
}
func saveData() -> Bool {
if !self.hasChanges {
return true
}
let error = NSErrorPointer()
let save: Bool
do {
try self.save()
save = true
} catch let error1 as NSError {
error.memory = error1
save = false
}
if (!save) {
print("Unresolved error in saving context for entity:")
print(self)
print("!\nError: " + error.debugDescription)
return false
}
return true
}
}
public extension NSPredicate{
public func condition(condition: AnyObject?) -> NSPredicate?{
if let cond: AnyObject = condition {
return NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates:[self, NSPredicate.predicate(cond)])
}
return self
}
public func orCondition(condition: AnyObject?) -> NSPredicate?{
if let cond: AnyObject = condition {
return NSCompoundPredicate(type: NSCompoundPredicateType.OrPredicateType, subpredicates:[self, NSPredicate.predicate(cond)])
}
return self
}
private static func predicate(properties: [String:AnyObject]) -> NSPredicate {
var preds = [NSPredicate]()
for (key, value) in properties {
preds.append(NSPredicate(format: "%K = %@", argumentArray: [key, value]))
}
return NSCompoundPredicate(type: NSCompoundPredicateType.AndPredicateType, subpredicates: preds)
}
private static func predicate(condition: AnyObject) -> NSPredicate {
if condition is NSPredicate {
return condition as! NSPredicate
}
if let d = condition as? [String:AnyObject] {
return self.predicate(d)
}
return NSPredicate()
}
}
public extension NSFetchRequest{
public func condition(condition: AnyObject?) -> NSFetchRequest{
if let cond: AnyObject = condition {
if let pred = self.predicate {
self.predicate = pred.condition(cond)
}else{
self.predicate = NSPredicate.predicate(cond)
}
}
return self
}
public func orCondition(condition: AnyObject?) -> NSFetchRequest{
if let cond: AnyObject = condition,let pred = self.predicate {
self.predicate = pred.orCondition(cond)
}
return self
}
public func orderBy(key:String,_ order:String = "ASC") -> NSFetchRequest{
let sortDescriptor = NSSortDescriptor(key: key, ascending: order.uppercaseString=="ASC")
if self.sortDescriptors == nil{
self.sortDescriptors = [sortDescriptor]
}else{
self.sortDescriptors?.append(sortDescriptor)
}
return self
}
/**
* Set the "limit" value of the query.
*
* @param int value
* @return self
* @static
*/
public func limit(value:Int) -> NSFetchRequest{
self.fetchLimit = value
self.fetchOffset = 0
return self
}
/**
* Alias to set the "limit" value of the query.
*
* @param int value
* @return NSFetchRequest
*/
public func take(value:Int) -> NSFetchRequest{
return self.limit(value)
}
/**
* Set the limit and offset for a given page.
*
* @param int page
* @param int perPage
* @return NSFetchRequest
*/
public func forPage(page:Int,_ perPage:Int) -> NSFetchRequest{
self.fetchLimit = perPage
self.fetchOffset = (page - 1) * perPage
return self
}
public func first() -> NSManagedObject?{
return self.take(1).get().first
}
public func delete() -> NSInteger{
var i = 0
for o in self.get() {
o.delete()
i++
}
return i
}
public func get() -> [NSManagedObject]{
return (try! NSManagedObjectContext.defaultContext.executeFetchRequest(self)) as! [NSManagedObject]
}
public func count() -> Int {
return NSManagedObjectContext.defaultContext.countForFetchRequest(self, error: nil)
}
public func exists() -> Bool {
return self.count() > 0
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+Array.swift
================================================
//
// EZExtend+Array.swift
// medical
//
// Created by zhuchao on 15/5/1.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
extension Array {
func stringAtIndex(index:Int,other:String) -> String{
if self.count >= index + 1 {
return (self[index] as! String).trim
}else{
return other
}
}
func floatAtIndex(index:Int,other:CGFloat) -> CGFloat{
if self.count >= index + 1 {
return (self[index] as! String).trim.floatValue
}else{
return other
}
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+Bond.swift
================================================
//
// EZBond.swift
// medical
//
// Created by zhuchao on 15/4/27.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Bond
import TTTAttributedLabel
@objc class TapGestureDynamicHelper:NSObject
{
weak var view: UIView?
let sink: (UITapGestureRecognizer) -> Void
init(view: UIView,number:NSInteger,sink:((UITapGestureRecognizer) -> Void)) {
self.view = view
self.sink = sink
super.init()
view.addTapGesture(number, target: self, action: Selector("tapHandle:"))
}
func tapHandle(gesture: UITapGestureRecognizer) {
sink(gesture)
}
}
@objc class PanGestureDynamicHelper:NSObject{
weak var view: UIView?
let sink: (UIPanGestureRecognizer) -> Void
init(view: UIView,number:NSInteger,sink:((UIPanGestureRecognizer) -> Void)) {
self.view = view
self.sink = sink
super.init()
view.addPanGesture(self, action: Selector("panHandle:"))
}
func panHandle(gestureRecognizer:UIPanGestureRecognizer) {
sink(gestureRecognizer)
}
}
@objc class SwipeGestureDynamicHelper:NSObject
{
weak var view: UIView?
let sink: ((UISwipeGestureRecognizer) -> Void)
var number:NSInteger = 1
init(view: UIView,number:NSInteger,sink:((UISwipeGestureRecognizer) -> Void)) {
self.view = view
self.number = number
self.sink = sink
super.init()
view.addSwipeGesture(UISwipeGestureRecognizerDirection.Right, numberOfTouches: number, target: self, action: Selector("swipeRightHandle:"))
view.addSwipeGesture(UISwipeGestureRecognizerDirection.Up, numberOfTouches: number, target: self, action: Selector("swipeUpHandle:"))
view.addSwipeGesture(UISwipeGestureRecognizerDirection.Down, numberOfTouches: number, target: self, action: Selector("swipeDownHandle:"))
view.addSwipeGesture(UISwipeGestureRecognizerDirection.Left, numberOfTouches: number, target: self, action: Selector("swipeLeftHandle:"))
}
func swipeRightHandle(gestureRecognizer:UISwipeGestureRecognizer) {
sink(gestureRecognizer)
}
func swipeUpHandle(gestureRecognizer:UISwipeGestureRecognizer) {
sink(gestureRecognizer)
}
func swipeDownHandle(gestureRecognizer:UISwipeGestureRecognizer) {
sink(gestureRecognizer)
}
func swipeLeftHandle(gestureRecognizer:UISwipeGestureRecognizer) {
sink(gestureRecognizer)
}
}
extension UIView{
private struct AssociatedKeys {
static var PanGestureEventKey = "bnd_PanGestureEventKey"
static var PanGestureEventHelperKey = "bnd_PanGestureEventHelperKey"
static var SwipeGestureEventKey = "bnd_SwipeGestureEventKey"
static var SwipeGestureEventHelperKey = "bnd_SwipeGestureEventHelperKey"
static var TapGestureEventKey = "bnd_TapGestureEventKey"
static var TapGestureEventHelperKey = "bnd_TapGestureEventHelperKey"
}
public func bnd_swipeGestureEvent(number:NSInteger) ->EventProducer {
if let bnd_swipeGestureEvent: AnyObject = objc_getAssociatedObject(self, &AssociatedKeys.SwipeGestureEventKey) {
return bnd_swipeGestureEvent as! EventProducer
} else {
var capturedSink: (UISwipeGestureRecognizer -> ())! = nil
let bnd_swipeGestureEvent = EventProducer { sink in
capturedSink = sink
return nil
}
let controlHelper = SwipeGestureDynamicHelper(view: self, number: number, sink: capturedSink)
objc_setAssociatedObject(self, &AssociatedKeys.SwipeGestureEventHelperKey, controlHelper, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_setAssociatedObject(self, &AssociatedKeys.SwipeGestureEventKey, bnd_swipeGestureEvent, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return bnd_swipeGestureEvent
}
}
public func bnd_tapGestureEvent(number:NSInteger) ->EventProducer {
if let bnd_tapGestureEvent: AnyObject = objc_getAssociatedObject(self, &AssociatedKeys.TapGestureEventKey) {
return bnd_tapGestureEvent as! EventProducer
} else {
var capturedSink: (UITapGestureRecognizer -> ())! = nil
let bnd_tapGestureEvent = EventProducer { sink in
capturedSink = sink
return nil
}
let controlHelper = TapGestureDynamicHelper(view: self, number: number, sink: capturedSink)
objc_setAssociatedObject(self, &AssociatedKeys.TapGestureEventHelperKey, controlHelper, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_setAssociatedObject(self, &AssociatedKeys.TapGestureEventKey, bnd_tapGestureEvent, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return bnd_tapGestureEvent
}
}
public var bnd_panGestureEvent:EventProducer {
if let bnd_panGestureEvent: AnyObject = objc_getAssociatedObject(self, &AssociatedKeys.PanGestureEventKey) {
return bnd_panGestureEvent as! EventProducer
} else {
var capturedSink: (UIPanGestureRecognizer -> ())! = nil
let bnd_panGestureEvent = EventProducer { sink in
capturedSink = sink
return nil
}
let controlHelper = PanGestureDynamicHelper(view: self, number: 1, sink: capturedSink)
objc_setAssociatedObject(self, &AssociatedKeys.PanGestureEventHelperKey, controlHelper, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_setAssociatedObject(self, &AssociatedKeys.PanGestureEventKey, bnd_panGestureEvent, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return bnd_panGestureEvent
}
}
}
extension UIImageView {
private struct AssociatedKeys {
static var UrlImageDynamicHandleUIImageView = "UrlImageDynamicHandleUIImageView"
}
public var bnd_URLImage: Observable {
if let d: AnyObject = objc_getAssociatedObject(self, &AssociatedKeys.UrlImageDynamicHandleUIImageView) {
return (d as? Observable)!
} else {
let d = Observable(NSURL())
d.observe { [weak self] v in if let s = self {
if v != nil {
s.kf_setImageWithURL(v!)
}
} }
objc_setAssociatedObject(self, &AssociatedKeys.UrlImageDynamicHandleUIImageView, d, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return d
}
}
}
extension TTTAttributedLabel {
private struct AssociatedKeys {
static var textDynamicHandleTTTAttributeLabel = "textDynamicHandleTTTAttributeLabel"
static var attributedTextDynamicHandleTTTAttributeLabel = "attributedTextDynamicHandleTTTAttributeLabel"
static var dataDynamicHandleTTTAttributeLabel = "dataDynamicHandleTTTAttributeLabel"
}
public var dynTTText: Observable {
if let d: AnyObject = objc_getAssociatedObject(self, &AssociatedKeys.textDynamicHandleTTTAttributeLabel) {
return (d as? Observable)!
} else {
let d = Observable(self.text ?? "")
d.observe { [weak self] v in if let s = self {
s.setText(v)
} }
objc_setAssociatedObject(self, &AssociatedKeys.textDynamicHandleTTTAttributeLabel, d, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return d
}
}
public var dynTTTData: Observable {
if let d: AnyObject = objc_getAssociatedObject(self, &AssociatedKeys.dataDynamicHandleTTTAttributeLabel) {
return (d as? Observable)!
} else {
let d = Observable(NSData())
d.observe{ [weak self] v in if let s = self {
s.setText(NSAttributedString(fromHTMLData: v, attributes: ["dict":s.tagProperty.style]))
}}
objc_setAssociatedObject(self, &AssociatedKeys.dataDynamicHandleTTTAttributeLabel, d, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return d
}
}
public var dynTTTAttributedText: Observable {
if let d: AnyObject = objc_getAssociatedObject(self, &AssociatedKeys.attributedTextDynamicHandleTTTAttributeLabel) {
return (d as? Observable)!
} else {
let d = Observable(self.attributedText ?? NSAttributedString(string: ""))
d.observe { [weak self] v in if let s = self {
s.setText(v) } }
objc_setAssociatedObject(self, &AssociatedKeys.attributedTextDynamicHandleTTTAttributeLabel, d, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
return d
}
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+Dictionary.swift
================================================
//
// Dictionary+EZExtend.swift
// medical
//
// Created by zhuchao on 15/4/25.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
extension Dictionary {
//join the Dictionary with "&" to a url path
var joinPath : String{
var array = ArraySlice()
for (key,value) in self {
array.append("\(key)=\(value)")
}
return array.joinWithSeparator("&")
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+NSDate.swift
================================================
//
// EZExtend+NSDate.swift
// medical
//
// Created by zhuchao on 15/5/9.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
extension NSDate {
//format :yyyy-MM-dd
public func formatTo(format:String) -> String{
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = format
let currentDateStr = dateFormatter.stringFromDate(self)
return currentDateStr
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+String.swift
================================================
//
// EZExtend+String.swift
// medical
//
// Created by zhuchao on 15/4/28.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
// MARK: - String
public func trimToArray (str:String) -> Array{
return str.trim.componentsSeparatedByCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).filter(){
return !$0.characters.isEmpty
}
}
public func trimToArrayBy (str:String,by:String) -> Array{
return str.trim.componentsSeparatedByString(by).filter(){
return !$0.characters.isEmpty
}
}
extension String {
public subscript (i: Int) -> String {
return String(Array(self.characters)[i])
}
public var urlencode :String? {
return self.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.letterCharacterSet())
}
public var urldecode :String? {
return self.stringByRemovingPercentEncoding;
}
public var trim :String {
return self.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())
}
public var trimArray : Array{
return trimToArray(self)
}
public func trimArrayBy (str:String) -> Array {
return trimToArrayBy(self,by: str)
}
public var toKeyPath :String {
let keyArray = self.trim.componentsSeparatedByString("-")
var str = ""
var index = 0
for akey in keyArray {
if index == 0 {
str += akey
}else{
str += akey.capitalizedString
}
index++
}
if let reg = Regex("_").replace(str, withTemplate: ".") {
str = reg
}
return str
}
public var floatValue: CGFloat {
return CGFloat((self as NSString).floatValue)
}
public var integerValue: Int {
return (self as NSString).integerValue
}
public var boolValue: Bool {
return (self as NSString).boolValue
}
public func anyValue(key:String) -> AnyObject{
if key == "font" {
if let font = UIFont.Font(self.trim) {
return font
}
}
return self.anyValue
}
public var anyValue :AnyObject{
let str = self.trim
if str.hasSuffix(".cg"){
if let color = UIColor(CSS: Regex(".cg").replace(str, withTemplate: "")){
return color.CGColor
}
}
if ["YES","NO","TRUE","FALSE"].contains(str.uppercaseString) {
return str.boolValue
}else if let color = UIColor(CSS: str){
return color
}else if let image = UIImage(named: str){
return image
}else if str.floatValue != 0.0 {
return str.floatValue
}else{
return str
}
}
public var MD5 : String {
let data = self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
return data!.MD5String
}
public func toData () -> NSData?{
return self.dataUsingEncoding(NSUTF8StringEncoding)?.dataByReplacingOccurrencesOfData("\\n".dataUsingEncoding(NSUTF8StringEncoding), withData: "\n".dataUsingEncoding(NSUTF8StringEncoding))
}
public var chineseFirstLetter : String{
return HTFirstLetter.firstLetter(self)
}
public var chineseFirstLetters : String {
return HTFirstLetter.firstLetters(self)
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+UIAlertController.swift
================================================
//
// EZExtend+UIAlertController.swift
// medical
//
// Created by zhuchao on 15/4/28.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
// MARK: - UIAlertController
public func alert (title: String,
message: String,
cancelAction: ((UIAlertAction!)->Void)? = nil,
okAction: ((UIAlertAction!)->Void)? = nil) -> UIAlertController {
let a = UIAlertController (title: title, message: message, preferredStyle: .Alert)
if let ok = okAction {
a.addAction(UIAlertAction(title: "OK", style: .Default, handler: ok))
a.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: cancelAction))
} else {
a.addAction(UIAlertAction(title: "OK", style: .Cancel, handler: cancelAction))
}
return a
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+UIButton.swift
================================================
//
// UIButton+EZExtend.swift
// medical
//
// Created by zhuchao on 15/4/22.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
let NAV_BAR_HEIGHT = CGFloat(40.0)
let NAV_BUTTON_MIN_WIDTH = CGFloat(40.0)
let NAV_BUTTON_MIN_HEIGHT = CGFloat(40.0)
extension UIButton{
public convenience init(navImage: UIImage){
var buttonFrame = CGRectMake(CGFloat(0.0), CGFloat(0.0), navImage.size.width, NAV_BAR_HEIGHT)
if buttonFrame.size.width < NAV_BUTTON_MIN_WIDTH
{
buttonFrame.size.width = NAV_BUTTON_MIN_WIDTH
}
if buttonFrame.size.height < NAV_BUTTON_MIN_HEIGHT
{
buttonFrame.size.height = NAV_BUTTON_MIN_HEIGHT
}
self.init(frame:buttonFrame)
self.contentMode = UIViewContentMode.ScaleAspectFill
self.backgroundColor = UIColor.clearColor()
self.setImage(navImage, forState: UIControlState.Normal)
}
public convenience init(navTitle: String,color: UIColor){
let titleSize = navTitle.boundingRectWithSize(CGSizeMake(999999.0, NAV_BAR_HEIGHT), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: Dictionary(dictionaryLiteral: (NSFontAttributeName,UIFont.systemFontOfSize(16.0))), context: nil).size
var buttonFrame = CGRectMake(CGFloat(0.0), CGFloat(0.0), titleSize.width, NAV_BAR_HEIGHT)
if buttonFrame.size.width < NAV_BUTTON_MIN_WIDTH
{
buttonFrame.size.width = NAV_BUTTON_MIN_WIDTH
}
if buttonFrame.size.height < NAV_BUTTON_MIN_HEIGHT
{
buttonFrame.size.height = NAV_BUTTON_MIN_HEIGHT
}
self.init(frame: buttonFrame)
self.contentMode = UIViewContentMode.ScaleAspectFill
self.backgroundColor = UIColor.clearColor()
self.titleLabel?.font = UIFont.systemFontOfSize(16.0)
self.setTitleColor(color, forState: UIControlState.Normal)
self.setTitle(navTitle, forState: UIControlState.Normal)
}
public func setBackgroundImageWithColor(color: UIColor?, forState state: UIControlState){
if let c = color {
let image = UIImage.imageWithColor(c, size: CGSizeMake(1, 1))
self.setBackgroundImage(image, forState: state)
}
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+UIFont.swift
================================================
//
// EZExtend+UIFont.swift
// medical
//
// Created by zhuchao on 15/4/28.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
// MARK: - UIFont
extension UIFont {
public enum FontType: String {
case Regular = "Regular"
case Bold = "Bold"
case Light = "Light"
case UltraLight = "UltraLight"
case Italic = "Italic"
case Thin = "Thin"
case Book = "Book"
case Roman = "Roman"
case Medium = "Medium"
case MediumItalic = "MediumItalic"
case CondensedMedium = "CondensedMedium"
case CondensedExtraBold = "CondensedExtraBold"
case SemiBold = "SemiBold"
case BoldItalic = "BoldItalic"
case Heavy = "Heavy"
}
public enum FontName: String {
case HelveticaNeue = "HelveticaNeue"
case Helvetica = "Helvetica"
case Futura = "Futura"
case Menlo = "Menlo"
case Avenir = "Avenir"
case AvenirNext = "AvenirNext"
case Didot = "Didot"
case AmericanTypewriter = "AmericanTypewriter"
case Baskerville = "Baskerville"
case Geneva = "Geneva"
case GillSans = "GillSans"
case SanFranciscoDisplay = "SanFranciscoDisplay"
case Seravek = "Seravek"
}
public class func PrintFontFamily (font: FontName) {
let arr = UIFont.fontNamesForFamilyName(font.rawValue)
for name in arr {
print(name)
}
}
public class func Font (str:String) -> UIFont? {
var array = str.trimArray
if array.count >= 2{
let font = array[1] as String
if font == "system" {
return UIFont.systemFontOfSize(array[0].floatValue)
}else{
return UIFont(name: array[1], size: array[0].floatValue)
}
}else if array.count == 1{
return UIFont.systemFontOfSize(array[0].floatValue)
}
return nil
}
public class func Font (name: FontName, type: FontType, size: CGFloat) -> UIFont {
return UIFont (name: name.rawValue + "-" + type.rawValue, size: size)!
}
public class func HelveticaNeue (type: FontType, size: CGFloat) -> UIFont {
return Font(.HelveticaNeue, type: type, size: size)
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+UIImage.swift
================================================
//
// EZExtend+UIImage.swift
// medical
//
// Created by zhuchao on 15/4/28.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
// MARK: - UIImage
extension UIImage {
public class func imageWithColor(color:UIColor,size:CGSize) -> UIImage {
let rect = CGRectMake(0, 0, size.width, size.height)
UIGraphicsBeginImageContextWithOptions(size, false, 0)
color.setFill()
UIRectFill(rect)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
public func aspectResizeWithWidth (width: CGFloat) -> UIImage {
let aspectSize = CGSize (width: width, height: aspectHeightForWidth(width))
UIGraphicsBeginImageContext(aspectSize)
self.drawInRect(CGRect(origin: CGPointZero, size: aspectSize))
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
public func aspectResizeWithHeight (height: CGFloat) -> UIImage {
let aspectSize = CGSize (width: aspectWidthForHeight(height), height: height)
UIGraphicsBeginImageContext(aspectSize)
self.drawInRect(CGRect(origin: CGPointZero, size: aspectSize))
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
public func aspectHeightForWidth (width: CGFloat) -> CGFloat {
return (width * self.size.height) / self.size.width
}
public func aspectWidthForHeight (height: CGFloat) -> CGFloat {
return (height * self.size.width) / self.size.height
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+UILabel.swift
================================================
//
// EZExtend+UILabel.swift
// medical
//
// Created by zhuchao on 15/4/28.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
// MARK: - UILabel
private var UILabelAttributedStringArray: UInt8 = 0
extension UILabel {
public var attributedStrings: [NSAttributedString]? {
get {
return objc_getAssociatedObject(self, &UILabelAttributedStringArray) as? [NSAttributedString]
} set (value) {
objc_setAssociatedObject(self, &UILabelAttributedStringArray, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public func addAttributedString (text: String,
color: UIColor,
font: UIFont) {
let att = NSAttributedString (string: text,
attributes: [NSFontAttributeName: font,
NSForegroundColorAttributeName: color])
self.addAttributedString(att)
}
public func addAttributedString (attributedString: NSAttributedString) {
var att: NSMutableAttributedString?
if let a = self.attributedText {
att = NSMutableAttributedString (attributedString: a)
att?.appendAttributedString(attributedString)
} else {
att = NSMutableAttributedString (attributedString: attributedString)
attributedStrings = []
}
attributedStrings?.append(attributedString)
self.attributedText = NSAttributedString (attributedString: att!)
}
public func updateAttributedStringAtIndex (index: Int,
attributedString: NSAttributedString) {
if (attributedStrings?[index] != nil) {
attributedStrings?.removeAtIndex(index)
attributedStrings?.insert(attributedString, atIndex: index)
let updated = NSMutableAttributedString ()
for att in attributedStrings! {
updated.appendAttributedString(att)
}
self.attributedText = NSAttributedString (attributedString: updated)
}
}
public func updateAttributedStringAtIndex (index: Int,
newText: String) {
if let att = attributedStrings?[index] {
let newAtt = NSMutableAttributedString (string: newText)
att.enumerateAttributesInRange(NSMakeRange(0, att.string.characters.count-1),
options: NSAttributedStringEnumerationOptions.LongestEffectiveRangeNotRequired,
usingBlock: { (attribute, range, stop) -> Void in
for (key, value) in attribute {
newAtt.addAttribute(key , value: value, range: range)
}
})
updateAttributedStringAtIndex(index, attributedString: newAtt)
}
}
public func getEstimatedHeight () -> CGFloat {
let att = NSAttributedString(string: self.text!, attributes: [NSFontAttributeName:font])
let rect = att.boundingRectWithSize(CGSize (width: w, height: CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, context: nil)
return rect.height
}
public func fitHeight () {
self.h = getEstimatedHeight()
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+UIView.swift
================================================
//
// EZExtend+UIView.swift
// medical
//
// Created by zhuchao on 15/4/28.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import Bond
// MARK: - UIView
let UIViewAnimationDuration: NSTimeInterval = 1
let UIViewAnimationSpringDamping: CGFloat = 0.5
let UIViewAnimationSpringVelocity: CGFloat = 0.5
var UIViewGestureUniqueArray:CGFloat = 0.6
extension UIView {
// public var gestureUniqueArray: [String:DisposableType] {
// get {
// if let viewGestureUniqueArray: AnyObject = objc_getAssociatedObject(self, &UIViewGestureUniqueArray) {
// return viewGestureUniqueArray as! Dictionary
// } else {
// let mapData = [String:DisposableType]()
// objc_setAssociatedObject(self, &UIViewGestureUniqueArray, mapData, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
// return mapData
// }
// }set(value){
//// if let viewGestureUniqueArray: AnyObject = objc_getAssociatedObject(self, &UIViewGestureUniqueArray) {
////
//// } else {
//// let mapData = [String:DisposableType]()
//// mapData[]
//// }
//
// }
//
// }
// MARK: Custom Initilizer
convenience init (x: CGFloat,
y: CGFloat,
w: CGFloat,
h: CGFloat) {
self.init (frame: CGRect (x: x, y: y, width: w, height: h))
}
// MARK: Frame Extensions
public var x: CGFloat {
get {
return self.frame.origin.x
} set (value) {
self.frame = CGRect (x: value, y: self.y, width: self.w, height: self.h)
}
}
public var y: CGFloat {
get {
return self.frame.origin.y
} set (value) {
self.frame = CGRect (x: self.x, y: value, width: self.w, height: self.h)
}
}
public var w: CGFloat {
get {
return self.frame.size.width
} set (value) {
self.frame = CGRect (x: self.x, y: self.y, width: value, height: self.h)
}
}
public var h: CGFloat {
get {
return self.frame.size.height
} set (value) {
self.frame = CGRect (x: self.x, y: self.y, width: self.w, height: value)
}
}
public var left: CGFloat {
get {
return self.x
} set (value) {
self.x = value
}
}
var right: CGFloat {
get {
return self.x + self.w
} set (value) {
self.x = value - self.w
}
}
public var top: CGFloat {
get {
return self.y
} set (value) {
self.y = value
}
}
public var bottom: CGFloat {
get {
return self.y + self.h
} set (value) {
self.y = value - self.h
}
}
public var position: CGPoint {
get {
return self.frame.origin
} set (value) {
self.frame = CGRect (origin: value, size: self.frame.size)
}
}
public var size: CGSize {
get {
return self.frame.size
} set (value) {
self.frame = CGRect (origin: self.frame.origin, size: size)
}
}
public func leftWithOffset (offset: CGFloat) -> CGFloat {
return self.left - offset
}
public func rightWithOffset (offset: CGFloat) -> CGFloat {
return self.right + offset
}
public func topWithOffset (offset: CGFloat) -> CGFloat {
return self.top - offset
}
public func botttomWithOffset (offset: CGFloat) -> CGFloat {
return self.bottom + offset
}
// MARK: Transform Extensions
public func setRotationX (x: CGFloat) {
var transform = CATransform3DIdentity
transform.m34 = 1.0 / -1000.0
transform = CATransform3DRotate(transform, degreesToRadians(x), 1.0, 0.0, 0.0)
self.layer.transform = transform
}
public func setRotationY (y: CGFloat) {
var transform = CATransform3DIdentity
transform.m34 = 1.0 / -1000.0
transform = CATransform3DRotate(transform, degreesToRadians(y), 0.0, 1.0, 0.0)
self.layer.transform = transform
}
public func setRotationZ (z: CGFloat) {
var transform = CATransform3DIdentity
transform.m34 = 1.0 / -1000.0
transform = CATransform3DRotate(transform, degreesToRadians(z), 0.0, 0.0, 1.0)
self.layer.transform = transform
}
public func setRotation (x: CGFloat,
y: CGFloat,
z: CGFloat) {
var transform = CATransform3DIdentity
transform.m34 = 1.0 / -1000.0
transform = CATransform3DRotate(transform, degreesToRadians(x), 1.0, 0.0, 0.0)
transform = CATransform3DRotate(transform, degreesToRadians(y), 0.0, 1.0, 0.0)
transform = CATransform3DRotate(transform, degreesToRadians(z), 0.0, 0.0, 1.0)
self.layer.transform = transform
}
public func setScale (x: CGFloat,
y: CGFloat) {
var transform = CATransform3DIdentity
transform.m34 = 1.0 / -1000.0
transform = CATransform3DScale(transform, x, y, 1)
self.layer.transform = transform
}
// MARK: Anchor Extensions
public func setAnchorPosition (anchorPosition: AnchorPosition) {
print(anchorPosition.rawValue)
self.layer.anchorPoint = anchorPosition.rawValue
}
// MARK: Layer Extensions
public func addShadow (offset: CGSize,
radius: CGFloat,
color: UIColor,
opacity: Float) {
self.layer.shadowOffset = offset
self.layer.shadowRadius = radius
self.layer.shadowOpacity = opacity
self.layer.shadowColor = color.CGColor
}
public func addBorder (width: CGFloat,
color: UIColor) {
self.layer.borderWidth = width
self.layer.borderColor = color.CGColor
self.layer.masksToBounds = true
}
public func setCornerRadius (radius: CGFloat) {
self.layer.cornerRadius = radius
self.layer.masksToBounds = true
}
public func drawCircle (fillColor: UIColor,
strokeColor: UIColor,
strokeWidth: CGFloat) {
let path = UIBezierPath (roundedRect: CGRect (x: 0, y: 0, width: self.w, height: self.w), cornerRadius: self.w/2)
let shapeLayer = CAShapeLayer ()
shapeLayer.path = path.CGPath
shapeLayer.fillColor = fillColor.CGColor
shapeLayer.strokeColor = strokeColor.CGColor
shapeLayer.lineWidth = strokeWidth
self.layer.addSublayer(shapeLayer)
}
public func drawStroke (width: CGFloat,
color: UIColor) {
let path = UIBezierPath (roundedRect: CGRect (x: 0, y: 0, width: self.w, height: self.w), cornerRadius: self.w/2)
let shapeLayer = CAShapeLayer ()
shapeLayer.path = path.CGPath
shapeLayer.fillColor = UIColor.clearColor().CGColor
shapeLayer.strokeColor = color.CGColor
shapeLayer.lineWidth = width
self.layer.addSublayer(shapeLayer)
}
public func drawArc (from: CGFloat,
to: CGFloat,
clockwise: Bool,
width: CGFloat,
fillColor: UIColor,
strokeColor: UIColor,
lineCap: String) {
let path = UIBezierPath (arcCenter: self.center, radius: self.w/2, startAngle: degreesToRadians(from), endAngle: degreesToRadians(to), clockwise: clockwise)
let shapeLayer = CAShapeLayer ()
shapeLayer.path = path.CGPath
shapeLayer.fillColor = fillColor.CGColor
shapeLayer.strokeColor = strokeColor.CGColor
shapeLayer.lineWidth = width
self.layer.addSublayer(shapeLayer)
}
// MARK: Animation Extensions
public func spring (animations: (()->Void)!,
completion: ((Bool)->Void)? = nil) {
UIView.animateWithDuration(UIViewAnimationDuration,
delay: 0,
usingSpringWithDamping: UIViewAnimationSpringDamping,
initialSpringVelocity: UIViewAnimationSpringVelocity,
options: UIViewAnimationOptions.AllowAnimatedContent,
animations: animations,
completion: completion)
}
public func animate (animations: (()->Void)!,
completion: ((Bool)->Void)? = nil) {
UIView.animateWithDuration(UIViewAnimationDuration,
animations: animations,
completion: completion)
}
// MARK: Gesture Extensions
public func addTapGesture (tapNumber: NSInteger,
target: AnyObject, action: Selector) {
let tap = UITapGestureRecognizer (target: target, action: action)
tap.numberOfTapsRequired = tapNumber
self.addGestureRecognizer(tap)
}
public func addSwipeGesture (direction: UISwipeGestureRecognizerDirection,
numberOfTouches: Int,
target: AnyObject,
action: Selector) {
let swipe = UISwipeGestureRecognizer (target: target, action: action)
swipe.direction = direction
swipe.numberOfTouchesRequired = numberOfTouches
self.addGestureRecognizer(swipe)
}
public func addPanGesture (target: AnyObject,
action: Selector) {
let pan = UIPanGestureRecognizer (target: target, action: action)
self.addGestureRecognizer(pan)
}
public func whenTap(number:NSInteger = 1,block:()->Void) -> DisposableType{
self.userInteractionEnabled = true
return bnd_tapGestureEvent(number).observe { (_) -> () in
block()
}
}
public func whenSwipe(number:NSInteger = 1,direction:UISwipeGestureRecognizerDirection,block:()->Void) -> DisposableType{
self.userInteractionEnabled = true
return bnd_swipeGestureEvent(number).observe { (_) -> () in
block()
}
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZExtend+UIViewController.swift
================================================
//
// EZExtend+UIViewController.swift
// medical
//
// Created by zhuchao on 15/4/28.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
// MARK: - UIViewController
extension UIViewController {
public var top: CGFloat {
get {
if let nav = self.navigationController {
if nav.navigationBarHidden {
return view.top
} else {
return nav.navigationBar.bottom
}
} else {
return view.top
}
}
}
public var bottom: CGFloat {
get {
if let tab = tabBarController {
if tab.tabBar.hidden {
return view.bottom
} else {
return tab.tabBar.top
}
} else {
return view.bottom
}
}
}
public var navigationBarHeight: CGFloat {
get {
if let nav = self.navigationController {
return nav.navigationBar.h
}
return 0
}
}
public var navigationBarColor: UIColor? {
get {
return navigationController?.navigationBar.tintColor
} set (value) {
navigationController?.navigationBar.barTintColor = value
}
}
public var navigationBar: UINavigationBar? {
get {
return navigationController?.navigationBar
}
}
public var applicationFrame: CGRect {
get {
return CGRect (x: view.x, y: top, width: view.w, height: bottom - top)
}
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZKit.swift
================================================
//
// CEMKit.swift
// CEMKit-Swift
//
// Created by Cem Olcay on 05/11/14.
// Copyright (c) 2014 Cem Olcay. All rights reserved.
//
import UIKit
// MARK: - UIBarButtonItem
public func barButtonItem (imageName: String,
action: (AnyObject)->()) -> UIBarButtonItem {
let button = BlockButton (frame: CGRect(x: 0, y: 0, width: 20, height: 20))
button.setImage(UIImage(named: imageName), forState: .Normal)
button.actionBlock = action
return UIBarButtonItem (customView: button)
}
public func barButtonItem (title: String,
color: UIColor,
action: (AnyObject)->()) -> UIBarButtonItem {
let button = BlockButton (frame: CGRect(x: 0, y: 0, width: 20, height: 20))
button.setTitle(title, forState: .Normal)
button.setTitleColor(color, forState: .Normal)
button.actionBlock = action
button.sizeToFit()
return UIBarButtonItem (customView: button)
}
// MARK: - CGSize
public func + (left: CGSize, right: CGSize) -> CGSize {
return CGSize (width: left.width + right.width, height: left.height + right.height)
}
public func - (left: CGSize, right: CGSize) -> CGSize {
return CGSize (width: left.width - right.width, height: left.width - right.width)
}
// MARK: - CGPoint
public func + (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint (x: left.x + right.x, y: left.y + right.y)
}
public func - (left: CGPoint, right: CGPoint) -> CGPoint {
return CGPoint (x: left.x - right.x, y: left.y - right.y)
}
public enum AnchorPosition: CGPoint {
case TopLeft = "{0, 0}"
case TopCenter = "{0.5, 0}"
case TopRight = "{1, 0}"
case MidLeft = "{0, 0.5}"
case MidCenter = "{0.5, 0.5}"
case MidRight = "{1, 0.5}"
case BottomLeft = "{0, 1}"
case BottomCenter = "{0.5, 1}"
case BottomRight = "{1, 1}"
}
extension CGPoint: StringLiteralConvertible {
public init(stringLiteral value: StringLiteralType) {
self = CGPointFromString(value)
}
public init(extendedGraphemeClusterLiteral value: StringLiteralType) {
self = CGPointFromString(value)
}
public init(unicodeScalarLiteral value: StringLiteralType) {
self = CGPointFromString(value)
}
}
// MARK: - CGFloat
public func degreesToRadians (angle: CGFloat) -> CGFloat {
return (CGFloat (M_PI) * angle) / 180.0
}
public func normalizeValue (value: CGFloat,
min: CGFloat,
max: CGFloat) -> CGFloat {
return (max - min) / value
}
public func convertNormalizedValue (value: CGFloat,
min: CGFloat,
max: CGFloat) -> CGFloat {
return ((max - min) * value) + min
}
// MARK: - Block Classes
// MARK: - BlockButton
public class BlockButton: UIButton {
override init (frame: CGRect) {
super.init(frame: frame)
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
var actionBlock: ((sender: BlockButton) -> ())? {
didSet {
self.addTarget(self, action: "action:", forControlEvents: UIControlEvents.TouchUpInside)
}
}
func action (sender: BlockButton) {
actionBlock! (sender: sender)
}
}
// MARK: - BlockWebView
public class BlockWebView: UIWebView, UIWebViewDelegate {
var didStartLoad: ((NSURLRequest?) -> ())?
var didFinishLoad: ((NSURLRequest?) -> ())?
var didFailLoad: ((NSURLRequest?, NSError?) -> ())?
var shouldStartLoadingRequest: ((NSURLRequest) -> (Bool))?
override init(frame: CGRect) {
super.init(frame: frame)
delegate = self
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
@objc public func webViewDidStartLoad(webView: UIWebView) {
didStartLoad? (webView.request)
}
@objc public func webViewDidFinishLoad(webView: UIWebView) {
didFinishLoad? (webView.request)
}
@objc public func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
didFailLoad? (webView.request, error)
}
@objc public func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if let should = shouldStartLoadingRequest {
return should (request)
} else {
return true
}
}
}
public func nsValueForAny(anyValue:Any) -> NSObject? {
switch(anyValue) {
case let intValue as Int:
return NSNumber(int: CInt(intValue))
case let doubleValue as Double:
return NSNumber(double: CDouble(doubleValue))
case let stringValue as String:
return stringValue as NSString
case let boolValue as Bool:
return NSNumber(bool: boolValue)
default:
return nil
}
}
extension NSObject{
public class var nameOfClass: String{
return NSStringFromClass(self).componentsSeparatedByString(".").last!
}
public var nameOfClass: String{
return NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last!
}
public func listProperties() -> Dictionary{
var modelDictionary = Dictionary()
Mirror(reflecting: self).children.forEach { (element) -> () in
if element.label != "super" {
if let nsValue = nsValueForAny(element.value) {
modelDictionary.updateValue(nsValue, forKey: element.label!)
}
}
}
return modelDictionary
}
}
public func isEmpty(x: C) -> Bool {
if x.isKindOfClass(NSNull) {
return true
}else if x.respondsToSelector(Selector("length")) && NSData().self.length == 0 {
return true
}else if x.respondsToSelector(Selector("count")) && NSArray().self.count == 0 {
return true
}
return false
}
================================================
FILE: Pod/Classes/Easy/Lib/EZPrintln.swift
================================================
//
// EZPrintln.swift
// medical
//
// Created by zhuchao on 15/4/28.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
var EZ_DEBUG_MODE = true
/**
Writes the textual representation of `object` and a newline character into the standard output.
The textual representation is obtained from the `object` using its protocol conformances,
in the following order of preference: `Streamable`, `Printable`, `DebugPrintable`.
This functional also augments the original function with the filename, function name, and line number of the object that is being logged.
- parameter object: A textual representation of the object.
- parameter file: Defaults to the name of the file that called magic(). Do not override this default.
- parameter function: Defaults to the name of the function within the file in which magic() was called. Do not override this default.
- parameter line: Defaults to the line number within the file in which magic() was called. Do not override this default.
*/
public func EZPrintln(object: T, _ file: String = __FILE__, _ function: String = __FUNCTION__, _ line: Int = __LINE__)
{
if EZ_DEBUG_MODE {
let filename = NSURL(fileURLWithPath: file).lastPathComponent?.URLString
print("\(filename).\(function)[\(line)]: \(object)\n", terminator: "")
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZSystemInfo.swift
================================================
//
// EZSystemInfo.swift
// medical
//
// Created by zhuchao on 15/4/22.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
#if os(iOS)
let IOS10_OR_LATER = (UIDevice.currentDevice().systemVersion.caseInsensitiveCompare("10.0") != NSComparisonResult.OrderedAscending)
let IOS9_OR_LATER = (UIDevice.currentDevice().systemVersion.caseInsensitiveCompare("9.0") != NSComparisonResult.OrderedAscending)
let IOS8_OR_LATER = (UIDevice.currentDevice().systemVersion.caseInsensitiveCompare("8.0") != NSComparisonResult.OrderedAscending)
let IOS7_OR_LATER = (UIDevice.currentDevice().systemVersion.caseInsensitiveCompare("7.0") != NSComparisonResult.OrderedAscending)
let IOS6_OR_LATER = (UIDevice.currentDevice().systemVersion.caseInsensitiveCompare("6.0") != NSComparisonResult.OrderedAscending)
let IOS5_OR_LATER = (UIDevice.currentDevice().systemVersion.caseInsensitiveCompare("5.0") != NSComparisonResult.OrderedAscending)
let IOS4_OR_LATER = (UIDevice.currentDevice().systemVersion.caseInsensitiveCompare("4.0") != NSComparisonResult.OrderedAscending)
let IOS3_OR_LATER = (UIDevice.currentDevice().systemVersion.caseInsensitiveCompare("3.0") != NSComparisonResult.OrderedAscending)
let IOS9_OR_EARLIER = !IOS10_OR_LATER
let IOS8_OR_EARLIER = !IOS9_OR_LATER
let IOS7_OR_EARLIER = !IOS8_OR_LATER
let IOS6_OR_EARLIER = !IOS7_OR_LATER
let IOS5_OR_EARLIER = !IOS6_OR_LATER
let IOS4_OR_EARLIER = !IOS5_OR_LATER
let IOS3_OR_EARLIER = !IOS4_OR_LATER
let IS_SCREEN_4_INCH = CGSizeEqualToSize(CGSizeMake(640, 1136), UIScreen.mainScreen().currentMode!.size)
let IS_SCREEN_35_INCH = CGSizeEqualToSize(CGSizeMake(640, 960), UIScreen.mainScreen().currentMode!.size)
let IS_SCREEN_47_INCH = CGSizeEqualToSize(CGSizeMake(750, 1334), UIScreen.mainScreen().currentMode!.size)
let IS_SCREEN_55_INCH = CGSizeEqualToSize(CGSizeMake(1242, 2208), UIScreen.mainScreen().currentMode!.size)
#else
let IOS9_OR_LATER = false
let IOS8_OR_LATER = false
let IOS7_OR_LATER = false
let IOS6_OR_LATER = false
let IOS5_OR_LATER = false
let IOS4_OR_LATER = false
let IOS3_OR_LATER = false
let IOS9_OR_EARLIER = false
let IOS8_OR_EARLIER = false
let IOS7_OR_EARLIER = false
let IOS6_OR_EARLIER = false
let IOS5_OR_EARLIER = false
let IOS4_OR_EARLIER = false
let IOS3_OR_EARLIER = false
let IS_SCREEN_4_INCH = false
let IS_SCREEN_35_INCH = false
let IS_SCREEN_47_INCH = false
let IS_SCREEN_55_INCH = false
#endif
public var IsSimulator:Bool {
#if (arch(i386) || arch(x86_64)) && os(iOS)
return true;
#else
return false;
#endif
}
public func OSVersion() ->String{
#if os(iOS)
return UIDevice.currentDevice().systemName + " " + UIDevice.currentDevice().systemVersion
#else // #if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
return ""
#endif // #if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
}
//func AppVersion() ->String{
// var value = NSBundle.mainBundle().infoDictionary["CFBundleVersion"]
// if nil == value || 0 == value.length
// {
// value = NSBundle.mainBundle().infoDictionary["CFBundleShortVersion"]
// }
// return value
//}
//func AppIdentifier() ->String{
//#if os(iOS)
// var value = NSBundle.mainBundle().infoDictionary["CFBundleVersion"]
// if nil == value || 0 == value.length
// {
// value = NSBundle.mainBundle().infoDictionary["CFBundleShortVersion"]
// }
// return value
//#else // #if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
// return ""
//#endif // #if (TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR)
//}
public var Orientation: UIInterfaceOrientation {
get {
return UIApplication.sharedApplication().statusBarOrientation
}
}
public var ScreenWidth: CGFloat {
get {
if UIInterfaceOrientationIsPortrait(Orientation) {
return UIScreen.mainScreen().bounds.size.width
} else {
return UIScreen.mainScreen().bounds.size.height
}
}
}
public var ScreenHeight: CGFloat {
get {
if UIInterfaceOrientationIsPortrait(Orientation) {
return UIScreen.mainScreen().bounds.size.height
} else {
return UIScreen.mainScreen().bounds.size.width
}
}
}
public var StatusBarHeight: CGFloat {
get {
return UIApplication.sharedApplication().statusBarFrame.height
}
}
================================================
FILE: Pod/Classes/Easy/Lib/EZWatch.swift
================================================
// EZWatch.swift
// medical
//
// Created by zhuchao on 15/4/29.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
func watchForChangesToFilePath(filePath:String,callback:dispatch_block_t) {
let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
let fileDescriptor = open(filePath, O_EVTONLY)
if fileDescriptor <= 0 {
return
}
assert(fileDescriptor > 0, "Error could subscribe to events for file at path: \(filePath)")
let source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, UInt(fileDescriptor), DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND, queue)
dispatch_source_set_event_handler(source){
let flags = dispatch_source_get_data(source)
if flags != 0 {
dispatch_source_cancel(source)
dispatch_async(dispatch_get_main_queue()){
callback()
}
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.5*Double(NSEC_PER_SEC)))
dispatch_after(popTime, queue){
watchForChangesToFilePath(filePath, callback: callback)
}
}
}
dispatch_source_set_cancel_handler(source){
close(fileDescriptor)
}
dispatch_resume(source)
}
================================================
FILE: Pod/Classes/Easy/Lib/EasyORM.swift
================================================
//
// NSManagedObject+EZExtend.swift
// medical
//
// Created by zhuchao on 15/5/30.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
import CoreData
public func DBQuery(aClass: NSManagedObject.Type!,entityName:String) -> NSFetchRequest {
return aClass.defaultContext().createFetchRequest(entityName)
}
public class EasyORM {
public static var generateRelationships = false
public static func setUpEntities(entities: [String:NSManagedObject.Type]) {
nameToEntities = entities
}
private static var nameToEntities: [String:NSManagedObject.Type] = [String:NSManagedObject.Type]()
}
public extension NSManagedObject{
public func defaultContext() -> NSManagedObjectContext{
return self.managedObjectContext ?? self.dynamicType.defaultContext()
}
public static func defaultContext() -> NSManagedObjectContext{
return NSManagedObjectContext.defaultContext
}
private static var query:NSFetchRequest{
return self.defaultContext().createFetchRequest(self.entityName())
}
public static func condition(condition: AnyObject?) -> NSFetchRequest{
return self.query.condition(condition)
}
public static func orderBy(key:String,_ order:String = "ASC") -> NSFetchRequest{
return self.query.orderBy(key, order)
}
/**
* Set the "limit" value of the query.
*
* @param int value
* @return self
* @static
*/
public static func limit(value:Int) -> NSFetchRequest{
return self.query.limit(value)
}
/**
* Alias to set the "limit" value of the query.
*
* @param int value
* @return NSFetchRequest
*/
public static func take(value:Int) -> NSFetchRequest{
return self.query.take(value)
}
/**
* Set the limit and offset for a given page.
*
* @param int page
* @param int perPage
* @return NSFetchRequest
*/
public static func forPage(page:Int,_ perPage:Int) -> NSFetchRequest{
return self.query.forPage(page,perPage)
}
public static func all() -> [NSManagedObject] {
return self.query.get()
}
public static func count() -> Int {
return self.query.count()
}
public static func findAndUpdate(unique:[String:AnyObject],data:[String:AnyObject]) -> NSManagedObject?{
if let object = self.find(unique) {
object.update(data)
return object
}else{
return nil
}
}
public static func updateOrCreate(unique:[String:AnyObject],data:[String:AnyObject]) -> NSManagedObject{
if let object = self.find(unique) {
object.update(data)
return object
}else{
return self.create(data)
}
}
public static func findOrCreate(properties: [String:AnyObject]) -> NSManagedObject {
let transformed = self.transformProperties(properties)
let existing = self.find(properties)
return existing ?? self.create(transformed)
}
public static func find(condition: AnyObject) -> NSManagedObject? {
return self.query.condition(condition).first()
}
public func update(properties: [String:AnyObject]) {
if (properties.count == 0) {
return
}
let transformed = self.dynamicType.transformProperties(properties)
//Finish
for (key, value) in transformed {
self.willChangeValueForKey(key)
self.setSafeValue(value, forKey: key)
self.didChangeValueForKey(key)
}
}
public func save() -> Bool {
return self.defaultContext().saveData()
}
public func delete() -> NSManagedObjectContext {
let context = self.defaultContext()
context.deleteObject(self)
return context
}
public static func deleteAll() -> NSManagedObjectContext{
for o in self.all() {
o.delete()
}
return self.defaultContext()
}
public static func create() -> NSManagedObject {
let o = NSEntityDescription.insertNewObjectForEntityForName(self.entityName(), inManagedObjectContext: self.defaultContext())
if let idprop = self.autoIncrementingId() {
o.setPrimitiveValue(NSNumber(integer: self.nextId()), forKey: idprop)
}
return o
}
public static func create(properties: [String:AnyObject]) -> NSManagedObject {
let newEntity: NSManagedObject = self.create()
newEntity.update(properties)
if let idprop = self.autoIncrementingId() {
if newEntity.primitiveValueForKey(idprop) == nil {
newEntity.setPrimitiveValue(NSNumber(integer: self.nextId()), forKey: idprop)
}
}
return newEntity
}
public static func autoIncrements() -> Bool {
return self.autoIncrementingId() != nil
}
public static func nextId() -> Int {
let key = "SwiftRecord-" + self.entityName() + "-ID"
if self.autoIncrementingId() != nil {
let id = NSUserDefaults.standardUserDefaults().integerForKey(key)
NSUserDefaults.standardUserDefaults().setInteger(id + 1, forKey: key)
return id
}
return 0
}
public class func autoIncrementingId() -> String? {
return nil
}
//Private
private static func transformProperties(properties: [String:AnyObject]) -> [String:AnyObject]{
let entity = NSEntityDescription.entityForName(self.entityName(), inManagedObjectContext: self.defaultContext())!
let attrs = entity.attributesByName
let rels = entity.relationshipsByName
var transformed = [String:AnyObject]()
for (key, value) in properties {
let localKey = self.keyForRemoteKey(key)
if attrs[localKey] != nil {
transformed[localKey] = value
} else if let rel = rels[localKey] {
if EasyORM.generateRelationships {
if rel.toMany {
if let array = value as? [[String:AnyObject]] {
transformed[localKey] = self.generateSet(rel, array: array)
} else {
#if DEBUG
println("Invalid value for relationship generation in \(NSStringFromClass(self)).\(localKey)")
println(value)
#endif
}
} else if let dict = value as? [String:AnyObject] {
transformed[localKey] = self.generateObject(rel, dict: dict)
} else {
#if DEBUG
println("Invalid value for relationship generation in \(NSStringFromClass(self)).\(localKey)")
println(value)
#endif
}
}
}
}
return transformed
}
private func setSafeValue(value: AnyObject?, forKey key: String) {
if (value == nil) {
self.setNilValueForKey(key)
return
}
let val: AnyObject = value!
if let attr = self.entity.attributesByName[key] {
let attrType = attr.attributeType
if attrType == NSAttributeType.StringAttributeType && value is NSNumber {
self.setPrimitiveValue((val as! NSNumber).stringValue, forKey: key)
} else if let s = val as? String {
if self.isIntegerAttributeType(attrType) {
self.setPrimitiveValue(NSNumber(integer: val.integerValue), forKey: key)
return
} else if attrType == NSAttributeType.BooleanAttributeType {
self.setPrimitiveValue(NSNumber(bool: val.boolValue), forKey: key)
return
} else if (attrType == NSAttributeType.FloatAttributeType) {
self.setPrimitiveValue(NSNumber(floatLiteral: val.doubleValue), forKey: key)
return
} else if (attrType == NSAttributeType.DateAttributeType) {
self.setPrimitiveValue(self.dynamicType.dateFormatter.dateFromString(s), forKey: key)
return
}
}
}
self.setPrimitiveValue(value, forKey: key)
}
private func isIntegerAttributeType(attrType: NSAttributeType) -> Bool {
return attrType == NSAttributeType.Integer16AttributeType || attrType == NSAttributeType.Integer32AttributeType || attrType == NSAttributeType.Integer64AttributeType
}
private static var dateFormatter: NSDateFormatter {
if _dateFormatter == nil {
_dateFormatter = NSDateFormatter()
_dateFormatter!.dateFormat = "yyyy-MM-dd HH:mm:ss z"
}
return _dateFormatter!
}
private static var _dateFormatter: NSDateFormatter?
public class func mappings() -> [String:String] {
return [String:String]()
}
public static func keyForRemoteKey(remote: String) -> String {
if let s = cachedMappings[remote] {
return s
}
let entity = NSEntityDescription.entityForName(self.entityName(), inManagedObjectContext: self.defaultContext())!
let properties = entity.propertiesByName
if properties[remote] != nil {
_cachedMappings![remote] = remote
return remote
}
let camelCased = remote.camelCase
if properties[camelCased] != nil {
_cachedMappings![remote] = camelCased
return camelCased
}
_cachedMappings![remote] = remote
return remote
}
private static var cachedMappings: [String:String] {
if let m = _cachedMappings {
return m
} else {
var m = [String:String]()
for (key, value) in mappings() {
m[value] = key
}
_cachedMappings = m
return m
}
}
private static var _cachedMappings: [String:String]?
private static func generateSet(rel: NSRelationshipDescription, array: [[String:AnyObject]]) -> NSSet {
var cls: NSManagedObject.Type?
if EasyORM.nameToEntities.count > 0 {
cls = EasyORM.nameToEntities[rel.destinationEntity!.managedObjectClassName]
}
if cls == nil {
cls = (NSClassFromString(rel.destinationEntity!.managedObjectClassName) as! NSManagedObject.Type)
} else {
print("Got class name from entity setup")
}
let set = NSMutableSet()
for d in array {
set.addObject(cls!.findOrCreate(d))
}
return set
}
private static func generateObject(rel: NSRelationshipDescription, dict: [String:AnyObject]) -> NSManagedObject {
let entity = rel.destinationEntity!
let cls: NSManagedObject.Type = NSClassFromString(entity.managedObjectClassName) as! NSManagedObject.Type
return cls.findOrCreate(dict)
}
public static func primaryKey() -> String {
NSException(name: "Primary key undefined in " + NSStringFromClass(self), reason: "Override primaryKey if you want to support automatic creation, otherwise disable this feature", userInfo: nil).raise()
return ""
}
private static func entityName() -> String {
var name = NSStringFromClass(self)
if name.rangeOfString(".") != nil {
let comp = name.characters.split {$0 == "."}.map { String($0) }
if comp.count > 1 {
name = comp.last!
}
}
if name.rangeOfString("_") != nil {
var comp = name.characters.split {$0 == "_"}.map { String($0) }
var last: String = ""
var remove = -1
for (i,s) in Array(comp.reverse()).enumerate() {
if last == s {
remove = i
}
last = s
}
if remove > -1 {
comp.removeAtIndex(remove)
name = comp.joinWithSeparator("_")
}
}
return name
}
}
public extension String {
var camelCase: String {
let spaced = self.stringByReplacingOccurrencesOfString("_", withString: " ", options: [], range:Range(start: self.startIndex, end: self.endIndex))
let capitalized = spaced.capitalizedString
let spaceless = capitalized.stringByReplacingOccurrencesOfString(" ", withString: "", options:[], range:Range(start:self.startIndex, end:self.endIndex))
return spaceless.stringByReplacingCharactersInRange(Range(start:spaceless.startIndex, end:spaceless.startIndex.successor()), withString: "\(spaceless[spaceless.startIndex])".lowercaseString)
}
}
================================================
FILE: Pod/Classes/Easy/Lib/NSData+EasyExtend.h
================================================
//
// NSData+EasyExtend.h
// fastSign
//
// Created by EasyIOS on 14-4-10.
// Copyright (c) 2014年 zhuchao. All rights reserved.
//
#import
@interface NSData (EasyExtend)
@property (nonatomic, readonly) NSData * MD5;
@property (nonatomic, readonly) NSString * MD5String;
+ (NSData *)fromResource:(NSString *)resName;
@end
================================================
FILE: Pod/Classes/Easy/Lib/NSData+EasyExtend.m
================================================
//
// NSData+EasyExtend.m
//
// Created by EasyIOS on 14-4-10.
// Copyright (c) 2014年 zhuchao. All rights reserved.
//
#import "NSData+EasyExtend.h"
#import
@implementation NSData (EasyExtend)
- (NSData *)MD5
{
unsigned char md5Result[CC_MD5_DIGEST_LENGTH + 1];
CC_LONG md5Length = (CC_LONG)[self length];
CC_MD5( [self bytes], md5Length, md5Result );
NSMutableData * retData = [[NSMutableData alloc] init];
if ( nil == retData )
return nil;
[retData appendBytes:md5Result length:CC_MD5_DIGEST_LENGTH];
return retData;
}
- (NSString *)MD5String
{
NSData * value = [self MD5];
if ( value )
{
char tmp[16];
unsigned char * hex = (unsigned char *)malloc( 2048 + 1 );
unsigned char * bytes = (unsigned char *)[value bytes];
unsigned long length = [value length];
hex[0] = '\0';
for ( unsigned long i = 0; i < length; ++i )
{
sprintf( tmp, "%02X", bytes[i] );
strcat( (char *)hex, tmp );
}
NSString * result = [NSString stringWithUTF8String:(const char *)hex];
free( hex );
return result;
}
else
{
return nil;
}
}
+ (NSData *)fromResource:(NSString *)resName
{
NSString * extension = [resName pathExtension];
NSString * fullName = [resName substringToIndex:(resName.length - extension.length - 1)];
NSString * path = [[NSBundle mainBundle] pathForResource:fullName ofType:extension];
return [NSData dataWithContentsOfFile:path];
}
@end
================================================
FILE: Pod/Classes/Easy/Lib/PullRefresh/EZInfiniteScrolling.swift
================================================
//
// EZInfiniteScrolling.swift
// Demo
//
// Created by zhuchao on 15/5/15.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import Bond
let EZInfiniteScrollingViewHeight:CGFloat = 60.0
public enum EZInfiniteScrollingState {
case Stopped
case Triggered
case Loading
case Pulling
case Ended
}
public class Footer:UIView {
init(scrollView:UIScrollView,frame: CGRect = CGRectZero) {
super.init(frame: frame)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func resetScrollViewContentInset(scrollView:UIScrollView){
var currentInsets = scrollView.contentInset
let newBottom = scrollView.infiniteScrollingView!.originalBottomInset + scrollView.infiniteScrollingView!.extendBottom;
if newBottom != currentInsets.bottom {
currentInsets.bottom = newBottom
self.setScrollViewContentInset(currentInsets, scrollView: scrollView)
}
}
public func setScrollViewContentInsetForLoading(scrollView:UIScrollView){
var currentInsets = scrollView.contentInset
let newBottom = scrollView.infiniteScrollingView!.originalBottomInset + scrollView.infiniteScrollingView!.extendBottom + EZInfiniteScrollingViewHeight;
if newBottom != currentInsets.bottom {
currentInsets.bottom = newBottom
self.setScrollViewContentInset(currentInsets, scrollView: scrollView)
}
}
public func setScrollViewContentInset(contentInset:UIEdgeInsets,scrollView:UIScrollView){
UIView.animateWithDuration(0.3, delay: 0,
options: UIViewAnimationOptions.BeginFromCurrentState,
animations: {
scrollView.contentInset = contentInset
},completion:nil)
}
}
public class EZInfiniteScrollingView :UIView {
public var state = Observable(.Stopped)
public var extendBottom:CGFloat = 0.0
public var originalBottomInset:CGFloat = 0.0
private var infiniteScrollingHandler:(Void -> ())?
private var oldState = EZInfiniteScrollingState.Stopped
private func commonInit(){
self.autoresizingMask = UIViewAutoresizing.FlexibleWidth
self.state.observe{ [unowned self] state in
if state == .Loading && self.oldState == .Triggered {
self.infiniteScrollingHandler?()
}
self.oldState = state
}
}
override init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonInit()
}
func setCustomView(customView:UIView){
if customView.isKindOfClass(UIView) {
for view in self.subviews {
view.removeFromSuperview()
}
self.addSubview(customView)
let viewBounds = customView.bounds;
let origin = CGPointMake(
CGFloat(roundf(Float(self.bounds.size.width-viewBounds.size.width)/2)),
CGFloat(roundf(Float(self.bounds.size.height-viewBounds.size.height)/2)))
customView.frame = CGRectMake(origin.x, origin.y, viewBounds.size.width, viewBounds.size.height)
}
}
public func resetState(){
self.state.value = .Stopped;
}
public func startAnimating(){
self.state.value = .Loading;
}
public func stopAnimating(){
self.state.value = .Stopped;
}
public func setEnded(){
self.state.value = .Ended;
}
public override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer) {
let scrollView = object as! UIScrollView
if keyPath == "contentOffset" && scrollView.showsInfiniteScrolling {
if self.state.value != .Loading && self.state.value != .Ended && scrollView.contentSize.height > 0{
let scrollViewContentHeight = scrollView.contentSize.height;
let scrollOffsetThreshold = scrollViewContentHeight - scrollView.bounds.size.height + self.extendBottom
if !scrollView.dragging && self.state.value == .Triggered {
self.state.value = .Loading
}else if scrollView.dragging && self.state.value == .Pulling && scrollView.contentOffset.y - scrollOffsetThreshold > EZInfiniteScrollingViewHeight {
self.state.value = .Triggered
}else if scrollView.contentOffset.y - scrollOffsetThreshold <= 1 && self.state.value != .Stopped {
self.state.value = .Stopped
}else if scrollView.contentOffset.y - scrollOffsetThreshold > 0 && scrollView.contentOffset.y - scrollOffsetThreshold < EZInfiniteScrollingViewHeight {
self.state.value = .Pulling
}
}
}else if keyPath == "contentSize" && scrollView.contentSize.height >= scrollView.bounds.size.height && scrollView.showsInfiniteScrolling == false {
scrollView.showsInfiniteScrolling = true // 当contentSize.height大于scrollView的高度时才显示上拉加载
}
}
}
private var InfiniteScrollingViewHandle :UInt8 = 1
extension UIScrollView {
public var infiniteScrollingView : EZInfiniteScrollingView? {
get{
if let d: AnyObject = objc_getAssociatedObject(self, &InfiniteScrollingViewHandle) {
return d as? EZInfiniteScrollingView
}else{
return nil
}
}set (value){
objc_setAssociatedObject(self, &InfiniteScrollingViewHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var showsInfiniteScrolling :Bool {
get{
return !self.infiniteScrollingView!.hidden
}set(value){
if value {
self.addObserver(self.infiniteScrollingView!, forKeyPath: "contentOffset", options:NSKeyValueObservingOptions.New, context: nil)
self.infiniteScrollingView?.hidden = false
}else if (self.infiniteScrollingView?.hidden == false){
self.removeObserver(self.infiniteScrollingView!, forKeyPath: "contentOffset")
self.infiniteScrollingView?.hidden = true
}
}
}
public func addInfiniteScrollingWithActionHandler(customer:UIView? = nil,actionHandler:Void -> ()){
if self.infiniteScrollingView == nil {
let view = EZInfiniteScrollingView(frame: CGRectZero)
view.infiniteScrollingHandler = actionHandler
view.originalBottomInset = self.contentInset.bottom
view.hidden = true
self.infiniteScrollingView = view;
self.addObserver(self.infiniteScrollingView!, forKeyPath: "contentSize", options:NSKeyValueObservingOptions.New, context: nil)
self.addSubview(self.infiniteScrollingView!)
}
if customer == nil {
self.infiniteScrollingView?.setCustomView(PullFooter(scrollView: self))
}else{
self.infiniteScrollingView?.setCustomView(customer!)
}
}
public func triggerInfiniteScrolling(){
self.infiniteScrollingView?.oldState = .Triggered
self.infiniteScrollingView?.startAnimating()
}
}
================================================
FILE: Pod/Classes/Easy/Lib/PullRefresh/EZPullToRefresh.swift
================================================
//
// EZPullToRefresh.swift
// Demo
//
// Created by zhuchao on 15/5/15.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import Bond
let EZPullToRefreshViewHeight:CGFloat = 60.0
public enum EZPullToRefreshState {
case Stopped
case Triggered
case Loading
case Pulling
}
public class Header : UIView {
init(scrollView:UIScrollView,frame: CGRect = CGRectZero) {
super.init(frame: frame)
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
public func resetScrollViewContentInset(scrollView:UIScrollView){
var currentInsets = scrollView.contentInset
currentInsets.top = scrollView.pullToRefreshView!.originalTopInset
self.setScrollViewContentInset(currentInsets, scrollView: scrollView)
}
public func setScrollViewContentInsetForLoading(scrollView:UIScrollView){
let offset = max(EZPullToRefreshViewHeight, 0)
var currentInsets = scrollView.contentInset
currentInsets.top = max(offset, scrollView.pullToRefreshView!.originalTopInset + scrollView.pullToRefreshView!.bounds.size.height)
self.setScrollViewContentInset(currentInsets, scrollView: scrollView)
}
public func setScrollViewContentInset(contentInset:UIEdgeInsets,scrollView:UIScrollView){
UIView.animateWithDuration(0.3, delay: 0,
options: UIViewAnimationOptions.BeginFromCurrentState,
animations: {
scrollView.contentInset = contentInset
},completion:nil)
}
}
public class EZPullToRefreshView : UIView {
public var state = Observable(.Stopped)
public var originalTopInset:CGFloat = 0.0
public var originalBottomInset:CGFloat = 0.0
public var originalOffset:CGFloat = 0.0
private var pullToRefreshActionHandler:(Void -> ())?
private var oldState = EZPullToRefreshState.Stopped
private func commonInit(){
self.autoresizingMask = UIViewAutoresizing.FlexibleWidth
self.state.observe{ [unowned self] state in
if state == .Loading && self.oldState == .Triggered {
self.pullToRefreshActionHandler?()
}
self.oldState = state
}
}
override init(frame: CGRect) {
super.init(frame: frame)
self.commonInit()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonInit()
}
func setCustomView(customView:UIView){
if customView.isKindOfClass(UIView) {
for view in self.subviews {
view.removeFromSuperview()
}
self.addSubview(customView)
let viewBounds = customView.bounds;
let origin = CGPointMake(
CGFloat(roundf(Float(self.bounds.size.width-viewBounds.size.width)/2)),
CGFloat(roundf(Float(self.bounds.size.height-viewBounds.size.height)/2)))
customView.frame = CGRectMake(origin.x, origin.y, viewBounds.size.width, viewBounds.size.height)
}
}
public func startAnimating(){
self.state.value = .Loading
}
public func stopAnimating(){
self.state.value = .Stopped
}
public override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer) {
let scrollView = object as! UIScrollView
if keyPath == "contentOffset" && scrollView.showsPullToRefresh {
if self.state.value != .Loading{
let pullNum = scrollView.contentOffset.y + self.originalTopInset
if !scrollView.dragging && self.state.value == .Triggered {
self.state.value = .Loading
}else if scrollView.dragging && self.state.value == .Pulling && pullNum < -EZPullToRefreshViewHeight {
self.state.value = .Triggered
}else if pullNum <= -1 && pullNum > -EZPullToRefreshViewHeight {
self.state.value = .Pulling
}else if pullNum > -1 {
self.state.value = .Stopped
}
}
}
}
}
private var PullToRefreshViewHandle :UInt8 = 0
extension UIScrollView {
public var pullToRefreshView : EZPullToRefreshView? {
get{
if let d: AnyObject = objc_getAssociatedObject(self, &PullToRefreshViewHandle) {
return d as? EZPullToRefreshView
}else{
return nil
}
}set (value){
objc_setAssociatedObject(self, &PullToRefreshViewHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
var showsPullToRefresh :Bool {
get{
return !self.pullToRefreshView!.hidden
}set(value){
if value {
self.addObserver(self.pullToRefreshView!, forKeyPath: "contentOffset", options:NSKeyValueObservingOptions.New, context: nil)
self.pullToRefreshView?.hidden = false
}else{
self.removeObserver(self.pullToRefreshView!, forKeyPath: "contentOffset")
self.pullToRefreshView?.hidden = true
}
}
}
public func addPullToRefreshWithActionHandler(customer:UIView? = nil,actionHandler:Void -> ()){
if self.pullToRefreshView == nil {
let view = EZPullToRefreshView(frame: CGRectZero)
view.pullToRefreshActionHandler = actionHandler
view.originalTopInset = self.contentInset.top;
view.originalBottomInset = self.contentInset.bottom;
self.pullToRefreshView = view;
self.showsPullToRefresh = true;
self.addSubview(self.pullToRefreshView!)
}
if customer == nil {
self.pullToRefreshView?.setCustomView(PullHeader(scrollView: self))
}else{
self.pullToRefreshView?.setCustomView(customer!)
}
}
public func triggerPullToRefresh(){
self.pullToRefreshView?.oldState = .Triggered
self.pullToRefreshView?.startAnimating()
}
}
================================================
FILE: Pod/Classes/Easy/Lib/PullRefresh/PullFooter.swift
================================================
//
// PullFooter.swift
// Demo
//
// Created by zhuchao on 15/5/16.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import Bond
public class PullFooter : Footer {
var arrowImage:UIImageView!
var activityView:UIActivityIndicatorView!
var statusLabel:UILabel!
init (scrollView:UIScrollView){
super.init(
scrollView: scrollView,
frame: CGRectMake(0, 0, scrollView.superview!.size.width, EZInfiniteScrollingViewHeight))
self.commonInit()
scrollView.infiniteScrollingView!.frame = CGRectMake(0,scrollView.contentSize.height, scrollView.superview!.size.width, EZInfiniteScrollingViewHeight)
scrollView.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.New, context: nil)
scrollView.infiniteScrollingView!.state.observe{state in
switch (state){
case .Ended:
self.arrowImage.hidden = true
self.activityView.stopAnimating()
self.statusLabel.text = "没有了哦"
case .Stopped:
UIView.animateWithDuration(0.25){ [unowned self] in
self.resetScrollViewContentInset(scrollView)
self.arrowImage.hidden = false
self.activityView.stopAnimating()
self.statusLabel.text = "上拉加载"
self.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
}
case .Pulling:
UIView.animateWithDuration(0.25){ [unowned self] in
self.arrowImage.hidden = false
self.activityView.stopAnimating();
self.statusLabel.text = "上拉加载"
self.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
}
case .Triggered:
UIView.animateWithDuration(0.25){ [unowned self] in
self.arrowImage.hidden = false;
self.activityView.stopAnimating();
self.statusLabel.text = "释放加载"
self.arrowImage.transform = CGAffineTransformIdentity
}
case .Loading:
UIView.animateWithDuration(0.25){ [unowned self] in
self.setScrollViewContentInsetForLoading(scrollView)
self.arrowImage.hidden = true;
self.activityView.startAnimating();
self.statusLabel.text = "正在加载..."
}
}
}
}
public override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer) {
let scrollView = object as! UIScrollView
if keyPath == "contentSize" && scrollView.contentSize.height > scrollView.bounds.size.height && scrollView.bounds.size.height > 0 {
scrollView.infiniteScrollingView!.frame = CGRectMake(0, scrollView.contentSize.height, scrollView.superview!.size.width,EZInfiniteScrollingViewHeight)
}
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonInit()
}
func commonInit(){
let bundle = NSBundle(forClass: self.dynamicType)
let url = bundle.URLForResource("EasyIOS-Swift", withExtension: "bundle")
let imageBundle = NSBundle(URL: url!)
if imageBundle?.loaded == false {
imageBundle?.load()
}
let arrow = UIImage(contentsOfFile: imageBundle!.pathForResource("arrow-down@2x", ofType: "png")!)
arrowImage = UIImageView(image: arrow)
arrowImage.autoresizingMask = [UIViewAutoresizing.FlexibleLeftMargin, UIViewAutoresizing.FlexibleRightMargin]
self.addSubview(arrowImage)
activityView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
activityView.autoresizingMask = arrowImage.autoresizingMask;
activityView.hidden = true
self.addSubview(activityView)
statusLabel = UILabel()
statusLabel.autoresizingMask = UIViewAutoresizing.FlexibleWidth;
statusLabel.font = UIFont.boldSystemFontOfSize(13);
statusLabel.textColor = UIColor.blackColor();
statusLabel.backgroundColor = UIColor.clearColor();
statusLabel.textAlignment = NSTextAlignment.Center;
self.addSubview(statusLabel)
arrowImage.snp_makeConstraints(){[unowned self] (make) -> Void in
make.centerY.equalTo(self.arrowImage.superview!)
}
activityView.snp_makeConstraints(){[unowned self] (make) -> Void in
make.edges.equalTo(self.arrowImage)
}
statusLabel.snp_makeConstraints(){[unowned self] (make) -> Void in
make.leading.equalTo(self.arrowImage).offset(30.0)
make.center.equalTo(self.statusLabel.superview!)
}
}
}
================================================
FILE: Pod/Classes/Easy/Lib/PullRefresh/PullHeader.swift
================================================
//
// PullHeader.swift
// Demo
//
// Created by zhuchao on 15/5/16.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import SnapKit
import Bond
public class PullHeader : Header {
var arrowImage:UIImageView!
var activityView:UIActivityIndicatorView!
var statusLabel:UILabel!
var lastUpdateTimeLabel:UILabel!
init (scrollView:UIScrollView){
super.init(
scrollView: scrollView,
frame: CGRectMake(0, 0, scrollView.size.width, EZPullToRefreshViewHeight))
self.commonInit()
scrollView.pullToRefreshView!.frame = CGRectMake(0, -EZPullToRefreshViewHeight, scrollView.superview!.size.width, EZPullToRefreshViewHeight)
scrollView.pullToRefreshView!.state.observe{state in
switch (state){
case .Stopped:
UIView.animateWithDuration(0.25){ [unowned self] in
self.resetScrollViewContentInset(scrollView)
self.arrowImage.hidden = false
self.activityView.stopAnimating()
self.statusLabel.text = "下拉可以刷新"
self.arrowImage.transform = CGAffineTransformIdentity
self.updateTimeLabel(NSDate())
}
case .Pulling:
UIView.animateWithDuration(0.25){ [unowned self] in
self.arrowImage.hidden = false
self.activityView.stopAnimating();
self.statusLabel.text = "下拉可以刷新"
self.arrowImage.transform = CGAffineTransformIdentity;
}
case .Triggered:
UIView.animateWithDuration(0.25){ [unowned self] in
self.arrowImage.hidden = false;
self.activityView.stopAnimating();
self.statusLabel.text = "释放可以刷新"
self.arrowImage.transform = CGAffineTransformMakeRotation(CGFloat(M_PI));
}
case .Loading:
UIView.animateWithDuration(0.25){ [unowned self] in
self.setScrollViewContentInsetForLoading(scrollView)
self.arrowImage.hidden = true;
self.activityView.startAnimating();
self.statusLabel.text = "正在刷新..."
}
}
}
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.commonInit()
}
func commonInit(){
let bundle = NSBundle(forClass: self.dynamicType)
let url = bundle.URLForResource("EasyIOS-Swift", withExtension: "bundle")
let imageBundle = NSBundle(URL: url!)
if imageBundle?.loaded == false {
imageBundle?.load()
}
let arrow = UIImage(contentsOfFile: imageBundle!.pathForResource("arrow-down@2x", ofType: "png")!)
arrowImage = UIImageView(image: arrow)
arrowImage.autoresizingMask = [UIViewAutoresizing.FlexibleLeftMargin, UIViewAutoresizing.FlexibleRightMargin]
self.addSubview(arrowImage)
activityView = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
activityView.autoresizingMask = arrowImage.autoresizingMask;
activityView.hidden = true
self.addSubview(activityView)
statusLabel = UILabel()
statusLabel.autoresizingMask = UIViewAutoresizing.FlexibleWidth;
statusLabel.font = UIFont.boldSystemFontOfSize(13);
statusLabel.textColor = UIColor.blackColor();
statusLabel.backgroundColor = UIColor.clearColor();
statusLabel.textAlignment = NSTextAlignment.Center;
self.addSubview(statusLabel)
lastUpdateTimeLabel = UILabel()
lastUpdateTimeLabel.autoresizingMask = UIViewAutoresizing.FlexibleWidth;
lastUpdateTimeLabel.font = UIFont.boldSystemFontOfSize(12);
lastUpdateTimeLabel.textColor = UIColor.blackColor();
lastUpdateTimeLabel.backgroundColor = UIColor.clearColor();
lastUpdateTimeLabel.textAlignment = NSTextAlignment.Center;
self.updateTimeLabel(NSDate())
self.addSubview(lastUpdateTimeLabel)
arrowImage.snp_makeConstraints(){[unowned self] (make) -> Void in
make.centerY.equalTo(self.arrowImage.superview!)
}
activityView.snp_makeConstraints(){[unowned self] (make) -> Void in
make.edges.equalTo(self.arrowImage)
}
statusLabel.snp_makeConstraints(){[unowned self] (make) -> Void in
make.top.equalTo(self.statusLabel.superview!).offset(10.0)
make.centerX.equalTo(self.statusLabel.superview!)
}
lastUpdateTimeLabel.snp_makeConstraints(){[unowned self] (make) -> Void in
make.bottom.equalTo(self.lastUpdateTimeLabel.superview!).offset(-15.0)
make.centerX.equalTo(self.lastUpdateTimeLabel.superview!)
make.leading.equalTo(self.arrowImage).offset(40)
}
}
func updateTimeLabel(date:NSDate?){
if let aDate = date {
// 1.获得年月日
let calendar = NSCalendar.currentCalendar()
let unitFlags: NSCalendarUnit = [NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.Day, NSCalendarUnit.Hour, NSCalendarUnit.Minute]
let cmp1 = calendar.components(unitFlags, fromDate: aDate)
let now = calendar.components(unitFlags, fromDate: NSDate())
// 2.格式化日期
let formatter = NSDateFormatter()
if (cmp1.day == now.day) { // 今天
formatter.dateFormat = "今天 HH:mm";
} else if (cmp1.year == now.year) { // 今年
formatter.dateFormat = "MM-dd HH:mm";
} else {
formatter.dateFormat = "yyyy-MM-dd HH:mm";
}
// 3.显示日期
self.lastUpdateTimeLabel.text = "最后更新:" + formatter.stringFromDate(aDate)
}
}
}
================================================
FILE: Pod/Classes/Extend/EUI/Defines.h
================================================
//
// GTMDefines.h
//
// Copyright 2008 Google Inc.
//
// Licensed 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
// Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs
#ifndef MAC_OS_X_VERSION_10_5
#define MAC_OS_X_VERSION_10_5 1050
#endif
#ifndef MAC_OS_X_VERSION_10_6
#define MAC_OS_X_VERSION_10_6 1060
#endif
// ----------------------------------------------------------------------------
// CPP symbols that can be overridden in a prefix to control how the toolbox
// is compiled.
// ----------------------------------------------------------------------------
// GTMHTTPFetcher will support logging by default but only hook its input
// stream support for logging when requested. You can control the inclusion of
// the code by providing your own definitions for these w/in a prefix header.
//
#ifndef GTM_HTTPFETCHER_ENABLE_LOGGING
#define GTM_HTTPFETCHER_ENABLE_LOGGING 1
#endif // GTM_HTTPFETCHER_ENABLE_LOGGING
#ifndef GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING
#define GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING 0
#endif // GTM_HTTPFETCHER_ENABLE_INPUTSTREAM_LOGGING
// By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and
// GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens
// when a validation fails. If you implement your own validators, you may want
// to control their internals using the same macros for consistency.
#ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT
#define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0
#endif
// Give ourselves a consistent way to do inlines. Apple's macros even use
// a few different actual definitions, so we're based off of the foundation
// one.
#if !defined(GTM_INLINE)
#if defined (__GNUC__) && (__GNUC__ == 4)
#define GTM_INLINE static __inline__ __attribute__((always_inline))
#else
#define GTM_INLINE static __inline__
#endif
#endif
// Give ourselves a consistent way of doing externs that links up nicely
// when mixing objc and objc++
#if !defined (GTM_EXTERN)
#if defined __cplusplus
#define GTM_EXTERN extern "C"
#else
#define GTM_EXTERN extern
#endif
#endif
// Give ourselves a consistent way of exporting things if we have visibility
// set to hidden.
#if !defined (GTM_EXPORT)
#define GTM_EXPORT __attribute__((visibility("default")))
#endif
// _GTMDevLog & _GTMDevAssert
//
// _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for
// developer level errors. This implementation simply macros to NSLog/NSAssert.
// It is not intended to be a general logging/reporting system.
//
// Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert
// for a little more background on the usage of these macros.
//
// _GTMDevLog log some error/problem in debug builds
// _GTMDevAssert assert if conditon isn't met w/in a method/function
// in all builds.
//
// To replace this system, just provide different macro definitions in your
// prefix header. Remember, any implementation you provide *must* be thread
// safe since this could be called by anything in what ever situtation it has
// been placed in.
//
// We only define the simple macros if nothing else has defined this.
#ifndef _GTMDevLog
#ifdef DEBUG
#define _GTMDevLog(...) NSLog(__VA_ARGS__)
#else
#define _GTMDevLog(...) do { } while (0)
#endif
#endif // _GTMDevLog
// Declared here so that it can easily be used for logging tracking if
// necessary. See GTMUnitTestDevLog.h for details.
@class NSString;
GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...);
#ifndef _GTMDevAssert
// we directly invoke the NSAssert handler so we can pass on the varargs
// (NSAssert doesn't have a macro we can use that takes varargs)
#if !defined(NS_BLOCK_ASSERTIONS)
#define _GTMDevAssert(condition, ...) \
do { \
if (!(condition)) { \
[[NSAssertionHandler currentHandler] \
handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \
file:[NSString stringWithUTF8String:__FILE__] \
lineNumber:__LINE__ \
description:__VA_ARGS__]; \
} \
} while(0)
#else // !defined(NS_BLOCK_ASSERTIONS)
#define _GTMDevAssert(condition, ...) do { } while (0)
#endif // !defined(NS_BLOCK_ASSERTIONS)
#endif // _GTMDevAssert
// _GTMCompileAssert
// _GTMCompileAssert is an assert that is meant to fire at compile time if you
// want to check things at compile instead of runtime. For example if you
// want to check that a wchar is 4 bytes instead of 2 you would use
// _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X)
// Note that the second "arg" is not in quotes, and must be a valid processor
// symbol in it's own right (no spaces, punctuation etc).
// Wrapping this in an #ifndef allows external groups to define their own
// compile time assert scheme.
#ifndef _GTMCompileAssert
// We got this technique from here:
// http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html
#define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg
#define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg)
#define _GTMCompileAssert(test, msg) \
typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
#endif // _GTMCompileAssert
// Macro to allow fast enumeration when building for 10.5 or later, and
// reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration
// does keys, so pick the right thing, nothing is done on the FastEnumeration
// side to be sure you're getting what you wanted.
#ifndef GTM_FOREACH_OBJECT
#if defined(TARGET_OS_IPHONE) || (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
#define GTM_FOREACH_OBJECT(element, collection) \
for (element in collection)
#define GTM_FOREACH_KEY(element, collection) \
for (element in collection)
#else
#define GTM_FOREACH_OBJECT(element, collection) \
for (NSEnumerator * _ ## element ## _enum = [collection objectEnumerator]; \
(element = [_ ## element ## _enum nextObject]) != nil; )
#define GTM_FOREACH_KEY(element, collection) \
for (NSEnumerator * _ ## element ## _enum = [collection keyEnumerator]; \
(element = [_ ## element ## _enum nextObject]) != nil; )
#endif
#endif
// ============================================================================
// ----------------------------------------------------------------------------
// CPP symbols defined based on the project settings so the GTM code has
// simple things to test against w/o scattering the knowledge of project
// setting through all the code.
// ----------------------------------------------------------------------------
// Provide a single constant CPP symbol that all of GTM uses for ifdefing
// iPhone code.
#include
#if TARGET_OS_IPHONE // iPhone SDK
// For iPhone specific stuff
#define GTM_IPHONE_SDK 1
#if TARGET_IPHONE_SIMULATOR
#define GTM_IPHONE_SIMULATOR 1
#else
#define GTM_IPHONE_DEVICE 1
#endif // TARGET_IPHONE_SIMULATOR
#else
// For MacOS specific stuff
#define GTM_MACOS_SDK 1
#endif
// Provide a symbol to include/exclude extra code for GC support. (This mainly
// just controls the inclusion of finalize methods).
#ifndef GTM_SUPPORT_GC
#if GTM_IPHONE_SDK
// iPhone never needs GC
#define GTM_SUPPORT_GC 0
#else
// We can't find a symbol to tell if GC is supported/required, so best we
// do on Mac targets is include it if we're on 10.5 or later.
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
#define GTM_SUPPORT_GC 0
#else
#define GTM_SUPPORT_GC 1
#endif
#endif
#endif
// To simplify support for 64bit (and Leopard in general), we provide the type
// defines for non Leopard SDKs
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
// NSInteger/NSUInteger and Max/Mins
#ifndef NSINTEGER_DEFINED
#if __LP64__ || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
#define NSIntegerMax LONG_MAX
#define NSIntegerMin LONG_MIN
#define NSUIntegerMax ULONG_MAX
#define NSINTEGER_DEFINED 1
#endif // NSINTEGER_DEFINED
// CGFloat
#ifndef CGFLOAT_DEFINED
#if defined(__LP64__) && __LP64__
// This really is an untested path (64bit on Tiger?)
typedef double CGFloat;
#define CGFLOAT_MIN DBL_MIN
#define CGFLOAT_MAX DBL_MAX
#define CGFLOAT_IS_DOUBLE 1
#else /* !defined(__LP64__) || !__LP64__ */
typedef float CGFloat;
#define CGFLOAT_MIN FLT_MIN
#define CGFLOAT_MAX FLT_MAX
#define CGFLOAT_IS_DOUBLE 0
#endif /* !defined(__LP64__) || !__LP64__ */
#define CGFLOAT_DEFINED 1
#endif // CGFLOAT_DEFINED
#endif // MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
================================================
FILE: Pod/Classes/Extend/EUI/DesEncrypt.h
================================================
//
// DesEncrypt.h
// medical
//
// Created by zhuchao on 15/5/4.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
#import
@interface DesEncrypt : NSObject
+ (NSString *)encryptWithText:(NSString *)sText key:(NSString *)key;//加密
+ (NSString *)decryptWithText:(NSString *)sText key:(NSString *)key;//解密
@end
================================================
FILE: Pod/Classes/Extend/EUI/DesEncrypt.m
================================================
//
// DesEncrypt.m
// medical
//
// Created by zhuchao on 15/5/4.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
#import "DesEncrypt.h"
#import
@implementation DesEncrypt
+ (NSString *)encryptWithText:(NSString *)sText key:(NSString *)key
{
//kCCEncrypt 加密
return [self encrypt:sText encryptOrDecrypt:kCCEncrypt key:[NSString stringWithFormat:@"%@",key]];
}
+ (NSString *)decryptWithText:(NSString *)sText key:(NSString *)key
{
//kCCDecrypt 解密
return [self encrypt:sText encryptOrDecrypt:kCCDecrypt key:[NSString stringWithFormat:@"%@",key]];
}
+ (NSString *)encrypt:(NSString *)sText encryptOrDecrypt:(CCOperation)encryptOperation key:(NSString *)key
{
const void *dataIn;
size_t dataInLength;
if (encryptOperation == kCCDecrypt)//传递过来的是decrypt 解码
{
//解码 base64
// [[sText dataUsingEncoding:NSUTF8StringEncoding] base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength]
NSData *decryptData = [[NSData alloc]initWithBase64EncodedString:sText options:NSDataBase64DecodingIgnoreUnknownCharacters];//转成utf-8并decode
dataInLength = [decryptData length];
dataIn = [decryptData bytes];
}
else //encrypt
{
NSData* encryptData = [sText dataUsingEncoding:NSUTF8StringEncoding];
dataInLength = [encryptData length];
dataIn = (const void *)[encryptData bytes];
}
/*
DES加密 :用CCCrypt函数加密一下,然后用base64编码下,传过去
DES解密 :把收到的数据根据base64,decode一下,然后再用CCCrypt函数解密,得到原本的数据
*/
CCCryptorStatus ccStatus;
uint8_t *dataOut = NULL; //可以理解位type/typedef 的缩写(有效的维护了代码,比如:一个人用int,一个人用long。最好用typedef来定义)
size_t dataOutAvailable = 0; //size_t 是操作符sizeof返回的结果类型
size_t dataOutMoved = 0;
dataOutAvailable = (dataInLength + kCCBlockSizeDES) & ~(kCCBlockSizeDES - 1);
dataOut = malloc( dataOutAvailable * sizeof(uint8_t));
memset((void *)dataOut, 0x0, dataOutAvailable);//将已开辟内存空间buffer的首 1 个字节的值设为值 0
NSString *initIv = @"12345678";
const void *vkey = (const void *) [key UTF8String];
const void *iv = (const void *) [initIv UTF8String];
//CCCrypt函数 加密/解密
ccStatus = CCCrypt(encryptOperation,// 加密/解密
kCCAlgorithmDES,// 加密根据哪个标准(des,3des,aes。。。。)
kCCOptionPKCS7Padding,// 选项分组密码算法(des:对每块分组加一次密 3DES:对每块分组加三个不同的密)
vkey, //密钥 加密和解密的密钥必须一致
kCCKeySizeDES,// DES 密钥的大小(kCCKeySizeDES=8)
iv, // 可选的初始矢量
dataIn, // 数据的存储单元
dataInLength,// 数据的大小
(void *)dataOut,// 用于返回数据
dataOutAvailable,
&dataOutMoved);
NSString *result = nil;
if (encryptOperation == kCCDecrypt)//encryptOperation==1 解码
{
//得到解密出来的data数据,改变为utf-8的字符串
result = [[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved] encoding:NSUTF8StringEncoding];
}
else //encryptOperation==0 (加密过程中,把加好密的数据转成base64的)
{
//编码 base64
NSData *data = [NSData dataWithBytes:(const void *)dataOut length:(NSUInteger)dataOutMoved];
result = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
return result;
}
@end
================================================
FILE: Pod/Classes/Extend/EUI/ENSObject.swift
================================================
//
// ENSObject.swift
// Pods
//
// Created by zhuchao on 15/7/21.
//
//
import Foundation
import JavaScriptCore
@objc public protocol ENSObject:JSExport{
func val(keyPath:String) -> AnyObject?
func attr(keyPath:String,_ value:AnyObject?)
func attrs(dict:[NSObject : AnyObject]!)
func call(selector:String)
func call(selector:String,withObject object:AnyObject?)
}
public extension NSObject{
public func call(selector:String){
NSThread.detachNewThreadSelector(Selector(selector), toTarget:self, withObject: nil)
}
public func call(selector:String,withObject object:AnyObject?){
NSThread.detachNewThreadSelector(Selector(selector), toTarget:self, withObject: object)
}
public func attr(key:String,_ value:AnyObject?) {
SwiftTryCatch.`try`({
if let str = value as? String {
self.setValue(str.anyValue(key.toKeyPath), forKeyPath: key.toKeyPath)
}else{
self.setValue(value, forKeyPath: key.toKeyPath)
}
}, `catch`: { (error) in
print("JS Error:\(error.description)")
}, finally: nil)
}
public func attrs(var dict:[String : AnyObject]!){
SwiftTryCatch.`try`({
for (key, value) in dict {
if let str = value as? String {
dict[key.toKeyPath] = str.anyValue(key.toKeyPath)
}
}
self.setValuesForKeysWithDictionary(dict)
}, `catch`: { (error) in
print("JS Error:\(error.description)")
}, finally: nil)
}
public func val(key:String) -> AnyObject? {
var result:AnyObject?
SwiftTryCatch.`try`({
result = self.valueForKeyPath(key.toKeyPath)
}, `catch`: { (error) in
print("JS Error:\(error.description)")
}, finally: nil)
return result
}
}
@objc public protocol EZActionJSExport:JSExport{
static func SEND_IQ_CACHE (req:EZRequest)
static func SEND_CACHE (req:EZRequest)
static func SEND (req:EZRequest)
static func Upload (req:EZRequest)
static func Download (req:EZRequest)
}
================================================
FILE: Pod/Classes/Extend/EUI/EUI+ButtonProperty.swift
================================================
//
// EUI+ButtonProperty.swift
// medical
//
// Created by zhuchao on 15/5/1.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
class ButtonProperty:ViewProperty{
var highlightedStyle = ""
var disabledStyle = ""
var selectedStyle = ""
var applicationStyle = ""
var reservedStyle = ""
var highlightedText:String?
var disabledText:String?
var selectedText:String?
var applicationText:String?
var reservedText:String?
var onEvent:SelectorAction?
override func view() -> UIButton{
let view = UIButton()
view.tagProperty = self
if self.style != "" {
view.setAttributedTitle(NSAttributedString(fromHTMLData: self.contentText?.toData(), attributes: ["html":self.style]), forState: UIControlState.Normal)
}
if self.highlightedText != nil {
view.setAttributedTitle(NSAttributedString(fromHTMLData: self.highlightedText?.toData(), attributes: ["html":self.highlightedStyle]), forState: UIControlState.Highlighted)
}
if self.disabledText != nil {
view.setAttributedTitle(NSAttributedString(fromHTMLData: self.disabledText?.toData(), attributes: ["html":self.disabledStyle]), forState: UIControlState.Disabled)
}
if self.selectedText != nil {
view.setAttributedTitle(NSAttributedString(fromHTMLData: self.selectedText?.toData(), attributes: ["html":self.selectedStyle]), forState: UIControlState.Selected)
}
if self.applicationText != nil {
view.setAttributedTitle(NSAttributedString(fromHTMLData: self.applicationText?.toData(), attributes: ["html":self.applicationStyle]), forState: UIControlState.Application)
}
if self.reservedText != nil {
view.setAttributedTitle(NSAttributedString(fromHTMLData: self.reservedText?.toData(), attributes: ["html":self.reservedStyle]), forState: UIControlState.Reserved)
}
self.renderViewStyle(view)
return view
}
override func renderTag(pelement: OGElement) {
self.tagOut += ["highlighted","disabled","selected","application","reserved","disabled-text",
"selected-text","application-text","reserved-text","highlighted-text","onevent"]
super.renderTag(pelement)
if let highlightedStyle = EUIParse.string(pelement,key: "highlighted") {
self.highlightedStyle = "html{" + highlightedStyle + "}"
}
if let disabledStyle = EUIParse.string(pelement,key: "disabled") {
self.disabledStyle = "html{" + disabledStyle + "}"
}
if let selectedStyle = EUIParse.string(pelement,key: "selected") {
self.selectedStyle = "html{" + selectedStyle + "}"
}
if let applicationStyle = EUIParse.string(pelement,key: "application") {
self.applicationStyle = "html{" + applicationStyle + "}"
}
if let reservedStyle = EUIParse.string(pelement,key: "reserved") {
self.reservedStyle = "html{" + reservedStyle + "}"
}
self.disabledText = EUIParse.string(pelement,key: "disabled-text")
self.selectedText = EUIParse.string(pelement,key: "selected-text")
self.applicationText = EUIParse.string(pelement,key: "application-text")
self.reservedText = EUIParse.string(pelement,key: "reserved-text")
self.highlightedText = EUIParse.string(pelement,key: "highlighted-text")
if let theSelector = EUIParse.string(pelement, key: "onevent") {
var values = theSelector.trimArrayBy(":")
if values.count == 2 {
self.onEvent = SelectorAction(selector: values[1], event: values[0])
}
}
var html = ""
for child in pelement.children
{
html += child.html().trim
}
if let newHtml = self.bindTheKeyPath(html, key: "text") {
html = newHtml
}
self.contentText = html
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUI+CollectionViewProperty.swift
================================================
//
// EUI+CollectionViewProperty.swift
// medical
//
// Created by zhuchao on 15/5/10.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import Bond
class CollectionViewProperty: ScrollViewProperty {
var separatorInset:UIEdgeInsets?
var reuseCell = Dictionary()
var flowLayout = Dictionary()
var layout:String?
override func view() -> UICollectionView{
let view = UICollectionView(frame: CGRectZero, collectionViewLayout: self.getLayout())
view.tagProperty = self
self.renderViewStyle(view)
for (reuseId,_) in self.reuseCell {
view.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseId)
}
return view
}
override func renderTag(pelement:OGElement){
self.tagOut += ["delegate","datasource","flow-layout","layout"]
super.renderTag(pelement)
if let layout = EUIParse.string(pelement, key: "flow-layout") {
let dict = layout.trimArrayBy(";")
for value in dict {
var array = value.trimArrayBy(":")
let key = array[0] as String
let val = array[1] as String
self.flowLayout[key.toKeyPath] = val
}
}
self.layout = EUIParse.string(pelement, key: "layout")
}
func getLayout() -> UICollectionViewLayout{
if let customlayout = self.layout,let nsobject = NSObject(fromString: customlayout) as? UICollectionViewLayout {
return nsobject
}
let layout = UICollectionViewFlowLayout()
for (key,value) in self.flowLayout{
if key == "minimumLineSpacing" || key == "minimumInteritemSpacing"{
layout.setValue(value.floatValue, forKeyPath: key)
}else if key == "itemSize" {
layout.itemSize = CGSizeFromString(value)
}else if key == "estimatedItemSize" {
layout.estimatedItemSize = CGSizeFromString(value)
}else if key == "headerReferenceSize" {
layout.headerReferenceSize = CGSizeFromString(value)
}else if key == "footerReferenceSize"{
layout.footerReferenceSize = CGSizeFromString(value)
}else if key == "sectionInset" {
layout.sectionInset = UIEdgeInsetsFromString(value)
}else if key == "scrollDirection" {
if value.lowercaseString == "Vertical".lowercaseString {
layout.scrollDirection = .Vertical
}else if value.lowercaseString == "Horizontal".lowercaseString {
layout.scrollDirection = .Horizontal
}
}
}
return layout
}
override func childLoop(pelement: OGElement) {
for element in pelement.children {
if let ele = element as? OGElement,
let type = EUIParse.string(ele, key: "type"),
let tagId = EUIParse.string(ele, key: "id"),
let property = EUIParse.loopElement(ele){
if type.lowercaseString == "cell" {
self.reuseCell[tagId] = property
}
}
}
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUI+ImageProperty.swift
================================================
//
// EUI+ImageProperty.swift
// medical
//
// Created by zhuchao on 15/5/1.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
class ImageProperty:ViewProperty{
var src = ""
override func view() -> UIImageView{
let view = UIImageView()
view.tagProperty = self
if !self.src.characters.isEmpty {
if self.src.hasPrefix("http") {
view.kf_setImageWithURL(NSURL(string: self.src)!)
}else{
view.image = UIImage(named: self.src)
}
}
self.renderViewStyle(view)
for subTag in self.subTags {
view.addSubview(subTag.getView())
}
return view
}
override func renderTag(pelement:OGElement){
self.tagOut += ["src"]
super.renderTag(pelement)
if let src = EUIParse.string(pelement,key:"src"),let filterHtml = self.bindTheKeyPath(src, key: "src") {
self.src = filterHtml
}
}
override func childLoop(pelement: OGElement) {
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUI+LabelProperty.swift
================================================
//
// EUI+LabelProperty.swift
// medical
//
// Created by zhuchao on 15/5/1.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
import JavaScriptCore
import TTTAttributedLabel
class LabelProperty:ViewProperty{
var linkStyle = Dictionary()
var activeLinkStyle = Dictionary()
var textAlignment:NSTextAlignment = .Left
override func view() -> UIView{
if self.style.characters.isEmpty {
let view = UILabel()
view.tagProperty = self
view.text = self.contentText
self.renderViewStyle(view)
return view
}else{
let view = TTTAttributedLabel(frame: CGRectZero)
view.tagProperty = self
if self.linkStyle.count > 0 {
view.linkAttributes = self.linkStyle
}
if self.activeLinkStyle.count > 0 {
view.activeLinkAttributes = self.activeLinkStyle
}
view.setText(NSAttributedString(fromHTMLData: self.contentText?.toData(), attributes: ["dict":self.style]))
self.renderViewStyle(view)
return view
}
}
override func renderTag(pelement: OGElement) {
self.tagOut += ["link-style","active-link-style","text-alignment"]
super.renderTag(pelement)
if let textAlignment = EUIParse.string(pelement,key:"text-alignment") {
self.textAlignment = textAlignment.textAlignment
}
if let linkStyle = EUIParse.string(pelement,key:"link-style") {
self.linkStyle = linkStyle.linkStyleDict
}
if let linkStyle = EUIParse.string(pelement,key:"active-link-style") {
self.activeLinkStyle = linkStyle.linkStyleDict
}
var html = ""
for child in pelement.children
{
html += child.html().trim
}
var bindKey = "text"
if !self.style.characters.isEmpty {
bindKey = "TTText"
}
if let newHtml = self.bindTheKeyPath(html, key: bindKey) {
html = newHtml
}
self.contentText = html
}
override func childLoop(pelement: OGElement) {
}
override func renderViewStyle(view:UIView){
super.renderViewStyle(view)
let sview = view as! UILabel
sview.textAlignment = self.textAlignment
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUI+ScrollViewProperty.swift
================================================
//
// EUI+ScrollViewProperty.swift
// medical
//
// Created by zhuchao on 15/5/2.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
class ScrollViewProperty:ViewProperty{
var contentInset = UIEdgeInsetsZero
var contentOffset = CGPointZero
var contentSize = CGSizeZero
var scrollIndicatorInsets = UIEdgeInsetsZero
var indicatorStyle:UIScrollViewIndicatorStyle = .Default
var pullToRefresh:PullRefreshAction?
var infiniteScrolling:InfiniteScrollingAction?
override func view() -> UIScrollView{
let view = UIScrollView()
view.tagProperty = self
self.renderViewStyle(view)
for subTag in self.subTags {
view.addSubview(subTag.getView())
}
return view
}
override func renderViewStyle(view: UIView) {
super.renderViewStyle(view)
let sview = view as! UIScrollView
sview.contentInset = self.contentInset
sview.contentOffset = self.contentOffset
sview.contentSize = self.contentSize
sview.scrollIndicatorInsets = self.scrollIndicatorInsets
sview.indicatorStyle = self.indicatorStyle
}
override func renderTag(pelement:OGElement){
self.tagOut += ["content-offset","content-inset","content-size","scroll-indicator-insets","indicator-style","pull-to-refresh","infinite-scrolling"]
super.renderTag(pelement)
if let contentInset = EUIParse.string(pelement,key:"content-inset") {
self.contentInset = UIEdgeInsetsFromString(contentInset)
}
if let contentOffset = EUIParse.string(pelement,key:"content-offset") {
self.contentOffset = CGPointFromString(contentOffset)
}
if let contentSize = EUIParse.string(pelement,key:"content-size") {
self.contentSize = CGSizeFromString(contentSize)
}
if let indicatorStyle = EUIParse.string(pelement,key:"indicator-style") {
self.indicatorStyle = indicatorStyle.scrollViewIndicatorStyle
}
if let scrollIndicatorInsets = EUIParse.string(pelement,key:"scroll-indicator-insets") {
self.scrollIndicatorInsets = UIEdgeInsetsFromString(scrollIndicatorInsets)
}
if let thePullRefresh = EUIParse.string(pelement, key: "pull-to-refresh") {
var values = thePullRefresh.trimArray
if values.count == 1 {
self.pullToRefresh = PullRefreshAction(selector: values[0])
}else if values.count == 2 {
self.pullToRefresh = PullRefreshAction(selector: values[0], viewClass: values[1])
}
}
if let theInfiniteScrolling = EUIParse.string(pelement, key: "infinite-scrolling") {
var values = theInfiniteScrolling.trimArray
if values.count == 1 {
self.infiniteScrolling = InfiniteScrollingAction(selector: values[0])
}else if values.count == 2 {
self.infiniteScrolling = InfiniteScrollingAction(selector: values[0], viewClass: values[1])
}
}
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUI+TableViewProperty.swift
================================================
//
// EUI+TableViewProperty.swift
// medical
//
// Created by zhuchao on 15/5/2.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
import Bond
class TableViewProperty:ScrollViewProperty{
var tableViewStyle = UITableViewStyle.Plain
var separatorInset:UIEdgeInsets?
var rowHeight = UITableViewAutomaticDimension
var reuseCell = Dictionary()
var sectionView = Dictionary()
var separatorStyle = UITableViewCellSeparatorStyle.SingleLine
override func view() -> UITableView{
let view = UITableView(frame: CGRectZero, style: self.tableViewStyle)
view.tagProperty = self
view.rowHeight = self.rowHeight
view.separatorStyle = self.separatorStyle;
if let inset = self.separatorInset {
view.separatorInset = inset;
}
self.renderViewStyle(view)
for (reuseId,_) in self.reuseCell {
view.registerClass(UITableViewCell.self, forCellReuseIdentifier: reuseId)
}
return view
}
override func renderTag(pelement:OGElement){
self.tagOut += ["table-view-style","separator-inset","delegate","datasource","row-height","separator-style"]
super.renderTag(pelement)
if let style = EUIParse.string(pelement,key:"table-view-style") {
self.tableViewStyle = style.tableViewStyle
}
if let rowHeight = EUIParse.string(pelement, key: "row-height") {
self.rowHeight = rowHeight.floatValue
}
if let separatorInset = EUIParse.string(pelement,key:"separator-inset") {
self.separatorInset = UIEdgeInsetsFromString(separatorInset)
}
if let separatorStyle = EUIParse.string(pelement, key: "separator-style") {
self.separatorStyle = separatorStyle.separatorStyle
}
}
override func childLoop(pelement: OGElement) {
for element in pelement.children {
if let ele = element as? OGElement,
let type = EUIParse.string(ele, key: "type"),
let tagId = EUIParse.string(ele, key: "id"),
let property = EUIParse.loopElement(ele){
if type.lowercaseString == "cell" || type.lowercaseString == "UITableViewCell" {
self.reuseCell[tagId] = property
}else if type.lowercaseString == "section" || type.lowercaseString == "UITableViewSection"{
self.sectionView[tagId] = property
}
}
}
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUI+TextFieldProperty.swift
================================================
//
// EUI+TextFieldProperty.swift
// medical
//
// Created by zhuchao on 15/5/1.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
class TextFieldProperty:ViewProperty{
var placeholder:NSData?
var placeholderStyle = ""
var text:NSData?
var keyboardType = UIKeyboardType.Default
override func view() -> UITextField{
let view = UITextField()
view.tagProperty = self
view.keyboardType = self.keyboardType
let str = NSAttributedString(fromHTMLData:self.text, attributes: ["html":self.style])
view.defaultTextAttributes = str.attributesAtIndex(0, effectiveRange:nil)
view.attributedPlaceholder = NSAttributedString(fromHTMLData: self.placeholder, attributes: ["html":self.placeholderStyle])
self.renderViewStyle(view)
return view
}
override func renderTag(pelement: OGElement) {
self.tagOut += ["placeholder","placeholder-style","text","keyboard-type"]
super.renderTag(pelement)
if let text = EUIParse.string(pelement, key: "text"),
let newHtml = Regex("\\{\\{(\\w+)\\}\\}").replace(text, withBlock: { (regx) -> String in
let keyPath = regx.subgroupMatchAtIndex(0)?.trim
self.bind["text"] = keyPath
return ""
}) {
self.contentText = newHtml
}
self.text = "1".dataUsingEncoding(NSUTF8StringEncoding)?.dataByReplacingOccurrencesOfData("\\n".dataUsingEncoding(NSUTF8StringEncoding), withData: "\n".dataUsingEncoding(NSUTF8StringEncoding))
if let placeholderStyle = EUIParse.string(pelement,key: "placeholder-style") {
self.placeholderStyle = "html{" + placeholderStyle + "}"
}
if let placeholder = EUIParse.string(pelement,key: "placeholder") {
self.placeholder = placeholder.dataUsingEncoding(NSUTF8StringEncoding)?.dataByReplacingOccurrencesOfData("\\n".dataUsingEncoding(NSUTF8StringEncoding), withData: "\n".dataUsingEncoding(NSUTF8StringEncoding))
}
if let keyboardType = EUIParse.string(pelement, key: "keyboard-type") {
self.keyboardType = keyboardType.keyboardType
}
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUI+ViewProperty.swift
================================================
//
// EUI+ViewProperty.swift
// medical
//
// Created by zhuchao on 15/5/2.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import Foundation
class ViewProperty :NSObject{
var tag:GumboTag?
var tagId = ""
var style = ""
var type = ""
var subTags = Array()
var otherProperty = Dictionary()
var tagOut = Array()
var imageMode = UIViewContentMode.ScaleAspectFill
var align = Array()
var margin = Array()
var width:Constrain?
var height:Constrain?
var onTap:TapGestureAction?
var onSwipe:SwipeGestureAction?
var onTapBind:TapGestureAction?
var onSwipeBind:SwipeGestureAction?
var frame:CGRect?
var bind = Dictionary()
var contentText:String?
var flexEnable = false
var flexDirection:FLEXBOXFlexDirection = .Column
var flexContentDirection:FLEXBOXContentDirection = .LeftToRight
var flexJustifyContent:FLEXBOXJustification = .FlexStart
var flexAlignSelf:FLEXBOXAlignment = .Auto
var flexAlignItems:FLEXBOXAlignment = .Stretch
var flexMargin = UIEdgeInsetsZero
var flexPadding = UIEdgeInsetsZero
var flexWrap = false
var flex:CGFloat = 0.0
var flexFixedSize = CGSizeZero
var flexMinimumSize = CGSizeZero
var flexMaximumSize = CGSizeMake(CGFloat.max, CGFloat.max)
func getView() -> UIView{
if self.tag == nil {
return UIView()
}
return self.view()
}
func view() -> UIView{
if(flexEnable){
let view = FLEXBOXContainerView()
view.tagProperty = self
self.renderViewStyle(view)
for subTag in self.subTags {
view.addSubview(subTag.getView())
}
return view
}else{
let view = UIView()
view.tagProperty = self
self.renderViewStyle(view)
for subTag in self.subTags {
view.addSubview(subTag.getView())
}
return view
}
}
func renderTag(pelement:OGElement){
self.tagOut += ["id","style","align","margin","type","image-mode","name","width","height","class","ontap","onswipe","ontap-bind","onswipe-bind","frame","reuseid","push","present","align-self","align-items","justify-content","flex-direction","content-direction","flex-margin","flex-padding","flex-wrap","flex","flex-minimum-size"]
self.tag = pelement.tag
if let flexMinimumSize = EUIParse.string(pelement, key: "flex-minimum-size"){
self.flexEnable = true
self.flexMinimumSize = CGSizeFromString(flexMinimumSize)
}
if let flexMaximumSize = EUIParse.string(pelement, key: "flex-maximum-size"){
self.flexEnable = true
self.flexMaximumSize = CGSizeFromString(flexMaximumSize)
}
if let flexFixedSize = EUIParse.string(pelement, key: "flex-fixed-size"){
self.flexEnable = true
self.flexFixedSize = CGSizeFromString(flexFixedSize)
}
if let flexMargin = EUIParse.string(pelement, key: "flex-margin"){
self.flexEnable = true
self.flexMargin = UIEdgeInsetsFromString(flexMargin)
}
if let flexPadding = EUIParse.string(pelement, key: "flex-padding"){
self.flexEnable = true
self.flexPadding = UIEdgeInsetsFromString(flexPadding)
}
if let flexWrap = EUIParse.string(pelement, key: "flex-wrap"){
self.flexEnable = true
self.flexWrap = flexWrap.boolValue
}
if let flex = EUIParse.string(pelement, key: "flex"){
self.flexEnable = true
self.flex = flex.floatValue
}
if let alignSelf = EUIParse.string(pelement, key: "align-self"){
self.flexEnable = true
self.flexAlignSelf = alignSelf.alignItems
}
if let alignItems = EUIParse.string(pelement, key: "align-items"){
self.flexEnable = true
self.flexAlignItems = alignItems.alignItems
}
if let justifyContent = EUIParse.string(pelement, key: "justify-content"){
self.flexEnable = true
self.flexJustifyContent = justifyContent.justifyContent
}
if let flexDirection = EUIParse.string(pelement, key: "flex-direction"){
self.flexEnable = true
self.flexDirection = flexDirection.flexDirection
}
if let contentDirection = EUIParse.string(pelement, key: "content-direction"){
self.flexEnable = true
self.flexContentDirection = contentDirection.flexContentDirection
}
if let tagId = EUIParse.string(pelement,key:"id") {
self.tagId = tagId
}
if let style = EUIParse.string(pelement,key:"style") {
self.style = "html{" + style + "}"
}
if let theAlign = EUIParse.getStyleProperty(pelement,key: "align") {
self.align = theAlign
}
if let theMargin = EUIParse.getStyleProperty(pelement,key: "margin") {
self.margin = theMargin
}
if let theWidth = EUIParse.string(pelement,key:"width") {
var values = theWidth.trimArray
if values.count == 1 {
if values[0].hasSuffix("%") {
var val = values[0]
val.removeAtIndex(val.startIndex.advancedBy(val.characters.count - 1))
self.width = Constrain(name:.Width,value: CGFloat(val.floatValue/100))
}else{
self.width = Constrain(name:.Width,value: CGFloat(values[0].trim.floatValue),target:"")
}
}else if values.count >= 2 && values[0].trim.hasSuffix("%"){
var val = values[0].trim
val.removeAtIndex(val.startIndex.advancedBy(val.characters.count - 1))
self.width = Constrain(name:.Width,value: CGFloat(val.floatValue/100),target:values[1].trim)
}
}
if let theHeight = EUIParse.string(pelement,key:"height") {
var values = theHeight.trimArray
if values.count == 1 {
if values[0].hasSuffix("%") {
var val = values[0]
val.removeAtIndex(val.startIndex.advancedBy(val.characters.count - 1))
self.height = Constrain(name:.Height,value: CGFloat(val.floatValue/100))
}else{
self.height = Constrain(name:.Height,value: CGFloat(values[0].trim.floatValue),target:"")
}
}else if values.count >= 2 && values[0].trim.hasSuffix("%"){
var val = values[0].trim
val.removeAtIndex(val.startIndex.advancedBy(val.characters.count - 1))
self.height = Constrain(name:.Height,value: CGFloat(val.floatValue/100),target:values[1].trim)
}
}
if let frame = EUIParse.string(pelement, key: "frame") {
self.frame = CGRectFromString(frame)
}
if let theType = EUIParse.string(pelement,key:"type") {
self.type = theType
}
if let theImageMode = EUIParse.string(pelement,key:"image-mode") {
self.imageMode = theImageMode.viewContentMode
}
if let theGestureAction = EUIParse.string(pelement, key: "ontap") {
var values = theGestureAction.trimArray
if values.count == 1 {
self.onTap = TapGestureAction(selector: values[0])
}else if values.count >= 2 {
self.onTap = TapGestureAction(selector: values[0], tapNumber: values[1])
}
}
if let theGestureAction = EUIParse.string(pelement, key: "onswipe") {
var values = theGestureAction.trimArray
if values.count == 2 {
self.onSwipe = SwipeGestureAction(selector: values[0], direction: values[1])
}else if values.count >= 3 {
self.onSwipe = SwipeGestureAction(selector: values[0], direction: values[1], numberOfTouches: values[2])
}
}
if let theGestureAction = EUIParse.string(pelement, key: "ontap-bind") {
var values = theGestureAction.trimArray
if values.count == 1 {
self.onTapBind = TapGestureAction(selector: values[0])
}else if values.count >= 2 {
self.onTapBind = TapGestureAction(selector: values[0], tapNumber: values[1])
}
}
if let theGestureAction = EUIParse.string(pelement, key: "onswipe-bind") {
var values = theGestureAction.trimArray
if values.count == 2 {
self.onSwipeBind = SwipeGestureAction(selector: values[0], direction: values[1])
}else if values.count >= 3 {
self.onSwipeBind = SwipeGestureAction(selector: values[0], direction: values[1], numberOfTouches: values[2])
}
}
for (key,value) in pelement.attributes {
if self.tagOut.contains((key as! String)) == false {
self.otherProperty[key as! String] = value
}
}
self.childLoop(pelement)
}
func renderViewStyle(view:UIView){
view.contentMode = self.imageMode;
if(self.flexEnable){
view.flexDirection = self.flexDirection
view.flexContentDirection = self.flexContentDirection
view.flexAlignItems = self.flexAlignItems
view.flexAlignSelf = self.flexAlignSelf
view.flexJustifyContent = self.flexJustifyContent
view.flexMargin = self.flexMargin
view.flexPadding = self.flexPadding
view.flexWrap = self.flexWrap
view.flex = self.flex
view.flexFixedSize = self.flexFixedSize
view.flexMinimumSize = self.flexMinimumSize
view.flexMaximumSize = self.flexMaximumSize
}
if let frame = self.frame {
view.frame = frame
}
for (key,value) in self.otherProperty {
var theValue: AnyObject = value
if let str = value as? String {
if let newValue = self.bindTheKeyPath(str, key: key) {
theValue = newValue
}
if theValue as! String == "" {
continue
}
}
view.attr(key, value)
}
}
func childLoop(pelement:OGElement){
for element in pelement.children {
if let ele = element as? OGElement,let pro = EUIParse.loopElement(ele) {
self.subTags.append(pro)
}
}
}
func bindTheKeyPath(str:String,key:String) -> String?{
let value = Regex("\\{\\{(\\w+)\\}\\}").replace(str, withBlock: { (regx) -> String in
let keyPath = regx.subgroupMatchAtIndex(0)?.trim
self.bind[key] = keyPath
return ""
})
return value
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUI.swift
================================================
//
// EUI.swift
// medical
//
// Created by zhuchao on 15/5/5.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
public class EUI: NSObject {
public class func encode(fileName:String,suffix:String = "xml",toPath:String){
let path = NSBundle.mainBundle().pathForResource(fileName, ofType: suffix)!
if NSFileManager.defaultManager().fileExistsAtPath(path) == false{
return
}
if let str = try? String(contentsOfFile: path, encoding: NSUTF8StringEncoding) {
if let encrypt = DesEncrypt.encryptWithText(str, key: CRTPTO_KEY) {
var error:NSError?
do {
try encrypt.writeToFile(toPath, atomically: true, encoding: NSUTF8StringEncoding)
EZPrintln("success")
} catch let error1 as NSError {
error = error1
EZPrintln(error)
}
}
}
}
public class func setLiveLoad(controller:EUScene,suffix:String){
if IsSimulator && suffix == "xml"{
let paths = self.loadLiveFile(controller,suffix:suffix)
if paths?.count > 0 {
for path in paths! {
watchForChangesToFilePath(path) {
self.loadLiveFile(controller,suffix:suffix)
controller.eu_viewWillLoad()
controller.loadEZLayout()
}
}
}
}else{
self.loadHtml(controller, suffix: suffix)
}
controller.eu_viewWillLoad()
}
private class func loadLiveFile(controller:EUScene,suffix:String) -> [String]?{
let fileName = controller.nameOfClass
let path = NSBundle(path: LIVE_LOAD_PATH)!.pathForResource(fileName, ofType: suffix)!
if NSFileManager.defaultManager().fileExistsAtPath(path) == false{
return nil
}
var paths = Array()
paths.append(path)
do{
if let html = try? String(contentsOfFile: path, encoding: NSUTF8StringEncoding){
var finalHtml = html
if let newHtml = Regex("@import\\(([^\\)]*)\\)").replace(finalHtml,withBlock: { (regx) -> String in
let subFile = regx.subgroupMatchAtIndex(0)?.trim
let subPath = NSBundle(path: LIVE_LOAD_PATH)!.pathForResource(subFile, ofType: suffix)!
if NSFileManager.defaultManager().fileExistsAtPath(subPath) {
paths.append(subPath)
return try! String(contentsOfFile:subPath, encoding: NSUTF8StringEncoding)
}else{
return ""
}
}) {
finalHtml = newHtml
}
if let regMatchs = Regex("").match(finalHtml) {
for regx in regMatchs {
if let styleString = regx.subgroupMatchAtIndex(0)?.trim,
let regxsubs = Regex("\\.([\\w]*)[\\s]*\\{[\\s]?([^}]*)[\\s]?\\}").match(styleString){
for regxsub in regxsubs {
let className = regxsub.subgroupMatchAtIndex(0)!.trim
let values = regxsub.subgroupMatchAtIndex(1)!.trim
if let aHtml = Regex("@"+className).replace(finalHtml, withTemplate: values) {
finalHtml = aHtml
}
}
}
}
}
if let regMatchs = Regex("").match(finalHtml) {
var scriptStrings = "";
for regx in regMatchs {
if let scriptString = regx.subgroupMatchAtIndex(0)?.trim{
scriptStrings += scriptString
}
}
controller.scriptString = scriptStrings
}
if let cleanHtml = Regex("@[\\w]*").replace(finalHtml, withTemplate: "") {
finalHtml = cleanHtml
}
SwiftTryCatch.`try`({
let body = EUIParse.ParseHtml(finalHtml)
var views = [UIView]()
for aview in body {
views.append(aview.getView())
}
controller.eu_subViews = views
}, `catch`: { (error) in
print(controller.nameOfClass + "Error:\(error.description)")
}, finally: nil)
}else{
throw NSError(domain: "EasyIOS", code: -1, userInfo: ["err":"can not open "+path.URLString])
}
}catch let error as NSError{
print("error is \(error)")
}
return paths
}
private class func loadHtml (controller:EUScene,suffix:String){
let fileName = controller.nameOfClass
let path = NSBundle(path: BUNDLE_PATH)!.pathForResource(fileName, ofType: suffix)!
if NSFileManager.defaultManager().fileExistsAtPath(path) == false{
return
}
if let html = try? String(contentsOfFile: path, encoding: NSUTF8StringEncoding) {
var finalHtml = html
if suffix == "crypto" && CRTPTO_KEY != "" {
if let aHtml = DesEncrypt.decryptWithText(finalHtml, key: CRTPTO_KEY) {
finalHtml = aHtml
}
}
if let newHtml = Regex("@import\\(([^\\)]*)\\)").replace(finalHtml,withBlock: { (regx) -> String in
let subFile = regx.subgroupMatchAtIndex(0)?.trim
let subPath = NSBundle(path: BUNDLE_PATH)!.pathForResource(subFile, ofType: suffix)!
if NSFileManager.defaultManager().fileExistsAtPath(subPath) {
return try! String(contentsOfFile:subPath, encoding: NSUTF8StringEncoding)
}else{
return ""
}
}) {
finalHtml = newHtml
}
if let regMatchs = Regex("").match(finalHtml) {
for regx in regMatchs {
if let styleString = regx.subgroupMatchAtIndex(0)?.trim,
let regxsubs = Regex("\\.([\\w]*)[\\s]*\\{[\\s]?([^}]*)[\\s]?\\}").match(styleString){
for regxsub in regxsubs {
let className = regxsub.subgroupMatchAtIndex(0)!.trim
let values = regxsub.subgroupMatchAtIndex(1)!.trim
if let aHtml = Regex("@"+className).replace(finalHtml, withTemplate: values) {
finalHtml = aHtml
}
}
}
}
}
if let regMatchs = Regex("").match(finalHtml) {
var scriptStrings = "";
for regx in regMatchs {
if let scriptString = regx.subgroupMatchAtIndex(0)?.trim{
scriptStrings += scriptString
}
}
controller.scriptString = scriptStrings
}
if let cleanHtml = Regex("@[\\w]*").replace(finalHtml, withTemplate: "") {
finalHtml = cleanHtml
}
SwiftTryCatch.`try`({
let body = EUIParse.ParseHtml(finalHtml)
var views = [UIView]()
for aview in body {
views.append(aview.getView())
}
controller.eu_subViews = views
}, `catch`: { (error) in
print(controller.nameOfClass + "Error:\(error.description)")
}, finally: nil)
}
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUIExtend+UIView.swift
================================================
//
// EUIExtend+UIView.swift
// medical
//
// Created by zhuchao on 15/5/1.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import SnapKit
import Bond
import Kingfisher
import TTTAttributedLabel
private var UIViewTagIdHandle :UInt8 = 1
private var UIViewViewPropertyHandle :UInt8 = 2
private var UIViewConstraintGroupHandle :UInt8 = 3
private var UIViewWatchHandle :UInt8 = 4
private var UIViewDisposeBag :UInt8 = 5
//private var CollectionViewDataSourceBond :UInt8 = 6
private var attributedLabelDelegateHandle :UInt8 = 7
public class TTTAttributedLabelDelegateHandle:NSObject,TTTAttributedLabelDelegate{
}
extension EUScene{
public var attributedLabelDelegate:TTTAttributedLabelDelegateHandle? {
get{
if let d: AnyObject = objc_getAssociatedObject(self, &attributedLabelDelegateHandle) {
return d as? TTTAttributedLabelDelegateHandle
}else{
return nil
}
}set (value){
objc_setAssociatedObject(self, &attributedLabelDelegateHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public func eu_viewByTag(tagId:String) ->UIView?{
if let subViews = self.eu_subViews {
for view in subViews {
if view.subviews.count > 0 {
if let aview = view.getSubViewByTagId(tagId){
return aview
}
}
if view.tagProperty.tagId == tagId {
return view
}
}
}
return nil
}
func loadEZLayout(){
self.view.clearEZView()
if let subViews = self.eu_subViews {
for view in subViews {
self.view.addSubview(view)
}
self.view.subRender(self)
}
self.context.setObject(self, forKeyedSubscript: "document")
self.eval(self.scriptString)
self.eu_viewDidLoad()
}
}
extension UIView {
public var disposeBag:DisposeBag?{
get{
if let d: AnyObject = objc_getAssociatedObject(self, &UIViewDisposeBag) {
return d as? DisposeBag
}else{
return nil
}
}set(b){
objc_setAssociatedObject(self, &UIViewDisposeBag, b, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public class func formTag(tag:String) -> UIView {
if let scene = URLNavigation.currentViewController() as? EUScene {
if let view = scene.eu_viewByTag(tag) {
return view
}
}
return UIView()
}
func clearEZView(){
for view in self.subviews {
let aview = view
aview.clearEZView()
aview.removeFromSuperview()
}
}
var tagProperty:ViewProperty{
get{
if let d: AnyObject = objc_getAssociatedObject(self, &UIViewViewPropertyHandle) {
return d as! ViewProperty
}else{
return ViewProperty()
}
}set (value){
objc_setAssociatedObject(self, &UIViewViewPropertyHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public func getSubViewByTagId(tagId:String) -> UIView?{
for view in self.subviews {
if view.subviews.count > 0 {
if let aview = view.getSubViewByTagId(tagId){
return aview
}
}
if view.tagProperty.tagId == tagId {
return view
}
}
return nil
}
public func getRootView() -> UIView {
if self.superview == nil {
return self
}else{
return self.superview!.getRootView()
}
}
func getViewById(tagId:String) -> UIView? {
if tagId == ""{
return nil
}else if tagId == Constrain.targetRoot {
return self.getRootView()
}else if tagId == Constrain.targetSuper {
return self.superview
}else if tagId == Constrain.targetSelf || tagId == self.tagProperty.tagId{
return self
}else{
return self.getRootView().getSubViewByTagId(tagId)
}
}
func subRender(scene:EUScene) {
for subView in self.subviews {
let view = subView
view.renderTheView(scene)
}
}
func renderTheView(scene:EUScene){
self.subRender(scene)
self.renderSelector(scene)
self.renderGesture(scene)
self.renderLayout()
}
public func renderDataBinding(scene:EUScene,bind:NSObject?){
for subView in self.subviews {
subView.renderDataBinding(scene,bind: bind)
}
let property = self.tagProperty as ViewProperty
if let bindKey = property.bind["background-color"] {
if let color = bind!.valueForKey(bindKey) as? EZColor {
color.dym!.bindTo(self.bnd_backgroundColor)
}
}
if let bindKey = property.bind["alpha"] {
if let alpha = bind!.valueForKey(bindKey) as? EZFloat {
alpha.dym!.bindTo(self.bnd_alpha)
}
}
if let bindKey = property.bind["hidden"] {
if let hidden = bind!.valueForKey(bindKey) as? EZBool {
hidden.dym!.bindTo(self.bnd_hidden)
}
}
self.disposeBag?.dispose()
if let selector = property.onTapBind {
if self.disposeBag == nil {
self.disposeBag = DisposeBag()
}
self.disposeBag?.addDisposable(self.whenTap(selector.tapNumber){
let script = Regex("\\{\\{(\\w+)\\}\\}").replace(selector.selector, withBlock: { (regx) -> String in
let bindKey = regx.subgroupMatchAtIndex(0)?.trim
if let value = bind!.valueForKey(bindKey!) as? String{
return value
}else if let value = bind!.valueForKey(bindKey!) as? Int{
return String(value)
}else if let value = bind!.valueForKey(bindKey!) as? Bool{
return value ? "true" : "false"
}
return ""
})
scene.eval(script)
})
}
if let selector = property.onSwipeBind {
if self.disposeBag == nil {
self.disposeBag = DisposeBag()
}
self.disposeBag?.addDisposable(self.whenSwipe(selector.numberOfTouches, direction: selector.direction){
let script = Regex("\\{\\{(\\w+)\\}\\}").replace(selector.selector, withBlock: { (regx) -> String in
let bindKey = regx.subgroupMatchAtIndex(0)?.trim
if let value = bind!.valueForKey(bindKey!) as? String{
return value
}else if let value = bind!.valueForKey(bindKey!) as? Int{
return String(value)
}else if let value = bind!.valueForKey(bindKey!) as? Bool{
return value ? "true" : "false"
}
return ""
})
scene.eval(script)
})
}
}
func renderGesture(scene:EUScene){
let property = self.tagProperty as ViewProperty
self.disposeBag?.dispose()
if let selector = property.onTap {
if self.disposeBag == nil {
self.disposeBag = DisposeBag()
}
self.disposeBag?.addDisposable(self.whenTap(selector.tapNumber){
scene.eval(selector.selector)
})
}
if let selector = property.onSwipe {
if self.disposeBag == nil {
self.disposeBag = DisposeBag()
}
self.disposeBag?.addDisposable(self.whenSwipe(selector.numberOfTouches, direction: selector.direction){
scene.eval(selector.selector)
})
}
}
func renderSelector(scene:EUScene){
}
func renderLayout(){
var consList = self.tagProperty.align + self.tagProperty.margin
if let width = self.tagProperty.width {
consList.append(width)
}
if let height = self.tagProperty.height {
consList.append(height)
}
if consList.count == 0 {
return
}
self.snp_remakeConstraints(){[unowned self] (make) -> Void in
for cons in consList {
let targetView = self.getViewById(cons.target)
let value = cons.value
let key = cons.constrainName
if targetView != nil {
switch key {
case .AlignRight:
make.right.equalTo(targetView!).offset(value)
case .AlignLeft:
make.left.equalTo(targetView!).offset(value)
case .AlignTop:
make.top.equalTo(targetView!).offset(value)
case .AlignBottom:
make.bottom.equalTo(targetView!).offset(value)
case .AlignCenterX:
make.centerX.equalTo(targetView!).offset(value)
case .AlignCenterY:
make.centerY.equalTo(targetView!).offset(value)
case .MarginTop:
make.top.equalTo(targetView!.snp_bottom).offset(value)
case .MarginLeft:
make.left.equalTo(targetView!.snp_right).offset(value)
case .MarginRight:
make.right.equalTo(targetView!.snp_left).offset(-value)
case .MarginBottom:
make.bottom.equalTo(targetView!.snp_top).offset(-value)
case .Width:
make.width.equalTo(targetView!.snp_width).multipliedBy(value)
case .Height:
make.height.equalTo(targetView!.snp_height).multipliedBy(value)
default:
EZPrintln("remake default")
}
}else {
switch key {
case .Width:
make.width.equalTo(Int(value))
case .Height:
make.height.equalTo(Int(value))
default:
EZPrintln("remake default")
}
}
}
}
}
}
extension UIImageView {
override public class func formTag(tag:String) -> UIImageView {
if let scene = URLNavigation.currentViewController() as? EUScene {
if let view = scene.eu_viewByTag(tag) as? UIImageView {
return view
}
}
return UIImageView()
}
override public func renderDataBinding(scene:EUScene,bind:NSObject?){
super.renderDataBinding(scene,bind: bind)
if let bindKey = self.tagProperty.bind["src"] {
if let image = bind!.valueForKey(bindKey) as? EZImage {
image.dym!.bindTo(self.bnd_image)
}else if let src = bind!.valueForKey(bindKey) as? EZURL {
src.dym!.bindTo(self.bnd_URLImage)
}else if let image = bind!.valueForKey(bindKey) as? UIImage {
self.image = image
}else if let url = bind!.valueForKey(bindKey) as? NSURL {
self.kf_setImageWithURL(url)
}else if let str = bind!.valueForKey(bindKey) as? String {
if let image = UIImage(named: str) {
self.image = image
}else if let url = NSURL(string: str) {
self.kf_setImageWithURL(url)
}
}
}else if let bindKey = self.tagProperty.bind["image"] {
if let image = bind!.valueForKey(bindKey) as? EZImage {
image.dym!.bindTo(self.bnd_image)
}else if let image = bind!.valueForKey(bindKey) as? UIImage {
self.image = image
}
}
}
}
extension UILabel {
override public class func formTag(tag:String) -> UILabel {
if let scene = URLNavigation.currentViewController() as? EUScene {
if let view = scene.eu_viewByTag(tag) as? UILabel {
return view
}
}
return UILabel()
}
override public func renderDataBinding(scene:EUScene,bind:NSObject?){
super.renderDataBinding(scene,bind: bind)
if let bindKey = self.tagProperty.bind["text"] {
if let text = bind!.valueForKey(bindKey) as? EZAttributedString {
text.dym!.bindTo(self.bnd_attributedText)
}else if let text = bind!.valueForKey(bindKey) as? EZString {
text.dym!.bindTo(self.bnd_text)
}else if let text = bind!.valueForKey(bindKey) as? String {
self.text = text
}else if let data = bind!.valueForKey(bindKey) as? NSData {
self.attributedText = NSAttributedString(fromHTMLData: data, attributes: ["dict":self.tagProperty.style])
}else if let string = bind!.valueForKey(bindKey) as? NSAttributedString {
self.attributedText = string
}
}
if let bindKey = self.tagProperty.bind["text-color"] {
if let color = bind!.valueForKey(bindKey) as? EZColor {
color.dym!.bindTo(self.bnd_textColor)
}else if let color = bind!.valueForKey(bindKey) as? UIColor {
self.textColor = color
}
}
}
}
extension TTTAttributedLabel {
override public class func formTag(tag:String) -> TTTAttributedLabel {
if let scene = URLNavigation.currentViewController() as? EUScene {
if let view = scene.eu_viewByTag(tag) as? TTTAttributedLabel {
return view
}
}
return TTTAttributedLabel(frame: CGRectZero)
}
override public func renderDataBinding(scene:EUScene,bind:NSObject?){
super.renderDataBinding(scene,bind: bind)
if let bindKey = self.tagProperty.bind["TTText"] {
if let text = bind!.valueForKey(bindKey) as? EZAttributedString {
text.dym! ->> self.dynTTTAttributedText
}else if let text = bind!.valueForKey(bindKey) as? EZString {
text.dym! ->> self.dynTTText
}else if let data = bind!.valueForKey(bindKey) as? EZData {
data.dym! ->> self.dynTTTData
}else if let text = bind!.valueForKey(bindKey) as? String {
self.setText(text)
}else if let data = bind!.valueForKey(bindKey) as? NSData {
self.setText(NSAttributedString(fromHTMLData: data, attributes: ["dict":self.tagProperty.style]))
}else if let string = bind!.valueForKey(bindKey) as? NSAttributedString {
self.setText(string)
}
}
}
override func renderSelector(scene:EUScene){
if let delegate = scene.attributedLabelDelegate {
self.delegate = delegate
}
}
}
extension UITextField {
override public class func formTag(tag:String) -> UITextField {
if let scene = URLNavigation.currentViewController() as? EUScene {
if let view = scene.eu_viewByTag(tag) as? UITextField {
return view
}
}
return UITextField()
}
override public func renderDataBinding(scene:EUScene,bind:NSObject?){
super.renderDataBinding(scene,bind:bind)
if let bindKey = self.tagProperty.bind["text"] {
if let text = bind!.valueForKey(bindKey) as? EZString {
text.dym!.bindTo(self.bnd_text)
}else if let text = bind!.valueForKey(bindKey) as? String {
self.text = text
}
}
}
}
extension UIButton {
override public class func formTag(tag:String) -> UIButton {
if let scene = URLNavigation.currentViewController() as? EUScene {
if let view = scene.eu_viewByTag(tag) as? UIButton {
return view
}
}
return UIButton()
}
override func renderSelector(scene:EUScene){
let property = self.tagProperty as? ButtonProperty
if let selector = property?.onEvent {
self.bnd_controlEvent.filter{$0 == selector.event}.map{ e in}.observe({
scene.eval(selector.selector)
})
}
}
}
private var UITableViewCellHandle :UInt8 = 5
extension UITableView {
override public class func formTag(tag:String) -> UITableView {
if let scene = URLNavigation.currentViewController() as? EUScene {
if let view = scene.eu_viewByTag(tag) as? UITableView {
return view
}
}
return UITableView()
}
public func getSectionViewByTagId(tagId:String,target:EUScene,bind:NSObject? = nil) -> UIView?{
let property = self.tagProperty as? TableViewProperty
if let pro = property?.sectionView[tagId] {
let view = pro.getView()
view.renderTheView(target)
view.renderDataBinding(target,bind: bind)
return view
}
return nil
}
var reusableViews:Dictionary{
get{
if let d: AnyObject = objc_getAssociatedObject(self, &UITableViewCellHandle) {
return d as! Dictionary
}else{
return Dictionary()
}
}set (value){
objc_setAssociatedObject(self, &UITableViewCellHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
override func subRender(scene:EUScene) {
scene.eu_tableViewDidLoad(self)
}
public func dequeueReusableCell(reuseId:String,forIndexPath:NSIndexPath,target:EUScene,bind:NSObject? = nil) -> UITableViewCell{
let cell = self.dequeueReusableCellWithIdentifier(reuseId, forIndexPath: forIndexPath)
if cell.contentView.subviews.count == 0 {
SwiftTryCatch.`try`({
let property = self.tagProperty as! TableViewProperty
if let cellProperty = property.reuseCell[reuseId] {
let view = cellProperty.getView()
cell.contentView.addSubview(view)
view.renderTheView(target)
}}, `catch`: { (error) in
print(self.nameOfClass + "Error:\(error.description)")
}, finally:nil)
}
if let view = cell.contentView.subviews.first {
view.renderDataBinding(target,bind: bind)
}
return cell
}
}
private var UICollectionViewCellHandle :UInt8 = 5
extension UICollectionView {
override public class func formTag(tag:String) -> UICollectionView {
if let scene = URLNavigation.currentViewController() as? EUScene {
if let view = scene.eu_viewByTag(tag) as? UICollectionView {
return view
}
}
return UICollectionView()
}
var reusableViews:Dictionary{
get{
if let d: AnyObject = objc_getAssociatedObject(self, &UICollectionViewCellHandle) {
return d as! Dictionary
}else{
return Dictionary()
}
}set (value){
objc_setAssociatedObject(self, &UICollectionViewCellHandle, value, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
override func subRender(scene:EUScene) {
scene.eu_collectionViewDidLoad(self)
}
public func dequeueReusableCell(reuseId:String,forIndexPath:NSIndexPath,target:EUScene,bind:NSObject? = nil) -> UICollectionViewCell{
let cell = self.dequeueReusableCellWithReuseIdentifier(reuseId, forIndexPath: forIndexPath)
if cell.contentView.subviews.count == 0 {
SwiftTryCatch.`try`({
let property = self.tagProperty as! CollectionViewProperty
if let cellProperty = property.reuseCell[reuseId] {
let view = cellProperty.getView()
cell.contentView.addSubview(view)
view.renderTheView(target)
}}, `catch`: { (error) in
print(self.nameOfClass + "Error:\(error.description)")
}, finally: nil)
}
if let view = cell.contentView.subviews.first{
view.renderDataBinding(target,bind:bind)
}
return cell
}
}
extension UIScrollView {
override public class func formTag(tag:String) -> UIScrollView {
if let scene = URLNavigation.currentViewController() as? EUScene {
if let view = scene.eu_viewByTag(tag) as? UIScrollView {
return view
}
}
return UIScrollView()
}
override func renderSelector(scene:EUScene){
let property = self.tagProperty as? ScrollViewProperty
if let pullRefresh = property?.pullToRefresh {
if pullRefresh.viewClass.characters.isEmpty {
self.addPullToRefreshWithActionHandler(){
scene.eval(pullRefresh.selector)
}
}else if let view = NSObject(fromString: pullRefresh.viewClass) as? UIView {
self.addPullToRefreshWithActionHandler(view) {
scene.eval(pullRefresh.selector)
}
}
}
if let infiniteScrolling = property?.infiniteScrolling {
if infiniteScrolling.viewClass.characters.isEmpty {
self.addInfiniteScrollingWithActionHandler(){
scene.eval(infiniteScrolling.selector)
}
}else if let view = NSObject(fromString: infiniteScrolling.viewClass) as? UIView {
self.addInfiniteScrollingWithActionHandler(view) {
scene.eval(infiniteScrolling.selector)
}
}
}
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUIKit.swift
================================================
//
// EUIView.swift
// Pods
//
// Created by zhuchao on 15/7/21.
//
//
import CoreImage
import UIKit
import JavaScriptCore
@objc public protocol EUIView:JSExport,ENSObject{
}
@objc public protocol EUIImageView:JSExport,EUIView,ENSObject{
init(image: UIImage!)
init(image: UIImage!, highlightedImage: UIImage?)
}
@objc public protocol EUITextField:JSExport,EUIView,ENSObject{
}
@objc public protocol EUIButton:JSExport,EUIView,ENSObject{
}
@objc public protocol EUIScrollView:JSExport,EUIView,ENSObject{
}
@objc public protocol EUITableView:JSExport,EUIScrollView,ENSObject{
}
@objc public protocol EUICollectionView:JSExport,EUIScrollView,ENSObject{
}
@objc public protocol EUILabel:JSExport,EUIView,ENSObject{
}
@objc public protocol EUIColor:JSExport,ENSObject{
static func blackColor() -> UIColor // 0.0 white
static func darkGrayColor() -> UIColor // 0.333 white
static func lightGrayColor() -> UIColor // 0.667 white
static func whiteColor() -> UIColor // 1.0 white
static func grayColor() -> UIColor // 0.5 white
static func redColor() -> UIColor // 1.0, 0.0, 0.0 RGB
static func greenColor() -> UIColor // 0.0, 1.0, 0.0 RGB
static func blueColor() -> UIColor // 0.0, 0.0, 1.0 RGB
static func cyanColor() -> UIColor // 0.0, 1.0, 1.0 RGB
static func yellowColor() -> UIColor // 1.0, 1.0, 0.0 RGB
static func magentaColor() -> UIColor // 1.0, 0.0, 1.0 RGB
static func orangeColor() -> UIColor // 1.0, 0.5, 0.0 RGB
static func purpleColor() -> UIColor // 0.5, 0.0, 0.5 RGB
static func brownColor() -> UIColor // 0.6, 0.4, 0.2 RGB
static func clearColor() -> UIColor // 0.0 white, 0.0 alpha
}
@objc public protocol EUIImage:JSExport,ENSObject{
init(named name: String)// load from main bundle
@available(iOS, introduced=8.0)
init(named name: String, inBundle bundle: NSBundle?, compatibleWithTraitCollection traitCollection: UITraitCollection?)
init?(contentsOfFile path: String)
}
================================================
FILE: Pod/Classes/Extend/EUI/EUIParse.swift
================================================
//
// EZUI.swift
// medical
//
// Created by zhuchao on 15/4/30.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import SnapKit
class EUIParse: NSObject {
class func ParseHtml(html:String) -> [ViewProperty]{
let data = ObjectiveGumbo.parseDocumentWithString(html)
let body = data.elementsWithTag(GUMBO_TAG_BODY).first as! OGElement
var viewArray = [ViewProperty]()
for element in body.children {
if element.isKindOfClass(OGElement) {
if let pro = self.loopElement(element as! OGElement) {
viewArray.append(pro)
}
}
}
return viewArray
}
// 对子节点进行递归解析
class func loopElement(pelement:OGElement) -> ViewProperty?{
var tagProperty:ViewProperty?
var type:String?
switch (pelement.tag.rawValue){
case GUMBO_TAG_IMG.rawValue :
type = "UIImageView"
case GUMBO_TAG_SPAN.rawValue :
type = "UILabel"
case GUMBO_TAG_BUTTON.rawValue :
type = "UIButton"
case GUMBO_TAG_INPUT.rawValue :
type = "UITextField"
default :
type = self.string(pelement,key:"type")
}
if let atype = type {
switch (atype){
case "UIScrollView","scroll":
tagProperty = ScrollViewProperty()
case "UITableView","table":
tagProperty = TableViewProperty()
case "UICollectionView","collection":
tagProperty = CollectionViewProperty()
case "UIImageView","imageView":
tagProperty = ImageProperty()
case "UILabel","label":
tagProperty = LabelProperty()
case "UIButton","button":
tagProperty = ButtonProperty()
case "UITextField","field":
tagProperty = TextFieldProperty()
default :
tagProperty = ViewProperty()
}
}else{
tagProperty = ViewProperty()
}
if tagProperty != nil {
tagProperty!.renderTag(pelement)
}
return tagProperty
}
class func string (element:OGElement,key:String) ->String?{
if let str = element.attributes?[key] as? String {
return str
}
return nil
}
class func getStyleProperty (element:OGElement,key:String) -> Array? {
if element.attributes?[key] == nil {
return nil
}
var style = Array()
let origin = element.attributes?[key] as! String
let firstArray = origin.trimArrayBy(";")
for str in firstArray {
var secondArray = str.trimArrayBy(":")
if secondArray.count == 2 {
let raw = secondArray[0] as String
let rawKey = CSS(rawValue: key+"-"+raw.trim)
if rawKey == nil {
continue
}
var values = secondArray[1].trimArray
if key == "align" {
switch rawKey! {
case .AlignTop,.AlignBottom,.AlignLeft,.AlignRight,.AlignCenterX,.AlignCenterY:
if values.count == 1 {
style.append(Constrain(name:rawKey!,value: values[0].trim.floatValue))
}else if(values.count >= 2){
style.append(Constrain(name:rawKey!,value: values[0].trim.floatValue,target:values[1].trim))
}
case .AlignCenter:
if values.count >= 1 {
style.append(Constrain(name:.AlignCenterX,value: values[0].trim.floatValue))
}
if values.count >= 2 {
style.append(Constrain(name:.AlignCenterY,value: values[1].trim.floatValue))
}
case .AlignEdge:
if values.count >= 1 && values[0].trim != "*" {
style.append(Constrain(name:.AlignTop,value: values[0].trim.floatValue))
}
if values.count >= 2 && values[1].trim != "*" {
style.append(Constrain(name:.AlignLeft,value: values[1].trim.floatValue))
}
if values.count >= 3 && values[2].trim != "*" {
style.append(Constrain(name:.AlignBottom,value: values[2].trim.floatValue))
}
if values.count >= 4 && values[3].trim != "*" {
style.append(Constrain(name:.AlignRight,value: values[3].trim.floatValue))
}
default :
print(raw.trim + " is jumped")
}
}else if key == "margin" {
switch rawKey! {
case .MarginTop,.MarginBottom,.MarginLeft,.MarginRight:
if values.count == 1 {
style.append(Constrain(name:rawKey!,value: values[0].trim.floatValue))
}else if(values.count >= 2){
style.append(Constrain(name:rawKey!,value: values[0].trim.floatValue,target:values[1].trim))
}
default :
print(raw.trim + " is jumped")
}
}
}else if secondArray.count == 1 && key == "align" {
var values = secondArray[0].trimArray
if values.count >= 1 && values[0].trim != "*" {
style.append(Constrain(name:.AlignTop,value: values[0].trim.floatValue))
}
if values.count >= 2 && values[1].trim != "*" {
style.append(Constrain(name:.AlignLeft,value: values[1].trim.floatValue))
}
if values.count >= 3 && values[2].trim != "*" {
style.append(Constrain(name:.AlignBottom,value: values[2].trim.floatValue))
}
if values.count >= 4 && values[3].trim != "*" {
style.append(Constrain(name:.AlignRight,value: values[3].trim.floatValue))
}
}
}
return style
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUIProperty.swift
================================================
//
// EUIProperty.swift
// medical
//
// Created by zhuchao on 15/4/30.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
enum CSS:String{
case MarginTop = "margin-top"
case MarginLeft = "margin-left"
case MarginRight = "margin-right"
case MarginBottom = "margin-bottom"
case AlignTop = "align-top"
case AlignBottom = "align-bottom"
case AlignLeft = "align-left"
case AlignRight = "align-right"
case AlignCenter = "align-center"
case AlignCenterX = "align-center-x"
case AlignCenterY = "align-center-y"
case AlignEdge = "align-edge"
case Width = "width"
case Height = "height"
}
struct Constrain{
static var targetSelf = "self"
static var targetSuper = "super"
static var targetRoot = "root"
var value:CGFloat = 0.0
var target = targetSuper
var constrainName = CSS.AlignEdge
init(name:CSS,value:CGFloat,target:String = targetSuper){
self.constrainName = name
self.value = value
self.target = target
}
}
struct SelectorAction{
var selector:String = ""
var event:UIControlEvents = UIControlEvents.TouchUpInside
init(selector:String,event:String = "TouchUpInside"){
self.selector = selector
self.event = event.controlEvent
}
}
struct PullRefreshAction {
var selector:String = ""
var viewClass:String = ""
init(selector:String,viewClass:String = ""){
self.selector = selector
self.viewClass = viewClass
}
}
struct InfiniteScrollingAction {
var selector:String = ""
var viewClass:String = ""
init(selector:String,viewClass:String = ""){
self.selector = selector
self.viewClass = viewClass
}
}
struct TapGestureAction{
var selector:String = ""
var tapNumber:NSInteger = 1
init(selector:String,tapNumber:String = "1"){
self.selector = selector
self.tapNumber = tapNumber.integerValue
}
}
struct SwipeGestureAction {
var direction: UISwipeGestureRecognizerDirection
var selector:String
var numberOfTouches:Int = 1
init(selector:String,direction:String,numberOfTouches:String = "1"){
self.selector = selector
self.numberOfTouches = numberOfTouches.integerValue
switch direction.lowercaseString {
case "up" :
self.direction = .Up
case "down" :
self.direction = .Down
case "right" :
self.direction = .Right
case "left" :
self.direction = .Left
default :
self.direction = .Up
}
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EUScene.swift
================================================
//
// EUScene.swift
// medical
//
// Created by zhuchao on 15/5/6.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
import UIKit
import JavaScriptCore
public var LIVE_LOAD_PATH = NSBundle.mainBundle().pathForResource("xml", ofType: "bundle")!
public var BUNDLE_PATH = NSBundle.mainBundle().pathForResource("xml", ofType: "bundle")!
public var CRTPTO_KEY = ""
@objc protocol EUSceneExport:JSExport {
func getElementById(id:String) -> UIView
}
public class EUScene: EZScene,EUSceneExport{
public func getElementById(id:String) -> UIView {
return UIView.formTag(id)
}
public var SUFFIX = "xml"
public var eu_subViews:[UIView]?
public var scriptString:String?
public var context = EZJSContext()
public func define(funcName:String,actionBlock:@convention(block) ()->Void){
context.define(funcName, actionBlock: actionBlock)
}
public func eval(script: String?) -> JSValue?{
if let str = script {
var result:JSValue?
SwiftTryCatch.`try`({
result = self.context.evaluateScript(str)
}, `catch`: { (error) in
print("JS Error:\(error.description)")
}, finally: nil)
return result
}else{
return nil
}
}
override public func loadView() {
super.loadView()
EUI.setLiveLoad(self,suffix: SUFFIX)
}
override public func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false;
self.extendedLayoutIncludesOpaqueBars = true;
self.edgesForExtendedLayout = UIRectEdge.All;
self.view.backgroundColor = UIColor.whiteColor()
self.loadEZLayout()
}
public func eu_viewWillLoad(){
}
public func eu_viewDidLoad(){
}
public func eu_tableViewDidLoad(tableView:UITableView?){
}
public func eu_collectionViewDidLoad(collectionView:UICollectionView?){
}
}
================================================
FILE: Pod/Classes/Extend/EUI/EZJSCore.swift
================================================
import UIKit
import JavaScriptCore
@objc protocol ConsoleExport:JSExport {
static func log(object:AnyObject?)
}
@objc public class Console:NSObject,ConsoleExport {
static public func log(object:AnyObject?){
if let obj: AnyObject = object{
print(obj)
}
}
}
@objc protocol JSURLManagerExport:JSExport {
static func present(url:String,_ animated:Bool)
static func push(url:String,_ animated:Bool)
static func dismiss(animated:Bool)
}
public class JSURLManager:NSObject,JSURLManagerExport {
static public func present(url:String,_ animated:Bool){
let viewController = UIViewController.initFromString(url, fromConfig: URLManager.shareInstance().config)
let nav = EZNavigationController(rootViewController: viewController)
URLNavigation.presentViewController(nav, animated: animated)
}
static public func push(url:String,_ animated:Bool){
URLManager.pushURLString(url, animated: animated)
}
static public func dismiss(animated:Bool){
URLNavigation.dismissCurrentAnimated(animated)
}
}
public class EZJSContext:JSContext{
override init(){
super.init()
self.setObject(Console.self, forKeyedSubscript: "console")
self.setObject(JSURLManager.self, forKeyedSubscript: "um")
class_addProtocol(EZAction.self, EZActionJSExport.self)
self.setObject(EZAction.self, forKeyedSubscript: "EZAction")
class_addProtocol(UIColor.self, EUIColor.self)
self.setObject(UIColor.self, forKeyedSubscript: "UIColor")
class_addProtocol(UIImage.self, EUIImage.self)
self.setObject(UIImage.self, forKeyedSubscript: "UIImage")
class_addProtocol(UIView.self, EUIView.self)
self.setObject(UIView.self, forKeyedSubscript: "UIView")
class_addProtocol(UIImageView.self, EUIImageView.self)
self.setObject(UIImageView.self, forKeyedSubscript: "UIImageView")
class_addProtocol(UITextField.self, EUITextField.self)
self.setObject(UITextField.self, forKeyedSubscript: "UITextField")
class_addProtocol(UIButton.self, EUIButton.self)
self.setObject(UIButton.self, forKeyedSubscript: "UIButton")
class_addProtocol(UILabel.self, EUILabel.self)
self.setObject(UILabel.self, forKeyedSubscript: "UILabel")
class_addProtocol(UIScrollView.self, EUIScrollView.self)
self.setObject(UIScrollView.self, forKeyedSubscript: "UIScrollView")
class_addProtocol(UITableView.self, EUITableView.self)
self.setObject(UITableView.self, forKeyedSubscript: "UITableView")
class_addProtocol(UICollectionView.self, EUICollectionView.self)
self.setObject(UICollectionView.self, forKeyedSubscript: "UICollectionView")
self.exceptionHandler = { context, exception in
print("JS Error: \(exception)")
}
}
override init(virtualMachine: JSVirtualMachine!) {
super.init(virtualMachine:virtualMachine)
}
public func define(funcName:String,actionBlock:@convention(block) ()->Void){
self.setObject(unsafeBitCast(actionBlock, AnyObject.self), forKeyedSubscript:funcName)
}
}
================================================
FILE: Pod/Classes/Extend/EUI/NSAttributedString+HTMLStyle.h
================================================
//
// NSAttributedString+HTMLStyle.h
// QRContentMobilizer
//
// Created by Wojciech Czekalski on 22.03.2014.
// Copyright (c) 2014 Wojciech Czekalski. All rights reserved.
//
#import
typedef NSString QRHTMLAttribute;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeParagraph;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeLink;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeHeader1;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeHeader2;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeHeader3;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeHeader4;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeHeader5;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeHeader6;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeEmphasis;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeStrong;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeBold;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeAlternateVoice;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeSmall;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeSubscripted;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeSuperscripted;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeInserted;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeDeleted;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeHighlighted;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeCode;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeKeyboardText;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeSampleCode;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeVariable;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributePreformatted;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeAbbreviation;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeAddress;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeBlockQuote;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeInlineQuote;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeTitle;
FOUNDATION_EXPORT QRHTMLAttribute * const QRHTMLAttributeDefinition;
/**
* Creation of NSAttributedString out of HTML with per-tag attributes made easy.
*/
@interface NSAttributedString (HTMLStyle)
/**
* Creates an attributed string from HTML data. Assumes `NSUTF8StringEncoding`.
*
* @param data Data to be processed.
*
* @return Returns a new instance of `NSAttributedString` or nil if given data was invalid.
*/
+ (instancetype)attributedStringFromHTMLData:(NSData *)data;
/**
* Creates an attributed string from HTML string and CSS string with attributes.
*
* @param html A string containing HTML.
* @param css A CSS string. If nil, use attributedStringFromHTMLData: instead.
*
* @abstract Don't convert your HTML and CSS into NSStrings from NSData objects. Use `attributedStringFromHTMLData:CSSData:` instead.
*
* @return Returns a new instance of `NSAttributedString` or nil if given data was invalid.
*/
+ (instancetype)attributedStringFromHTMLString:(NSString *)html CSSString:(NSString *)css;
/**
* Creates an attributed string from merged HTML and CSS data.
*
* @param html HTML data to be processed
* @param css CSS data to be processed
*
* @return Returns a new instance of NSAttributedString or nil if given data was invalid.
*/
+ (instancetype)attributedStringFromHTMLData:(NSData *)html CSSData:(NSData *)css;
/**
* Creates an attributed string from merged HTML and CSS files.
*
* @param html URL of a CSS file.
* @param css URL of a CSS file.
*
* @return Returns a new instance of NSAttributedString or nil if given data was invalid.
*/
+ (instancetype)attributedStringFromHTMLFileAtURL:(NSURL *)html CSSURL:(NSURL *)css;
/**
* Creates an attributed string from HTML data and attributes parsed from attributes dict.
*
* @param data HTML data to be processed
* @param attributes Key-Value pairs of NSAttributedString attributes keyed under HTML tags.
*
* @return Returns a new instance of NSAttributedString or nil if given data was invalid.
*/
+ (instancetype)attributedStringFromHTMLData:(NSData *)data attributes:(NSDictionary *)attributes;
@end
/**
* Convinience methods for dealing with adding attributes to `NSAttributedStrings` from HTML.
*/
@interface NSMutableDictionary (CSS)
/**
* Sets attributes for a given HTML tag.
*
* @param attributes NSDictionary containing key-value pairs of `NSAttributedString` attributes.
* @param tag `HTML` tag to be assigned to the attributes
* @param flatten if flatten set to yes, the dictionary is converted into CSS string before being added to the receiver.
*/
- (void)addAttributes:(NSDictionary *)attributes forHTMLAttribute:(QRHTMLAttribute *)tag flatten:(BOOL)flatten;
@end
@interface NSDictionary (CSS)
/**
* Parses receiver and creates a `NSString` with `CSS` attributes.
*
* @return Returns a `NSString` with `CSS` attributes.
*/
- (NSString *)CSSStringFromAttributes;
@end
/**
* NSData category which adds method allowing to replace occurencies of given data with another data.
*/
@interface NSData (HTMLAdditions)
/**
* Creates `NSData` instance with replaced occurencies.
*
* @param data `NSData` to be replaced.
* @param replacementData `NSData` to be inserted in place of `data`.
*
* This method replaces all occurencies of `data` with `replacementData`.
*
* @return Returns `NSData` with replaced contents.
*/
- (NSData *)dataByReplacingOccurrencesOfData:(NSData *)data withData:(NSData *)replacementData;
@end
================================================
FILE: Pod/Classes/Extend/EUI/NSAttributedString+HTMLStyle.m
================================================
//
// NSAttributedString+HTMLStyle.m
// QRContentMobilizer
//
// Created by Wojciech Czekalski on 22.03.2014.
// Copyright (c) 2014 Wojciech Czekalski. All rights reserved.
//
#import "NSAttributedString+HTMLStyle.h"
#import "regex.h"
#import
QRHTMLAttribute * const QRHTMLAttributeParagraph = @"p";
QRHTMLAttribute * const QRHTMLAttributeLink = @"a";
QRHTMLAttribute * const QRHTMLAttributeHeader1 = @"h1";
QRHTMLAttribute * const QRHTMLAttributeHeader2 = @"h2";
QRHTMLAttribute * const QRHTMLAttributeHeader3 = @"h3";
QRHTMLAttribute * const QRHTMLAttributeHeader4 = @"h4";
QRHTMLAttribute * const QRHTMLAttributeHeader5 = @"h5";
QRHTMLAttribute * const QRHTMLAttributeHeader6 = @"h6";
QRHTMLAttribute * const QRHTMLAttributeEmphasis = @"em";
QRHTMLAttribute * const QRHTMLAttributeStrong = @"strong";
QRHTMLAttribute * const QRHTMLAttributeBold = @"b";
QRHTMLAttribute * const QRHTMLAttributeAlternateVoice = @"i";
QRHTMLAttribute * const QRHTMLAttributeSmall = @"small";
QRHTMLAttribute * const QRHTMLAttributeSubscripted = @"sub";
QRHTMLAttribute * const QRHTMLAttributeSuperscripted = @"sup";
QRHTMLAttribute * const QRHTMLAttributeInserted = @"ins";
QRHTMLAttribute * const QRHTMLAttributeDeleted = @"del";
QRHTMLAttribute * const QRHTMLAttributeHighlighted = @"mark";
QRHTMLAttribute * const QRHTMLAttributeCode = @"code";
QRHTMLAttribute * const QRHTMLAttributeKeyboardText = @"kbd";
QRHTMLAttribute * const QRHTMLAttributeSampleCode = @"samp";
QRHTMLAttribute * const QRHTMLAttributeVariable = @"var";
QRHTMLAttribute * const QRHTMLAttributePreformatted = @"pre";
QRHTMLAttribute * const QRHTMLAttributeAbbreviation = @"abbr";
QRHTMLAttribute * const QRHTMLAttributeAddress = @"address";
QRHTMLAttribute * const QRHTMLAttributeBlockQuote = @"blockquote";
QRHTMLAttribute * const QRHTMLAttributeInlineQuote = @"q";
QRHTMLAttribute * const QRHTMLAttributeTitle = @"cite";
QRHTMLAttribute * const QRHTMLAttributeDefinition = @"dfn";
@implementation NSAttributedString (HTMLStyle)
+ (instancetype)attributedStringFromHTMLFileAtURL:(NSURL *)html CSSURL:(NSURL *)css {
return [self attributedStringFromHTMLData:[NSData dataWithContentsOfURL:html] CSSData:[NSData dataWithContentsOfURL:css]];
}
+ (instancetype)attributedStringFromHTMLString:(NSString *)html CSSString:(NSString *)css {
return [self attributedStringFromHTMLData:[html dataUsingEncoding:NSUTF8StringEncoding] CSSData:[css dataUsingEncoding:NSUTF8StringEncoding]];
}
+ (instancetype)attributedStringFromHTMLData:(NSData *)data {
return [[self alloc] initWithData:data options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} documentAttributes:NULL error:nil];
}
+ (instancetype)attributedStringFromHTMLData:(NSData *)html CSSData:(NSData *)css {
if (css) {
NSMutableData *newHTMLData = [css mutableCopy];
[newHTMLData appendData:html];
return [self attributedStringFromHTMLData:newHTMLData];
}
return [self attributedStringFromHTMLData:html];
}
+ (instancetype)attributedStringFromHTMLData:(NSData *)data attributes:(NSDictionary *)attributes {
return [self attributedStringFromHTMLData:data CSSData:[[attributes CSSStringFromAttributes] dataUsingEncoding:NSUTF8StringEncoding]];
}
@end
@interface UIColor (HTMLRGBString)
- (NSString *)HTMLRGBString;
@end
@implementation UIColor (HTMLRGBString)
- (NSString *)HTMLRGBString {
UIColor *color = self;
CGFloat red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
if (CGColorGetNumberOfComponents(color.CGColor) == 2) {
CGFloat white = 0.f, alpha = 0.f;
[color getWhite:&white alpha:&alpha];
red = white;
green = white;
blue = white;
} else {
[color getRed:&red green:&green blue:&blue alpha:&alpha];
}
return [NSString stringWithFormat:@"rgb(%li, %li, %li)", lroundf(red*255.f), lroundf(green*255.f), lroundf(blue*255.f)];
}
@end
@implementation NSDictionary (CSS)
+ (NSString *)cssStringWithValues:(NSDictionary *)attributes HTMLTag:(QRHTMLAttribute *)tag {
NSMutableString *cssString = [NSMutableString stringWithFormat:@"%@ {", tag];
for (NSString *key in attributes) {
#if DEBUG
NSSet *set = [NSSet setWithObjects:NSLigatureAttributeName, NSKernAttributeName, NSStrikethroughStyleAttributeName, NSStrikethroughColorAttributeName, NSUnderlineStyleAttributeName, NSStrokeColorAttributeName, NSStrokeWidthAttributeName, NSTextEffectAttributeName, NSObliquenessAttributeName, NSExpansionAttributeName, NSWritingDirectionAttributeName, NSVerticalGlyphFormAttributeName, NSUnderlineColorAttributeName, NSAttachmentAttributeName, NSLinkAttributeName, NSBaselineOffsetAttributeName, nil];
NSAssert(![set containsObject:key], @"Invalid Key. This library doesn't support %@ yet.", key);
#endif
if (key == NSFontAttributeName) {
UIFont *font = attributes[NSFontAttributeName];
[cssString appendFormat:@"font-family:'%@'; font-size: %0.fpx; ", font.fontName, roundf(font.pointSize)];;
} else if (key == NSParagraphStyleAttributeName) {
NSParagraphStyle *style = attributes[key];
NSString *alignment;
switch (style.alignment) {
case NSTextAlignmentCenter:
alignment = @"center";
break;
case NSTextAlignmentJustified:
alignment = @"justify";
break;
case NSTextAlignmentLeft:
alignment = @"left";
break;
case NSTextAlignmentNatural:
alignment = @"initial";
break;
case NSTextAlignmentRight:
alignment = @"right";
break;
default:
alignment = @"left";
break;
}
[cssString appendFormat:@"line-height:%0.1f%%; text-align:%@;", style.lineHeightMultiple*100, alignment];
if (style.baseWritingDirection == NSWritingDirectionRightToLeft){
[cssString appendString:@"direction:rtl;"];
}else{
[cssString appendString:@"direction:ltr;"];
}
} else if (key == NSForegroundColorAttributeName) {
[cssString appendFormat:@"color:%@; ", [attributes[key] HTMLRGBString]];
} else if (key == NSBackgroundColorAttributeName ) {
[cssString appendFormat:@"background-color:%@; ", [attributes[key] HTMLRGBString]];;
} else if (key == NSShadowAttributeName) {
NSShadow *shadow = attributes[NSShadowAttributeName];
[cssString appendFormat:@"text-shadow: %fpx %fpx %fpx %@; ", shadow.shadowOffset.width, shadow.shadowOffset.height, shadow.shadowBlurRadius, [shadow.shadowColor HTMLRGBString]];
}
}
[cssString appendString:@"}"];
return cssString;
}
- (NSString *)CSSStringFromAttributes {
NSMutableString *string = [NSMutableString stringWithString:@""];
return string;
}
@end
@implementation NSMutableDictionary (CSS)
- (void)addAttributes:(NSDictionary *)attributes forHTMLAttribute:(QRHTMLAttribute *)tag flatten:(BOOL)flatten {
if (!flatten) {
[self setObject:attributes forKey:tag];
} else {
[self setObject:[NSDictionary cssStringWithValues:attributes HTMLTag:tag] forKey:tag];
}
}
@end
@implementation NSData (HTMLAdditions)
- (NSData *)dataByReplacingOccurrencesOfData:(NSData *)data withData:(NSData *)replacementData {
NSMutableData *mutableSelf = [self mutableCopy];
const void *replacementBytes = [replacementData bytes];
NSUInteger replacementBytesLength = [replacementData length];
NSRange rangeOfCharacters = [mutableSelf rangeOfData:data options:0 range:NSMakeRange(0, [mutableSelf length])];
while (rangeOfCharacters.location != NSNotFound) {
[mutableSelf replaceBytesInRange:rangeOfCharacters withBytes:replacementBytes];
NSUInteger searchLocation = replacementBytesLength + rangeOfCharacters.location;
rangeOfCharacters = [mutableSelf rangeOfData:data options:0 range:NSMakeRange(searchLocation, [mutableSelf length]-searchLocation)];
}
return [NSData dataWithData:mutableSelf];
}
@end
================================================
FILE: Pod/Classes/Extend/EUI/StringFormat.swift
================================================
//
// StringFormat.swift
// Pods
//
// Created by zhuchao on 15/10/15.
//
//
import Foundation
extension String{
var viewContentMode:UIViewContentMode{
var dict = Dictionary()
dict["ScaleToFill"] = UIViewContentMode.ScaleToFill
dict["ScaleAspectFit"] = UIViewContentMode.ScaleAspectFit
dict["ScaleAspectFill"] = UIViewContentMode.ScaleAspectFill
dict["Redraw"] = UIViewContentMode.Redraw
dict["Center"] = UIViewContentMode.Center
dict["Top"] = UIViewContentMode.Top
dict["Bottom"] = UIViewContentMode.Bottom
dict["Left"] = UIViewContentMode.Left
dict["Right"] = UIViewContentMode.Right
dict["TopLeft"] = UIViewContentMode.TopLeft
dict["TopRight"] = UIViewContentMode.TopRight
dict["BottomLeft"] = UIViewContentMode.BottomLeft
dict["BottomRight"] = UIViewContentMode.BottomRight
if let mode = dict[self.trim]{
return mode
}else{
return UIViewContentMode.ScaleToFill
}
}
var flexContentDirection:FLEXBOXContentDirection{
switch self.trim {
case "ltr":
return .LeftToRight
case "rtl":
return .RightToLeft
case "inherit":
return .Inherit
default:
return .LeftToRight
}
}
var justifyContent:FLEXBOXJustification{
switch self.trim {
case "center":
return .Center
case "flex-start":
return .FlexStart
case "flex-end":
return .FlexEnd
case "space-between":
return .SpaceBetween
case "space-around":
return .SpaceAround
default:
return .FlexStart
}
}
var alignItems:FLEXBOXAlignment{
switch self.trim {
case "center":
return .Center
case "flex-start":
return .FlexStart
case "flex-end":
return .FlexEnd
case "stretch":
return .Stretch
case "auto":
return .Auto
default:
return .Auto
}
}
var flexDirection:FLEXBOXFlexDirection{
switch self.trim {
case "column":
return .Column
case "row":
return .Row
case "row-reverse":
return .RowReverse
case "column-reverse":
return .ColumnReverse
default:
return .Row
}
}
var separatorStyle:UITableViewCellSeparatorStyle{
switch self.trim{
case "None" :
return .None
case "SingleLine":
return .SingleLine
case "SingleLineEtched":
return .SingleLineEtched
default:
return .SingleLine
}
}
var tableViewStyle:UITableViewStyle{
switch self.trim{
case "plain":
return .Plain
case "grouped":
return .Grouped
default:
return .Plain
}
}
var scrollViewIndicatorStyle:UIScrollViewIndicatorStyle{
switch self.trim{
case "white":
return .White
case "black":
return .Black
default:
return .Default
}
}
var textAlignment:NSTextAlignment {
switch(self.trim){
case "center":
return NSTextAlignment.Center
case "left":
return NSTextAlignment.Left
case "right":
return NSTextAlignment.Right
case "justified":
return NSTextAlignment.Justified
case "natural":
return NSTextAlignment.Natural
default:
return NSTextAlignment.Left
}
}
var linkStyleDict:[NSObject:AnyObject]{
let linkArray = self.trimArrayBy(";")
var dict = Dictionary()
for str in linkArray {
var strArray = str.trimArrayBy(":")
if strArray.count == 2 {
switch strArray[0] {
case "color":
dict[kCTForegroundColorAttributeName] = UIColor(CSS: strArray[1].trim)
case "text-decoration":
dict[NSUnderlineStyleAttributeName] = strArray[1].trim.underlineStyle.rawValue
default :
dict[NSUnderlineStyleAttributeName] = NSUnderlineStyle.StyleSingle.rawValue
}
}
}
return dict
}
var keyboardType:UIKeyboardType {
switch self.lowercaseString {
case "Default".lowercaseString:
return UIKeyboardType.Default
case "ASCIICapable".lowercaseString:
return UIKeyboardType.ASCIICapable
case "NumbersAndPunctuation".lowercaseString:
return UIKeyboardType.NumbersAndPunctuation
case "URL".lowercaseString:
return UIKeyboardType.URL
case "NumberPad".lowercaseString:
return UIKeyboardType.NumberPad
case "PhonePad".lowercaseString:
return UIKeyboardType.PhonePad
case "NamePhonePad".lowercaseString:
return UIKeyboardType.NamePhonePad
case "EmailAddress".lowercaseString:
return UIKeyboardType.EmailAddress
case "DecimalPad".lowercaseString:
return UIKeyboardType.DecimalPad
case "Twitter".lowercaseString:
return UIKeyboardType.Twitter
case "Twitter".lowercaseString:
return UIKeyboardType.WebSearch
default:
return UIKeyboardType.Default
}
}
var underlineStyle:NSUnderlineStyle{
switch self.lowercaseString {
case "None".lowercaseString :
return NSUnderlineStyle.StyleNone
case "StyleSingle".lowercaseString :
return NSUnderlineStyle.StyleSingle
case "StyleThick".lowercaseString :
return NSUnderlineStyle.StyleThick
case "StyleDouble".lowercaseString :
return NSUnderlineStyle.StyleDouble
case "PatternDot".lowercaseString :
return NSUnderlineStyle.PatternDot
case "PatternDash".lowercaseString :
return NSUnderlineStyle.PatternDash
case "PatternDashDot".lowercaseString :
return NSUnderlineStyle.PatternDashDot
case "PatternDashDotDot".lowercaseString :
return NSUnderlineStyle.PatternDashDotDot
case "ByWord".lowercaseString :
return NSUnderlineStyle.ByWord
default :
return NSUnderlineStyle.StyleSingle
}
}
var controlEvent: UIControlEvents{
switch self.lowercaseString {
case "TouchDown".lowercaseString :
return UIControlEvents.TouchDown
case "TouchDownRepeat".lowercaseString :
return UIControlEvents.TouchDownRepeat
case "TouchDragInside".lowercaseString :
return UIControlEvents.TouchDragInside
case "TouchDragOutside".lowercaseString :
return UIControlEvents.TouchDragOutside
case "TouchDragEnter".lowercaseString :
return UIControlEvents.TouchDragEnter
case "TouchDragExit".lowercaseString :
return UIControlEvents.TouchDragExit
case "TouchUpInside".lowercaseString :
return UIControlEvents.TouchUpInside
case "TouchUpOutside".lowercaseString :
return UIControlEvents.TouchUpOutside
case "ValueChanged".lowercaseString :
return UIControlEvents.ValueChanged
case "TouchCancel".lowercaseString :
return UIControlEvents.TouchCancel
case "EditingDidBegin".lowercaseString :
return UIControlEvents.EditingDidBegin
case "EditingChanged".lowercaseString :
return UIControlEvents.EditingChanged
case "EditingDidEnd".lowercaseString :
return UIControlEvents.EditingDidEnd
case "EditingDidEndOnExit".lowercaseString :
return UIControlEvents.EditingDidEndOnExit
case "AllTouchEvents".lowercaseString :
return UIControlEvents.AllTouchEvents
case "AllEditingEvents".lowercaseString :
return UIControlEvents.AllEditingEvents
case "ApplicationReserved".lowercaseString :
return UIControlEvents.ApplicationReserved
case "SystemReserved".lowercaseString :
return UIControlEvents.SystemReserved
case "AllEvents".lowercaseString :
return UIControlEvents.AllEvents
default :
return UIControlEvents.TouchUpInside
}
}
}
================================================
FILE: Pod/Classes/Extend/EUI/SwiftTryCatch.h
================================================
//
// SwiftTryCatch.h
//
// Created by William Falcon on 10/10/14.
// Copyright (c) 2014 William Falcon. All rights reserved.
//
/*
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#import
@import UIKit;
@interface SwiftTryCatch : NSObject
/**
Provides try catch functionality for swift by wrapping around Objective-C
*/
+ (void)try:(void(^)())try catch:(void(^)(NSException*exception))catch finally:(void(^)())finally;
+ (void)throwString:(NSString*)s;
+ (void)throwException:(NSException*)e;
@end
================================================
FILE: Pod/Classes/Extend/EUI/SwiftTryCatch.m
================================================
//
// SwiftTryCatch.h
//
// Created by William Falcon on 10/10/14.
// Copyright (c) 2014 William Falcon. All rights reserved.
//
/*
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#import "SwiftTryCatch.h"
@implementation SwiftTryCatch
/**
Provides try catch functionality for swift by wrapping around Objective-C
*/
+(void)try:(void (^)())try catch:(void (^)(NSException *))catch finally:(void (^)())finally{
@try {
try ? try() : nil;
}
@catch (NSException *exception) {
catch ? catch(exception) : nil;
}
@finally {
finally ? finally() : nil;
}
}
+ (void)throwString:(NSString*)s
{
@throw [NSException exceptionWithName:s reason:s userInfo:nil];
}
+ (void)throwException:(NSException*)e
{
@throw e;
}
@end
================================================
FILE: Pod/Classes/Extend/EUI/UIColor+HTMLColors.h
================================================
//
// UIColor+HTMLColors.h
//
// Created by James Lawton on 12/9/12.
// Copyright (c) 2012 James Lawton. All rights reserved.
//
#import
/**
* Extensions to read and write colors in the formats supported by CSS.
* Emphasis has been given to parsing corrently formatted colors, rather
* than rejecting technically invalid colors.
*/
@interface UIColor (HTMLColors)
/**
* Reads a color from a string containing hex, RGB, HSL or X11 named color.
* Returns `nil` on failure.
*/
+ (UIColor *)colorWithCSS:(NSString *)cssColor;
/**
* Reads a color from a string containing a hex color, of the form
* "#FFFFFF" or "#FFF".
* Returns `nil` on failure.
*/
+ (UIColor *)colorWithHexString:(NSString *)hexColor;
/**
* Reads a color from a string containing an RGB color, of the form
* "rgb(255, 255, 255)" or "rgba(255, 255, 255, 1.0)". Supports components
* represented as percentages.
* Returns `nil` on failure.
*/
+ (UIColor *)colorWithRGBString:(NSString *)rgbColor;
/**
* Reads a color from a string containing an HSL color, of the form
* "hsl(359, 100%, 100%)" or "hsla(359, 100%, 100%, 1.0)".
* Returns `nil` on failure.
*/
+ (UIColor *)colorWithHSLString:(NSString *)hslColor;
/**
* Reads a color from a string containing a W3C named color.
* Returns `nil` on failure.
*/
+ (UIColor *)colorWithW3CNamedColor:(NSString *)namedColor;
/**
* Returns a representation of this color as a hex string, of the form "#FFFFFF".
* Alpha information is not represented.
*/
- (NSString *)hexStringValue;
/**
* Returns a representation of this color as an RGB string, of the form
* "rgb(255, 255, 255)" or "rgba(255, 255, 255, 1.0)".
* Returns `nil` on failure.
*/
- (NSString *)rgbStringValue;
/**
* Returns a representation of this color as an RGB string, of the form
* "hsl(359, 100%, 100%)" or "hsla(359, 100%, 100%, 1.0)".
* Returns `nil` on failure.
*/
- (NSString *)hslStringValue;
/**
* FOR DEBUGGING - All the supported W3C color names.
*/
+ (NSArray *)W3CColorNames;
@end
/**
* Extensions to scan colors in the formats supported by CSS.
*/
@interface NSScanner (HTMLColors)
/**
* Scan a color hex, RGB, HSL or X11 named color.
*/
- (BOOL)scanCSSColor:(UIColor **)color;
/**
* Scan an RGB color ("rgb(255, 255, 255)", "rgba(255, 255, 255, 1.0)").
*/
- (BOOL)scanRGBColor:(UIColor **)color;
/**
* Scan an HSL color ("hsl(359, 100%, 100%)", "hsla(359, 100%, 100%, 1.0)").
*/
- (BOOL)scanHSLColor:(UIColor **)color;
/**
* Scan a hex color ("#FFFFFF", "#FFF").
*/
- (BOOL)scanHexColor:(UIColor **)color;
/**
* Scan a CSS3/SVG named color. These are similar to the X11 named colors.
* See: http://www.w3.org/TR/css3-color/#svg-color
*/
- (BOOL)scanW3CNamedColor:(UIColor **)color;
@end
================================================
FILE: Pod/Classes/Extend/EUI/UIColor+HTMLColors.m
================================================
//
// UIColor+HTMLColors.m
//
// Created by James Lawton on 12/9/12.
// Copyright (c) 2012 James Lawton. All rights reserved.
//
#import "UIColor+HTMLColors.h"
typedef struct {
CGFloat a, b, c;
} CMRFloatTriple;
typedef struct {
CGFloat a, b, c, d;
} CMRFloatQuad;
// CSS uses HSL, but we have to specify UIColor as HSB
static inline CMRFloatTriple HSB2HSL(CGFloat hue, CGFloat saturation, CGFloat brightness);
static inline CMRFloatTriple HSL2HSB(CGFloat hue, CGFloat saturation, CGFloat lightness);
static NSArray *CMRW3CColorNames(void);
static NSDictionary *CMRW3CNamedColors(void);
@implementation UIColor (HTMLColors)
#pragma mark - Reading
+ (UIColor *)colorWithCSS:(NSString *)cssColor
{
UIColor *color = nil;
NSScanner *scanner = [NSScanner scannerWithString:cssColor];
[scanner scanCSSColor:&color];
return (scanner.isAtEnd) ? color : nil;
}
+ (UIColor *)colorWithHexString:(NSString *)hexColor
{
UIColor *color = nil;
NSScanner *scanner = [NSScanner scannerWithString:hexColor];
[scanner scanHexColor:&color];
return (scanner.isAtEnd) ? color : nil;
}
+ (UIColor *)colorWithRGBString:(NSString *)rgbColor
{
UIColor *color = nil;
NSScanner *scanner = [NSScanner scannerWithString:rgbColor];
[scanner scanRGBColor:&color];
return (scanner.isAtEnd) ? color : nil;
}
+ (UIColor *)colorWithHSLString:(NSString *)hslColor
{
UIColor *color = nil;
NSScanner *scanner = [NSScanner scannerWithString:hslColor];
[scanner scanHSLColor:&color];
return (scanner.isAtEnd) ? color : nil;
}
+ (UIColor *)colorWithW3CNamedColor:(NSString *)namedColor
{
UIColor *color = nil;
NSScanner *scanner = [NSScanner scannerWithString:namedColor];
[scanner scanW3CNamedColor:&color];
return (scanner.isAtEnd) ? color : nil;
}
#pragma mark - Writing
static inline unsigned ToByte(CGFloat f)
{
f = MAX(0, MIN(f, 1)); // Clamp
return (unsigned)round(f * 255);
}
- (NSString *)hexStringValue
{
NSString *hex = nil;
CGFloat red, green, blue, alpha;
if ([self cmr_getRed:&red green:&green blue:&blue alpha:&alpha]) {
hex = [NSString stringWithFormat:@"#%02X%02X%02X",
ToByte(red), ToByte(green), ToByte(blue)];
}
return hex;
}
- (NSString *)rgbStringValue
{
NSString *rgb = nil;
CGFloat red, green, blue, alpha;
if ([self cmr_getRed:&red green:&green blue:&blue alpha:&alpha]) {
if (alpha == 1.0) {
rgb = [NSString stringWithFormat:@"rgb(%u, %u, %u)",
ToByte(red), ToByte(green), ToByte(blue)];
} else {
rgb = [NSString stringWithFormat:@"rgba(%u, %u, %u, %g)",
ToByte(red), ToByte(green), ToByte(blue), alpha];
}
}
return rgb;
}
static inline unsigned ToDeg(CGFloat f)
{
return (unsigned)round(f * 360) % 360;
}
static inline unsigned ToPercentage(CGFloat f)
{
f = MAX(0, MIN(f, 1)); // Clamp
return (unsigned)round(f * 100);
}
- (NSString *)hslStringValue
{
NSString *hsl = nil;
CGFloat hue, saturation, brightness, alpha;
if ([self cmr_getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha]) {
CMRFloatTriple hslVal = HSB2HSL(hue, saturation, brightness);
if (alpha == 1.0) {
hsl = [NSString stringWithFormat:@"hsl(%u, %u%%, %u%%)",
ToDeg(hslVal.a), ToPercentage(hslVal.b), ToPercentage(hslVal.c)];
} else {
hsl = [NSString stringWithFormat:@"hsla(%u, %u%%, %u%%, %g)",
ToDeg(hslVal.a), ToPercentage(hslVal.b), ToPercentage(hslVal.c), alpha];
}
}
return hsl;
}
// Fix up getting color components
- (BOOL)cmr_getRed:(CGFloat *)red green:(CGFloat *)green blue:(CGFloat *)blue alpha:(CGFloat *)alpha
{
if ([self getRed:red green:green blue:blue alpha:alpha]) {
return YES;
}
CGFloat white;
if ([self getWhite:&white alpha:alpha]) {
if (red)
*red = white;
if (green)
*green = white;
if (blue)
*blue = white;
return YES;
}
return NO;
}
- (BOOL)cmr_getHue:(CGFloat *)hue saturation:(CGFloat *)saturation brightness:(CGFloat *)brightness alpha:(CGFloat *)alpha
{
if ([self getHue:hue saturation:saturation brightness:brightness alpha:alpha]) {
return YES;
}
CGFloat white;
if ([self getWhite:&white alpha:alpha]) {
if (hue)
*hue = 0;
if (saturation)
*saturation = 0;
if (brightness)
*brightness = white;
return YES;
}
return NO;
}
+ (NSArray *)W3CColorNames
{
return [[CMRW3CNamedColors() allKeys] sortedArrayUsingSelector:@selector(compare:)];
}
@end
@implementation NSScanner (HTMLColors)
- (BOOL)scanCSSColor:(UIColor **)color
{
return [self scanHexColor:color]
|| [self scanRGBColor:color]
|| [self scanHSLColor:color]
|| [self cmr_scanTransparent:color]
|| [self scanW3CNamedColor:color];
}
- (BOOL)scanRGBColor:(UIColor **)color
{
return [self cmr_caseInsensitiveWithCleanup:^BOOL{
if ([self scanString:@"rgba" intoString:NULL]) {
CMRFloatQuad scale = {1.0/255.0, 1.0/255.0, 1.0/255.0, 1.0};
CMRFloatQuad q;
if ([self cmr_scanFloatQuad:&q scale:scale]) {
if (color) {
*color = [UIColor colorWithRed:q.a green:q.b blue:q.c alpha:q.d];
}
return YES;
}
} else if ([self scanString:@"rgb" intoString:NULL]) {
CMRFloatTriple scale = {1.0/255.0, 1.0/255.0, 1.0/255.0};
CMRFloatTriple t;
if ([self cmr_scanFloatTriple:&t scale:scale]) {
if (color) {
*color = [UIColor colorWithRed:t.a green:t.b blue:t.c alpha:1.0];
}
return YES;
}
}
return NO;
}];
}
// Wrap hues in a circle, where [0,1] = [0°,360°]
static inline CGFloat CMRNormHue(CGFloat hue)
{
return hue - floor(hue);
}
- (BOOL)scanHSLColor:(UIColor **)color
{
return [self cmr_caseInsensitiveWithCleanup:^BOOL{
if ([self scanString:@"hsla" intoString:NULL]) {
CMRFloatQuad scale = {1.0/360.0, 1.0, 1.0, 1.0};
CMRFloatQuad q;
if ([self cmr_scanFloatQuad:&q scale:scale]) {
if (color) {
CMRFloatTriple t = HSL2HSB(CMRNormHue(q.a), q.b, q.c);
*color = [UIColor colorWithHue:t.a saturation:t.b brightness:t.c alpha:q.d];
}
return YES;
}
} else if ([self scanString:@"hsl" intoString:NULL]) {
CMRFloatTriple scale = {1.0/360.0, 1.0, 1.0};
CMRFloatTriple t;
if ([self cmr_scanFloatTriple:&t scale:scale]) {
if (color) {
t = HSL2HSB(CMRNormHue(t.a), t.b, t.c);
*color = [UIColor colorWithHue:t.a saturation:t.b brightness:t.c alpha:1.0];
}
return YES;
}
}
return NO;
}];
}
- (BOOL)scanHexColor:(UIColor **)color
{
return [self cmr_resetScanLocationOnFailure:^BOOL{
return [self scanString:@"#" intoString:NULL]
&& [self cmr_scanHexTriple:color];
}];
}
- (BOOL)scanW3CNamedColor:(UIColor **)color
{
return [self cmr_caseInsensitiveWithCleanup:^BOOL{
NSArray *colorNames = CMRW3CColorNames();
NSDictionary *namedColors = CMRW3CNamedColors();
for (NSString *name in colorNames) {
if ([self scanString:name intoString:NULL]) {
if (color) {
*color = [UIColor colorWithHexString:namedColors[name]];
}
return YES;
}
}
return NO;
}];
}
#pragma mark - Private
- (void)cmr_withSkip:(NSCharacterSet *)chars run:(void (^)(void))block
{
NSCharacterSet *skipped = self.charactersToBeSkipped;
self.charactersToBeSkipped = chars;
block();
self.charactersToBeSkipped = skipped;
}
- (void)cmr_withNoSkip:(void (^)(void))block
{
NSCharacterSet *skipped = self.charactersToBeSkipped;
self.charactersToBeSkipped = nil;
block();
self.charactersToBeSkipped = skipped;
}
- (NSRange)cmr_rangeFromScanLocation
{
NSUInteger loc = self.scanLocation;
NSUInteger len = self.string.length - loc;
return NSMakeRange(loc, len);
}
- (void)cmr_skipCharactersInSet:(NSCharacterSet *)chars
{
[self cmr_withNoSkip:^{
[self scanCharactersFromSet:chars intoString:NULL];
}];
}
- (void)cmr_skip
{
[self cmr_skipCharactersInSet:self.charactersToBeSkipped];
}
- (BOOL)cmr_resetScanLocationOnFailure:(BOOL (^)(void))block
{
NSUInteger initialScanLocation = self.scanLocation;
if (!block()) {
self.scanLocation = initialScanLocation;
return NO;
}
return YES;
}
- (BOOL)cmr_caseInsensitiveWithCleanup:(BOOL (^)(void))block
{
NSUInteger initialScanLocation = self.scanLocation;
BOOL caseSensitive = self.caseSensitive;
self.caseSensitive = NO;
BOOL success = block();
if (!success) {
self.scanLocation = initialScanLocation;
}
self.caseSensitive = caseSensitive;
return success;
}
// Scan, but only so far
- (NSRange)cmr_scanCharactersInSet:(NSCharacterSet *)chars maxLength:(NSUInteger)maxLength intoString:(NSString **)outString
{
NSRange range = [self cmr_rangeFromScanLocation];
range.length = MIN(range.length, maxLength);
NSUInteger len;
for (len = 0; len < range.length; ++len) {
if (![chars characterIsMember:[self.string characterAtIndex:(range.location + len)]]) {
break;
}
}
NSRange charRange = NSMakeRange(range.location, len);
if (outString) {
*outString = [self.string substringWithRange:charRange];
}
self.scanLocation = charRange.location + charRange.length;
return charRange;
}
// Hex characters
static NSCharacterSet *CMRHexCharacters() {
static NSCharacterSet *hexChars;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
hexChars = [NSCharacterSet characterSetWithCharactersInString:@"0123456789ABCDEFabcdef"];
});
return hexChars;
}
// We know we've got hex already, so assume this works
static NSUInteger CMRParseHex(NSString *str, BOOL repeated)
{
unsigned int ans = 0;
if (repeated) {
str = [NSString stringWithFormat:@"%@%@", str, str];
}
NSScanner *scanner = [NSScanner scannerWithString:str];
[scanner scanHexInt:&ans];
return ans;
}
// Scan FFF or FFFFFF, doesn't reset scan location on failure
- (BOOL)cmr_scanHexTriple:(UIColor **)color
{
NSString *hex = nil;
NSRange range = [self cmr_scanCharactersInSet:CMRHexCharacters() maxLength:6 intoString:&hex];
CGFloat red, green, blue;
if (hex.length == 6) {
// Parse 2 chars per component
red = CMRParseHex([hex substringWithRange:NSMakeRange(0, 2)], NO) / 255.0;
green = CMRParseHex([hex substringWithRange:NSMakeRange(2, 2)], NO) / 255.0;
blue = CMRParseHex([hex substringWithRange:NSMakeRange(4, 2)], NO) / 255.0;
} else if (hex.length >= 3) {
// Parse 1 char per component, but repeat it to calculate hex value
red = CMRParseHex([hex substringWithRange:NSMakeRange(0, 1)], YES) / 255.0;
green = CMRParseHex([hex substringWithRange:NSMakeRange(1, 1)], YES) / 255.0;
blue = CMRParseHex([hex substringWithRange:NSMakeRange(2, 1)], YES) / 255.0;
self.scanLocation = range.location + 3;
} else {
return NO; // Fail
}
if (color) {
*color = [UIColor colorWithRed:red green:green blue:blue alpha:1.0];
}
return YES;
}
// Scan "transparent"
- (BOOL)cmr_scanTransparent:(UIColor **)color
{
return [self cmr_caseInsensitiveWithCleanup:^BOOL{
if ([self scanString:@"transparent" intoString:NULL]) {
if (color) {
*color = [UIColor colorWithWhite:0 alpha:0];
}
return YES;
}
return NO;
}];
}
// Scan a float or percentage. Multiply float by `scale` if it was not a
// percentage.
- (BOOL)cmr_scanNum:(CGFloat *)value scale:(CGFloat)scale
{
float f = 0.0;
if ([self scanFloat:&f]) {
if ([self scanString:@"%" intoString:NULL]) {
f *= 0.01;
} else {
f *= scale;
}
if (value) {
*value = f;
}
return YES;
}
return NO;
}
// Scan a triple of numbers "(10, 10, 10)". If they are not percentages, multiply
// by the corresponding `scale` component.
- (BOOL)cmr_scanFloatTriple:(CMRFloatTriple *)triple scale:(CMRFloatTriple)scale
{
__block BOOL success = NO;
__block CMRFloatTriple t;
[self cmr_withSkip:[NSCharacterSet whitespaceAndNewlineCharacterSet] run:^{
success = [self scanString:@"(" intoString:NULL]
&& [self cmr_scanNum:&(t.a) scale:scale.a]
&& [self scanString:@"," intoString:NULL]
&& [self cmr_scanNum:&(t.b) scale:scale.b]
&& [self scanString:@"," intoString:NULL]
&& [self cmr_scanNum:&(t.c) scale:scale.c]
&& [self scanString:@")" intoString:NULL];
}];
if (triple) {
*triple = t;
}
return success;
}
// Scan a quad of numbers "(10, 10, 10, 10)". If they are not percentages,
// multiply by the corresponding `scale` component.
- (BOOL)cmr_scanFloatQuad:(CMRFloatQuad *)quad scale:(CMRFloatQuad)scale
{
__block BOOL success = NO;
__block CMRFloatQuad q;
[self cmr_withSkip:[NSCharacterSet whitespaceAndNewlineCharacterSet] run:^{
success = [self scanString:@"(" intoString:NULL]
&& [self cmr_scanNum:&(q.a) scale:scale.a]
&& [self scanString:@"," intoString:NULL]
&& [self cmr_scanNum:&(q.b) scale:scale.b]
&& [self scanString:@"," intoString:NULL]
&& [self cmr_scanNum:&(q.c) scale:scale.c]
&& [self scanString:@"," intoString:NULL]
&& [self cmr_scanNum:&(q.d) scale:scale.d]
&& [self scanString:@")" intoString:NULL];
}];
if (quad) {
*quad = q;
}
return success;
}
@end
static inline CMRFloatTriple HSB2HSL(CGFloat hue, CGFloat saturation, CGFloat brightness)
{
CGFloat l = (2.0 - saturation) * brightness;
saturation *= brightness;
CGFloat satDiv = (l <= 1.0) ? l : (2.0 - l);
if (satDiv) {
saturation /= satDiv;
}
l *= 0.5;
CMRFloatTriple hsl = {
hue,
saturation,
l
};
return hsl;
}
static inline CMRFloatTriple HSL2HSB(CGFloat hue, CGFloat saturation, CGFloat l)
{
l *= 2.0;
CGFloat s = saturation * ((l <= 1.0) ? l : (2.0 - l));
CGFloat brightness = (l + s) * 0.5;
if (s) {
s = (2.0 * s) / (l + s);
}
CMRFloatTriple hsb = {
hue,
s,
brightness
};
return hsb;
}
// Color names, longest first
static NSArray *CMRW3CColorNames() {
static NSArray *colorNames;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
colorNames = [[CMRW3CNamedColors() allKeys] sortedArrayUsingComparator:^NSComparisonResult(NSString *k1, NSString *k2) {
NSInteger diff = k1.length - k2.length;
if (!diff) {
return NSOrderedSame;
} else if (diff > 0) {
return NSOrderedAscending;
} else {
return NSOrderedDescending;
}
}];
});
return colorNames;
}
// Color values as defined in CSS3 spec.
// See: http://www.w3.org/TR/css3-color/#svg-color
static NSDictionary *CMRW3CNamedColors() {
static NSDictionary *namedColors;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
namedColors = @{
@"AliceBlue" : @"#F0F8FF",
@"AntiqueWhite" : @"#FAEBD7",
@"Aqua" : @"#00FFFF",
@"Aquamarine" : @"#7FFFD4",
@"Azure" : @"#F0FFFF",
@"Beige" : @"#F5F5DC",
@"Bisque" : @"#FFE4C4",
@"Black" : @"#000000",
@"BlanchedAlmond" : @"#FFEBCD",
@"Blue" : @"#0000FF",
@"BlueViolet" : @"#8A2BE2",
@"Brown" : @"#A52A2A",
@"BurlyWood" : @"#DEB887",
@"CadetBlue" : @"#5F9EA0",
@"Chartreuse" : @"#7FFF00",
@"Chocolate" : @"#D2691E",
@"Coral" : @"#FF7F50",
@"CornflowerBlue" : @"#6495ED",
@"Cornsilk" : @"#FFF8DC",
@"Crimson" : @"#DC143C",
@"Cyan" : @"#00FFFF",
@"DarkBlue" : @"#00008B",
@"DarkCyan" : @"#008B8B",
@"DarkGoldenRod" : @"#B8860B",
@"DarkGray" : @"#A9A9A9",
@"DarkGrey" : @"#A9A9A9",
@"DarkGreen" : @"#006400",
@"DarkKhaki" : @"#BDB76B",
@"DarkMagenta" : @"#8B008B",
@"DarkOliveGreen" : @"#556B2F",
@"DarkOrange" : @"#FF8C00",
@"DarkOrchid" : @"#9932CC",
@"DarkRed" : @"#8B0000",
@"DarkSalmon" : @"#E9967A",
@"DarkSeaGreen" : @"#8FBC8F",
@"DarkSlateBlue" : @"#483D8B",
@"DarkSlateGray" : @"#2F4F4F",
@"DarkSlateGrey" : @"#2F4F4F",
@"DarkTurquoise" : @"#00CED1",
@"DarkViolet" : @"#9400D3",
@"DeepPink" : @"#FF1493",
@"DeepSkyBlue" : @"#00BFFF",
@"DimGray" : @"#696969",
@"DimGrey" : @"#696969",
@"DodgerBlue" : @"#1E90FF",
@"FireBrick" : @"#B22222",
@"FloralWhite" : @"#FFFAF0",
@"ForestGreen" : @"#228B22",
@"Fuchsia" : @"#FF00FF",
@"Gainsboro" : @"#DCDCDC",
@"GhostWhite" : @"#F8F8FF",
@"Gold" : @"#FFD700",
@"GoldenRod" : @"#DAA520",
@"Gray" : @"#808080",
@"Grey" : @"#808080",
@"Green" : @"#008000",
@"GreenYellow" : @"#ADFF2F",
@"HoneyDew" : @"#F0FFF0",
@"HotPink" : @"#FF69B4",
@"IndianRed" : @"#CD5C5C",
@"Indigo" : @"#4B0082",
@"Ivory" : @"#FFFFF0",
@"Khaki" : @"#F0E68C",
@"Lavender" : @"#E6E6FA",
@"LavenderBlush" : @"#FFF0F5",
@"LawnGreen" : @"#7CFC00",
@"LemonChiffon" : @"#FFFACD",
@"LightBlue" : @"#ADD8E6",
@"LightCoral" : @"#F08080",
@"LightCyan" : @"#E0FFFF",
@"LightGoldenRodYellow" : @"#FAFAD2",
@"LightGray" : @"#D3D3D3",
@"LightGrey" : @"#D3D3D3",
@"LightGreen" : @"#90EE90",
@"LightPink" : @"#FFB6C1",
@"LightSalmon" : @"#FFA07A",
@"LightSeaGreen" : @"#20B2AA",
@"LightSkyBlue" : @"#87CEFA",
@"LightSlateGray" : @"#778899",
@"LightSlateGrey" : @"#778899",
@"LightSteelBlue" : @"#B0C4DE",
@"LightYellow" : @"#FFFFE0",
@"Lime" : @"#00FF00",
@"LimeGreen" : @"#32CD32",
@"Linen" : @"#FAF0E6",
@"Magenta" : @"#FF00FF",
@"Maroon" : @"#800000",
@"MediumAquaMarine" : @"#66CDAA",
@"MediumBlue" : @"#0000CD",
@"MediumOrchid" : @"#BA55D3",
@"MediumPurple" : @"#9370DB",
@"MediumSeaGreen" : @"#3CB371",
@"MediumSlateBlue" : @"#7B68EE",
@"MediumSpringGreen" : @"#00FA9A",
@"MediumTurquoise" : @"#48D1CC",
@"MediumVioletRed" : @"#C71585",
@"MidnightBlue" : @"#191970",
@"MintCream" : @"#F5FFFA",
@"MistyRose" : @"#FFE4E1",
@"Moccasin" : @"#FFE4B5",
@"NavajoWhite" : @"#FFDEAD",
@"Navy" : @"#000080",
@"OldLace" : @"#FDF5E6",
@"Olive" : @"#808000",
@"OliveDrab" : @"#6B8E23",
@"Orange" : @"#FFA500",
@"OrangeRed" : @"#FF4500",
@"Orchid" : @"#DA70D6",
@"PaleGoldenRod" : @"#EEE8AA",
@"PaleGreen" : @"#98FB98",
@"PaleTurquoise" : @"#AFEEEE",
@"PaleVioletRed" : @"#DB7093",
@"PapayaWhip" : @"#FFEFD5",
@"PeachPuff" : @"#FFDAB9",
@"Peru" : @"#CD853F",
@"Pink" : @"#FFC0CB",
@"Plum" : @"#DDA0DD",
@"PowderBlue" : @"#B0E0E6",
@"Purple" : @"#800080",
@"Red" : @"#FF0000",
@"RosyBrown" : @"#BC8F8F",
@"RoyalBlue" : @"#4169E1",
@"SaddleBrown" : @"#8B4513",
@"Salmon" : @"#FA8072",
@"SandyBrown" : @"#F4A460",
@"SeaGreen" : @"#2E8B57",
@"SeaShell" : @"#FFF5EE",
@"Sienna" : @"#A0522D",
@"Silver" : @"#C0C0C0",
@"SkyBlue" : @"#87CEEB",
@"SlateBlue" : @"#6A5ACD",
@"SlateGray" : @"#708090",
@"SlateGrey" : @"#708090",
@"Snow" : @"#FFFAFA",
@"SpringGreen" : @"#00FF7F",
@"SteelBlue" : @"#4682B4",
@"Tan" : @"#D2B48C",
@"Teal" : @"#008080",
@"Thistle" : @"#D8BFD8",
@"Tomato" : @"#FF6347",
@"Turquoise" : @"#40E0D0",
@"Violet" : @"#EE82EE",
@"Wheat" : @"#F5DEB3",
@"White" : @"#FFFFFF",
@"WhiteSmoke" : @"#F5F5F5",
@"Yellow" : @"#FFFF00",
@"YellowGreen" : @"#9ACD32"
};
});
return namedColors;
}
================================================
FILE: Pod/Classes/Extend/FlexboxKit/FLEXBOXContainerView.h
================================================
//
// FLEXBOXContainerView.h
// FlexboxKit
//
// Created by Alex Usbergo on 10/05/15.
// Copyright (c) 2015 Alex Usbergo. All rights reserved.
//
#import
@interface FLEXBOXContainerView : UIView
@end
================================================
FILE: Pod/Classes/Extend/FlexboxKit/FLEXBOXContainerView.m
================================================
//
// FLEXBOXContainerView.m
// FlexboxKit
//
// Created by Alex Usbergo on 10/05/15.
// Copyright (c) 2015 Alex Usbergo. All rights reserved.
//
#import "FLEXBOXContainerView.h"
#import "UIView+FLEXBOX.h"
@implementation FLEXBOXContainerView
- (void)layoutSubviews
{
//default flexbox container attributes
self.flex = self.flex < FLT_EPSILON ? 1 : self.flex;
self.flexContainer = YES;
[super layoutSubviews];
[self flexLayoutSubviews];
}
@end
================================================
FILE: Pod/Classes/Extend/FlexboxKit/FLEXBOXNode.h
================================================
//
// FLEXBOXNode.h
// FlexboxKit
//
// Created by Alex Usbergo on 09/05/15.
// Copyright (c) 2015 Alex Usbergo. All rights reserved.
//
#import "Layout.h"
@import UIKit;
typedef NS_ENUM(NSInteger, FLEXBOXFlexDirection) {
FLEXBOXFlexDirectionColumn = CSS_FLEX_DIRECTION_COLUMN,
FLEXBOXFlexDirectionRow = CSS_FLEX_DIRECTION_ROW,
FLEXBOXFlexDirectionRowReverse = CSS_FLEX_DIRECTION_ROW_REVERSE,
FLEXBOXFlexDirectionColumnReverse = CSS_FLEX_DIRECTION_COLUMN_REVERSE
};
typedef NS_ENUM(NSInteger, FLEXBOXContentDirection) {
FLEXBOXContentDirectionInherit = CSS_DIRECTION_INHERIT,
FLEXBOXContentDirectionLeftToRight = CSS_DIRECTION_LTR,
FLEXBOXContentDirectionRightToLeft = CSS_DIRECTION_RTL
};
typedef NS_ENUM(NSInteger, FLEXBOXJustification) {
FLEXBOXJustificationFlexStart = CSS_JUSTIFY_FLEX_START,
FLEXBOXJustificationCenter = CSS_JUSTIFY_CENTER,
FLEXBOXJustificationFlexEnd = CSS_JUSTIFY_FLEX_END,
FLEXBOXJustificationSpaceBetween = CSS_JUSTIFY_SPACE_BETWEEN,
FLEXBOXJustificationSpaceAround = CSS_JUSTIFY_SPACE_AROUND
};
typedef NS_ENUM(NSInteger, FLEXBOXAlignment) {
FLEXBOXAlignmentAuto = CSS_ALIGN_AUTO,
FLEXBOXAlignmentFlexStart = CSS_ALIGN_FLEX_START,
FLEXBOXAlignmentCenter = CSS_ALIGN_CENTER,
FLEXBOXAlignmentFlexEnd = CSS_ALIGN_FLEX_END,
FLEXBOXAlignmentStretch = CSS_ALIGN_STRETCH
};
extern const CGFloat FLEXBOXUndefinedDimension;
@interface FLEXBOXNode : NSObject
@property (nonatomic, readonly, assign) css_node_t *node;
@property (nonatomic, readonly, assign) CGRect frame;
@property (nonatomic, copy) CGSize (^measureBlock)(CGFloat width);
@property (nonatomic, copy) FLEXBOXNode *(^childrenAtIndexBlock)(NSUInteger i);
@property (nonatomic, copy) NSUInteger (^childrenCountBlock)(void);
/// Compute the layout for the node constrained to the width passed as argument
/// @param maximumWidth The maximum width or FLEXBOXUndefinedDimension
- (void)layoutConstrainedToMaximumWidth:(CGFloat)maximumWidth;
// Style
@property (nonatomic, assign) CGSize dimensions;
@property (nonatomic, assign) CGSize minDimensions;
@property (nonatomic, assign) CGSize maxDimensions;
@property (nonatomic, assign) FLEXBOXFlexDirection flexDirection;
@property (nonatomic, assign) UIEdgeInsets margin;
@property (nonatomic, assign) UIEdgeInsets padding;
@property (nonatomic, assign) BOOL flexWrap;
@property (nonatomic, assign) FLEXBOXJustification justifyContent;
@property (nonatomic, assign) FLEXBOXAlignment alignSelf;
@property (nonatomic, assign) FLEXBOXAlignment alignItems;
@property (nonatomic, assign) CGFloat flex;
@property (nonatomic, assign) FLEXBOXContentDirection contentDirection;
@end
================================================
FILE: Pod/Classes/Extend/FlexboxKit/FLEXBOXNode.m
================================================
//
// FLEXBOXNode.m
// FlexboxKit
//
// Created by Alex Usbergo on 09/05/15.
// Copyright (c) 2015 Alex Usbergo. All rights reserved.
//
#import "FLEXBOXNode.h"
const CGFloat FLEXBOXUndefinedDimension = CSS_UNDEFINED;
static bool FLEXBOX_alwaysDirty(void *context)
{
return YES;
}
static css_node_t *FLEXBOX_getChild(void *context, int i)
{
FLEXBOXNode *_self = (__bridge FLEXBOXNode*)context;
FLEXBOXNode *child = _self.childrenAtIndexBlock(i);
return child.node;
}
static css_dim_t FLEXBOX_measureNode(void *context, float width)
{
FLEXBOXNode *_self = (__bridge FLEXBOXNode*)context;
CGSize size = _self.measureBlock(width);
return (css_dim_t){ size.width, size.height };
}
@implementation FLEXBOXNode
#pragma mark - Lifecycle
- (instancetype)init
{
if (self = [super init]) {
//initialise the css_node_t
_node = new_css_node();
_node->context = (__bridge void *)self;
_node->is_dirty = FLEXBOX_alwaysDirty;
_node->measure = FLEXBOX_measureNode;
_node->get_child = FLEXBOX_getChild;
_maxDimensions = CGSizeZero;
_minDimensions = CGSizeZero;
//defaults
self.flexDirection = FLEXBOXFlexDirectionColumn;
self.flexWrap = NO;
self.alignItems = FLEXBOXAlignmentStretch;
self.alignSelf = FLEXBOXAlignmentAuto;
self.margin = UIEdgeInsetsZero;
self.padding = UIEdgeInsetsZero;
self.justifyContent = FLEXBOXJustificationFlexStart;
self.flex = 0;
self.contentDirection = FLEXBOXContentDirectionInherit;
}
return self;
}
- (void)dealloc
{
free_css_node(_node);
}
#pragma mark - Layout and Internals
- (void)prepareForLayout
{
if (self.childrenAtIndexBlock == nil)
return;
NSAssert(self.childrenCountBlock, nil);
NSUInteger count = self.childrenCountBlock();
// prepares the nodes for the layout recursively
for (NSInteger i = 0; i < count; i++) {
FLEXBOXNode *node = self.childrenAtIndexBlock(i);
[node prepareForLayout];
}
// Apparently we need to reset these before laying out, otherwise the layout
// has some weird additive effect.
self.node->layout.position[CSS_LEFT] = 0;
self.node->layout.position[CSS_TOP] = 0;
self.node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
self.node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
}
- (void)layoutConstrainedToMaximumWidth:(CGFloat)maximumWidth
{
_node->children_count = (int)self.childrenCountBlock();
maximumWidth = fabs(maximumWidth - FLT_MAX) < FLT_EPSILON ? FLEXBOXUndefinedDimension : maximumWidth;
[self prepareForLayout];
layoutNode(_node, maximumWidth, _node->style.direction);
}
- (CGRect)frame
{
return (CGRect) {
.origin.x = self.node->layout.position[CSS_LEFT],
.origin.y = self.node->layout.position[CSS_TOP],
.size.width = self.node->layout.dimensions[CSS_WIDTH],
.size.height = self.node->layout.dimensions[CSS_HEIGHT]
};
}
#pragma mark - Style
- (void)setDimensions:(CGSize)size
{
_dimensions = size;
_node->style.dimensions[CSS_WIDTH] = size.width;
_node->style.dimensions[CSS_HEIGHT] = size.height;
}
- (void)setMinDimensions:(CGSize)size
{
_minDimensions = size;
// _node->style.minDimensions[CSS_WIDTH] = size.width;
// _node->style.minDimensions[CSS_HEIGHT] = size.height;
}
- (void)setMaxDimensions:(CGSize)size
{
_maxDimensions = size;
// _node->style.maxDimensions[CSS_WIDTH] = size.width;
// _node->style.maxDimensions[CSS_HEIGHT] = size.height;
}
- (void)setFlexDirection:(FLEXBOXFlexDirection)flexDirection
{
_flexDirection = flexDirection;
_node->style.flex_direction = (int)flexDirection;
}
- (void)setMargin:(UIEdgeInsets)margin
{
_margin = margin;
_node->style.margin[CSS_LEFT] = margin.left;
_node->style.margin[CSS_TOP] = margin.top;
_node->style.margin[CSS_RIGHT] = margin.right;
_node->style.margin[CSS_BOTTOM] = margin.bottom;
}
- (void)setPadding:(UIEdgeInsets)padding
{
_padding = padding;
_node->style.padding[CSS_LEFT] = padding.left;
_node->style.padding[CSS_TOP] = padding.top;
_node->style.padding[CSS_RIGHT] = padding.right;
_node->style.padding[CSS_BOTTOM] = padding.bottom;
}
- (void)setFlex:(CGFloat)flex
{
_flex = flex;
_node->style.flex = flex;
}
- (void)setFlexWrap:(BOOL)flexWrap
{
_flexWrap = flexWrap;
_node->style.flex_wrap = flexWrap;
}
- (void)setJustifyContent:(FLEXBOXJustification)justifyContent
{
_justifyContent = justifyContent;
_node->style.justify_content = (int)justifyContent;
}
- (void)setAlignItems:(FLEXBOXAlignment)alignItems
{
_alignItems = alignItems;
_node->style.align_items = (int)alignItems;
}
- (void)setAlignSelf:(FLEXBOXAlignment)alignSelf
{
_alignSelf = alignSelf;
_node->style.align_self = (int)alignSelf;
}
- (void)setContentDirection:(FLEXBOXContentDirection)contentDirection
{
_contentDirection = contentDirection;
_node->style.direction = (int)contentDirection;
}
@end
================================================
FILE: Pod/Classes/Extend/FlexboxKit/FlexboxKit.h
================================================
//
// FlexboxKit.h
// FlexboxKit
//
// Created by Alex Usbergo on 09/05/15.
// Copyright (c) 2015 Alex Usbergo. All rights reserved.
//
#import
#import "FLEXBOXNode.h"
#import "UIView+FLEXBOX.h"
#import "FLEXBOXContainerView.h"
//! Project version number for FlexboxKit.
FOUNDATION_EXPORT double FlexboxKitVersionNumber;
//! Project version string for FlexboxKit.
FOUNDATION_EXPORT const unsigned char FlexboxKitVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import
================================================
FILE: Pod/Classes/Extend/FlexboxKit/Layout.c
================================================
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#include
#include
#include
#include
#include "Layout.h"
#ifdef _MSC_VER
#include
#define isnan _isnan
/* define fmaxf if < VC12 */
#if _MSC_VER < 1800
__forceinline const float fmaxf(const float a, const float b) {
return (a > b) ? a : b;
}
#endif
#endif
bool isUndefined(float value) {
return isnan(value);
}
static bool eq(float a, float b) {
if (isUndefined(a)) {
return isUndefined(b);
}
return fabs(a - b) < 0.0001;
}
void init_css_node(css_node_t *node) {
node->style.align_items = CSS_ALIGN_STRETCH;
node->style.align_content = CSS_ALIGN_FLEX_START;
node->style.direction = CSS_DIRECTION_INHERIT;
node->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN;
// Some of the fields default to undefined and not 0
node->style.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
node->style.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
node->style.minDimensions[CSS_WIDTH] = CSS_UNDEFINED;
node->style.minDimensions[CSS_HEIGHT] = CSS_UNDEFINED;
node->style.maxDimensions[CSS_WIDTH] = CSS_UNDEFINED;
node->style.maxDimensions[CSS_HEIGHT] = CSS_UNDEFINED;
node->style.position[CSS_LEFT] = CSS_UNDEFINED;
node->style.position[CSS_TOP] = CSS_UNDEFINED;
node->style.position[CSS_RIGHT] = CSS_UNDEFINED;
node->style.position[CSS_BOTTOM] = CSS_UNDEFINED;
node->style.margin[CSS_START] = CSS_UNDEFINED;
node->style.margin[CSS_END] = CSS_UNDEFINED;
node->style.padding[CSS_START] = CSS_UNDEFINED;
node->style.padding[CSS_END] = CSS_UNDEFINED;
node->style.border[CSS_START] = CSS_UNDEFINED;
node->style.border[CSS_END] = CSS_UNDEFINED;
node->layout.dimensions[CSS_WIDTH] = CSS_UNDEFINED;
node->layout.dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
// Such that the comparison is always going to be false
node->layout.last_requested_dimensions[CSS_WIDTH] = -1;
node->layout.last_requested_dimensions[CSS_HEIGHT] = -1;
node->layout.last_parent_max_width = -1;
node->layout.last_direction = (css_direction_t)-1;
node->layout.should_update = true;
}
css_node_t *new_css_node() {
css_node_t *node = (css_node_t *)calloc(1, sizeof(*node));
init_css_node(node);
return node;
}
void free_css_node(css_node_t *node) {
free(node);
}
static void indent(int n) {
for (int i = 0; i < n; ++i) {
printf(" ");
}
}
static void print_number_0(const char *str, float number) {
if (!eq(number, 0)) {
printf("%s: %g, ", str, number);
}
}
static void print_number_nan(const char *str, float number) {
if (!isnan(number)) {
printf("%s: %g, ", str, number);
}
}
static bool four_equal(float four[4]) {
return
eq(four[0], four[1]) &&
eq(four[0], four[2]) &&
eq(four[0], four[3]);
}
static void print_css_node_rec(
css_node_t *node,
css_print_options_t options,
int level
) {
indent(level);
printf("{");
if (node->print) {
node->print(node->context);
}
if (options & CSS_PRINT_LAYOUT) {
printf("layout: {");
printf("width: %g, ", node->layout.dimensions[CSS_WIDTH]);
printf("height: %g, ", node->layout.dimensions[CSS_HEIGHT]);
printf("top: %g, ", node->layout.position[CSS_TOP]);
printf("left: %g", node->layout.position[CSS_LEFT]);
printf("}, ");
}
if (options & CSS_PRINT_STYLE) {
if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN) {
printf("flexDirection: 'column', ");
} else if (node->style.flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {
printf("flexDirection: 'columnReverse', ");
} else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW) {
printf("flexDirection: 'row', ");
} else if (node->style.flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) {
printf("flexDirection: 'rowReverse', ");
}
if (node->style.justify_content == CSS_JUSTIFY_CENTER) {
printf("justifyContent: 'center', ");
} else if (node->style.justify_content == CSS_JUSTIFY_FLEX_END) {
printf("justifyContent: 'flex-end', ");
} else if (node->style.justify_content == CSS_JUSTIFY_SPACE_AROUND) {
printf("justifyContent: 'space-around', ");
} else if (node->style.justify_content == CSS_JUSTIFY_SPACE_BETWEEN) {
printf("justifyContent: 'space-between', ");
}
if (node->style.align_items == CSS_ALIGN_CENTER) {
printf("alignItems: 'center', ");
} else if (node->style.align_items == CSS_ALIGN_FLEX_END) {
printf("alignItems: 'flex-end', ");
} else if (node->style.align_items == CSS_ALIGN_STRETCH) {
printf("alignItems: 'stretch', ");
}
if (node->style.align_content == CSS_ALIGN_CENTER) {
printf("alignContent: 'center', ");
} else if (node->style.align_content == CSS_ALIGN_FLEX_END) {
printf("alignContent: 'flex-end', ");
} else if (node->style.align_content == CSS_ALIGN_STRETCH) {
printf("alignContent: 'stretch', ");
}
if (node->style.align_self == CSS_ALIGN_FLEX_START) {
printf("alignSelf: 'flex-start', ");
} else if (node->style.align_self == CSS_ALIGN_CENTER) {
printf("alignSelf: 'center', ");
} else if (node->style.align_self == CSS_ALIGN_FLEX_END) {
printf("alignSelf: 'flex-end', ");
} else if (node->style.align_self == CSS_ALIGN_STRETCH) {
printf("alignSelf: 'stretch', ");
}
print_number_nan("flex", node->style.flex);
if (four_equal(node->style.margin)) {
print_number_0("margin", node->style.margin[CSS_LEFT]);
} else {
print_number_0("marginLeft", node->style.margin[CSS_LEFT]);
print_number_0("marginRight", node->style.margin[CSS_RIGHT]);
print_number_0("marginTop", node->style.margin[CSS_TOP]);
print_number_0("marginBottom", node->style.margin[CSS_BOTTOM]);
print_number_0("marginStart", node->style.margin[CSS_START]);
print_number_0("marginEnd", node->style.margin[CSS_END]);
}
if (four_equal(node->style.padding)) {
print_number_0("padding", node->style.margin[CSS_LEFT]);
} else {
print_number_0("paddingLeft", node->style.padding[CSS_LEFT]);
print_number_0("paddingRight", node->style.padding[CSS_RIGHT]);
print_number_0("paddingTop", node->style.padding[CSS_TOP]);
print_number_0("paddingBottom", node->style.padding[CSS_BOTTOM]);
print_number_0("paddingStart", node->style.padding[CSS_START]);
print_number_0("paddingEnd", node->style.padding[CSS_END]);
}
if (four_equal(node->style.border)) {
print_number_0("borderWidth", node->style.border[CSS_LEFT]);
} else {
print_number_0("borderLeftWidth", node->style.border[CSS_LEFT]);
print_number_0("borderRightWidth", node->style.border[CSS_RIGHT]);
print_number_0("borderTopWidth", node->style.border[CSS_TOP]);
print_number_0("borderBottomWidth", node->style.border[CSS_BOTTOM]);
print_number_0("borderStartWidth", node->style.border[CSS_START]);
print_number_0("borderEndWidth", node->style.border[CSS_END]);
}
print_number_nan("width", node->style.dimensions[CSS_WIDTH]);
print_number_nan("height", node->style.dimensions[CSS_HEIGHT]);
if (node->style.position_type == CSS_POSITION_ABSOLUTE) {
printf("position: 'absolute', ");
}
print_number_nan("left", node->style.position[CSS_LEFT]);
print_number_nan("right", node->style.position[CSS_RIGHT]);
print_number_nan("top", node->style.position[CSS_TOP]);
print_number_nan("bottom", node->style.position[CSS_BOTTOM]);
}
if (options & CSS_PRINT_CHILDREN && node->children_count > 0) {
printf("children: [\n");
for (int i = 0; i < node->children_count; ++i) {
print_css_node_rec(node->get_child(node->context, i), options, level + 1);
}
indent(level);
printf("]},\n");
} else {
printf("},\n");
}
}
void print_css_node(css_node_t *node, css_print_options_t options) {
print_css_node_rec(node, options, 0);
}
static css_position_t leading[4] = {
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
/* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM,
/* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT,
/* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT
};
static css_position_t trailing[4] = {
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_BOTTOM,
/* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_TOP,
/* CSS_FLEX_DIRECTION_ROW = */ CSS_RIGHT,
/* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_LEFT
};
static css_position_t pos[4] = {
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_TOP,
/* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_BOTTOM,
/* CSS_FLEX_DIRECTION_ROW = */ CSS_LEFT,
/* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_RIGHT
};
static css_dimension_t dim[4] = {
/* CSS_FLEX_DIRECTION_COLUMN = */ CSS_HEIGHT,
/* CSS_FLEX_DIRECTION_COLUMN_REVERSE = */ CSS_HEIGHT,
/* CSS_FLEX_DIRECTION_ROW = */ CSS_WIDTH,
/* CSS_FLEX_DIRECTION_ROW_REVERSE = */ CSS_WIDTH
};
static bool isRowDirection(css_flex_direction_t flex_direction) {
return flex_direction == CSS_FLEX_DIRECTION_ROW ||
flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE;
}
static bool isColumnDirection(css_flex_direction_t flex_direction) {
return flex_direction == CSS_FLEX_DIRECTION_COLUMN ||
flex_direction == CSS_FLEX_DIRECTION_COLUMN_REVERSE;
}
static float getLeadingMargin(css_node_t *node, css_flex_direction_t axis) {
if (isRowDirection(axis) && !isUndefined(node->style.margin[CSS_START])) {
return node->style.margin[CSS_START];
}
return node->style.margin[leading[axis]];
}
static float getTrailingMargin(css_node_t *node, css_flex_direction_t axis) {
if (isRowDirection(axis) && !isUndefined(node->style.margin[CSS_END])) {
return node->style.margin[CSS_END];
}
return node->style.margin[trailing[axis]];
}
static float getLeadingPadding(css_node_t *node, css_flex_direction_t axis) {
if (isRowDirection(axis) &&
!isUndefined(node->style.padding[CSS_START]) &&
node->style.padding[CSS_START] >= 0) {
return node->style.padding[CSS_START];
}
if (node->style.padding[leading[axis]] >= 0) {
return node->style.padding[leading[axis]];
}
return 0;
}
static float getTrailingPadding(css_node_t *node, css_flex_direction_t axis) {
if (isRowDirection(axis) &&
!isUndefined(node->style.padding[CSS_END]) &&
node->style.padding[CSS_END] >= 0) {
return node->style.padding[CSS_END];
}
if (node->style.padding[trailing[axis]] >= 0) {
return node->style.padding[trailing[axis]];
}
return 0;
}
static float getLeadingBorder(css_node_t *node, css_flex_direction_t axis) {
if (isRowDirection(axis) &&
!isUndefined(node->style.border[CSS_START]) &&
node->style.border[CSS_START] >= 0) {
return node->style.border[CSS_START];
}
if (node->style.border[leading[axis]] >= 0) {
return node->style.border[leading[axis]];
}
return 0;
}
static float getTrailingBorder(css_node_t *node, css_flex_direction_t axis) {
if (isRowDirection(axis) &&
!isUndefined(node->style.border[CSS_END]) &&
node->style.border[CSS_END] >= 0) {
return node->style.border[CSS_END];
}
if (node->style.border[trailing[axis]] >= 0) {
return node->style.border[trailing[axis]];
}
return 0;
}
static float getLeadingPaddingAndBorder(css_node_t *node, css_flex_direction_t axis) {
return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);
}
static float getTrailingPaddingAndBorder(css_node_t *node, css_flex_direction_t axis) {
return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);
}
static float getBorderAxis(css_node_t *node, css_flex_direction_t axis) {
return getLeadingBorder(node, axis) + getTrailingBorder(node, axis);
}
static float getMarginAxis(css_node_t *node, css_flex_direction_t axis) {
return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);
}
static float getPaddingAndBorderAxis(css_node_t *node, css_flex_direction_t axis) {
return getLeadingPaddingAndBorder(node, axis) + getTrailingPaddingAndBorder(node, axis);
}
static css_position_type_t getPositionType(css_node_t *node) {
return node->style.position_type;
}
static css_justify_t getJustifyContent(css_node_t *node) {
return node->style.justify_content;
}
static css_align_t getAlignContent(css_node_t *node) {
return node->style.align_content;
}
static css_align_t getAlignItem(css_node_t *node, css_node_t *child) {
if (child->style.align_self != CSS_ALIGN_AUTO) {
return child->style.align_self;
}
return node->style.align_items;
}
static css_direction_t resolveDirection(css_node_t *node, css_direction_t parentDirection) {
css_direction_t direction = node->style.direction;
if (direction == CSS_DIRECTION_INHERIT) {
direction = parentDirection > CSS_DIRECTION_INHERIT ? parentDirection : CSS_DIRECTION_LTR;
}
return direction;
}
static css_flex_direction_t getFlexDirection(css_node_t *node) {
return node->style.flex_direction;
}
static css_flex_direction_t resolveAxis(css_flex_direction_t flex_direction, css_direction_t direction) {
if (direction == CSS_DIRECTION_RTL) {
if (flex_direction == CSS_FLEX_DIRECTION_ROW) {
return CSS_FLEX_DIRECTION_ROW_REVERSE;
} else if (flex_direction == CSS_FLEX_DIRECTION_ROW_REVERSE) {
return CSS_FLEX_DIRECTION_ROW;
}
}
return flex_direction;
}
static css_flex_direction_t getCrossFlexDirection(css_flex_direction_t flex_direction, css_direction_t direction) {
if (isColumnDirection(flex_direction)) {
return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
} else {
return CSS_FLEX_DIRECTION_COLUMN;
}
}
static float getFlex(css_node_t *node) {
return node->style.flex;
}
static bool isFlex(css_node_t *node) {
return (
getPositionType(node) == CSS_POSITION_RELATIVE &&
getFlex(node) > 0
);
}
static bool isFlexWrap(css_node_t *node) {
return node->style.flex_wrap == CSS_WRAP;
}
static float getDimWithMargin(css_node_t *node, css_flex_direction_t axis) {
return node->layout.dimensions[dim[axis]] +
getLeadingMargin(node, axis) +
getTrailingMargin(node, axis);
}
static bool isDimDefined(css_node_t *node, css_flex_direction_t axis) {
float value = node->style.dimensions[dim[axis]];
return !isUndefined(value) && value > 0.0;
}
static bool isPosDefined(css_node_t *node, css_position_t position) {
return !isUndefined(node->style.position[position]);
}
static bool isMeasureDefined(css_node_t *node) {
return node->measure;
}
static float getPosition(css_node_t *node, css_position_t position) {
float result = node->style.position[position];
if (!isUndefined(result)) {
return result;
}
return 0;
}
static float boundAxis(css_node_t *node, css_flex_direction_t axis, float value) {
float min = CSS_UNDEFINED;
float max = CSS_UNDEFINED;
if (isColumnDirection(axis)) {
min = node->style.minDimensions[CSS_HEIGHT];
max = node->style.maxDimensions[CSS_HEIGHT];
} else if (isRowDirection(axis)) {
min = node->style.minDimensions[CSS_WIDTH];
max = node->style.maxDimensions[CSS_WIDTH];
}
float boundValue = value;
if (!isUndefined(max) && max >= 0.0 && boundValue > max) {
boundValue = max;
}
if (!isUndefined(min) && min >= 0.0 && boundValue < min) {
boundValue = min;
}
return boundValue;
}
// When the user specifically sets a value for width or height
static void setDimensionFromStyle(css_node_t *node, css_flex_direction_t axis) {
// The parent already computed us a width or height. We just skip it
if (!isUndefined(node->layout.dimensions[dim[axis]])) {
return;
}
// We only run if there's a width or height defined
if (!isDimDefined(node, axis)) {
return;
}
// The dimensions can never be smaller than the padding and border
node->layout.dimensions[dim[axis]] = fmaxf(
boundAxis(node, axis, node->style.dimensions[dim[axis]]),
getPaddingAndBorderAxis(node, axis)
);
}
static void setTrailingPosition(css_node_t *node, css_node_t *child, css_flex_direction_t axis) {
child->layout.position[trailing[axis]] = node->layout.dimensions[dim[axis]] -
child->layout.dimensions[dim[axis]] - child->layout.position[pos[axis]];
}
// If both left and right are defined, then use left. Otherwise return
// +left or -right depending on which is defined.
static float getRelativePosition(css_node_t *node, css_flex_direction_t axis) {
float lead = node->style.position[leading[axis]];
if (!isUndefined(lead)) {
return lead;
}
return -getPosition(node, trailing[axis]);
}
static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, css_direction_t parentDirection) {
/** START_GENERATED **/
css_direction_t direction = resolveDirection(node, parentDirection);
css_flex_direction_t mainAxis = resolveAxis(getFlexDirection(node), direction);
css_flex_direction_t crossAxis = getCrossFlexDirection(mainAxis, direction);
css_flex_direction_t resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);
// Handle width and height style attributes
setDimensionFromStyle(node, mainAxis);
setDimensionFromStyle(node, crossAxis);
// Set the resolved resolution in the node's layout
node->layout.direction = direction;
// The position is set by the parent, but we need to complete it with a
// delta composed of the margin and left/top/right/bottom
node->layout.position[leading[mainAxis]] += getLeadingMargin(node, mainAxis) +
getRelativePosition(node, mainAxis);
node->layout.position[trailing[mainAxis]] += getTrailingMargin(node, mainAxis) +
getRelativePosition(node, mainAxis);
node->layout.position[leading[crossAxis]] += getLeadingMargin(node, crossAxis) +
getRelativePosition(node, crossAxis);
node->layout.position[trailing[crossAxis]] += getTrailingMargin(node, crossAxis) +
getRelativePosition(node, crossAxis);
if (isMeasureDefined(node)) {
float width = CSS_UNDEFINED;
if (isDimDefined(node, resolvedRowAxis)) {
width = node->style.dimensions[CSS_WIDTH];
} else if (!isUndefined(node->layout.dimensions[dim[resolvedRowAxis]])) {
width = node->layout.dimensions[dim[resolvedRowAxis]];
} else {
width = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis);
}
width -= getPaddingAndBorderAxis(node, resolvedRowAxis);
// We only need to give a dimension for the text if we haven't got any
// for it computed yet. It can either be from the style attribute or because
// the element is flexible.
bool isRowUndefined = !isDimDefined(node, resolvedRowAxis) &&
isUndefined(node->layout.dimensions[dim[resolvedRowAxis]]);
bool isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&
isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]);
// Let's not measure the text if we already know both dimensions
if (isRowUndefined || isColumnUndefined) {
css_dim_t measureDim = node->measure(
node->context,
width
);
if (isRowUndefined) {
node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] +
getPaddingAndBorderAxis(node, resolvedRowAxis);
}
if (isColumnUndefined) {
node->layout.dimensions[CSS_HEIGHT] = measureDim.dimensions[CSS_HEIGHT] +
getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
}
}
if (node->children_count == 0) {
return;
}
}
int i;
int ii;
css_node_t* child;
css_flex_direction_t axis;
// Pre-fill some dimensions straight from the parent
for (i = 0; i < node->children_count; ++i) {
child = node->get_child(node->context, i);
// Pre-fill cross axis dimensions when the child is using stretch before
// we call the recursive layout pass
if (getAlignItem(node, child) == CSS_ALIGN_STRETCH &&
getPositionType(child) == CSS_POSITION_RELATIVE &&
!isUndefined(node->layout.dimensions[dim[crossAxis]]) &&
!isDimDefined(child, crossAxis)) {
child->layout.dimensions[dim[crossAxis]] = fmaxf(
boundAxis(child, crossAxis, node->layout.dimensions[dim[crossAxis]] -
getPaddingAndBorderAxis(node, crossAxis) -
getMarginAxis(child, crossAxis)),
// You never want to go smaller than padding
getPaddingAndBorderAxis(child, crossAxis)
);
} else if (getPositionType(child) == CSS_POSITION_ABSOLUTE) {
// Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both
// left and right or top and bottom).
for (ii = 0; ii < 2; ii++) {
axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
if (!isUndefined(node->layout.dimensions[dim[axis]]) &&
!isDimDefined(child, axis) &&
isPosDefined(child, leading[axis]) &&
isPosDefined(child, trailing[axis])) {
child->layout.dimensions[dim[axis]] = fmaxf(
boundAxis(child, axis, node->layout.dimensions[dim[axis]] -
getPaddingAndBorderAxis(node, axis) -
getMarginAxis(child, axis) -
getPosition(child, leading[axis]) -
getPosition(child, trailing[axis])),
// You never want to go smaller than padding
getPaddingAndBorderAxis(child, axis)
);
}
}
}
}
float definedMainDim = CSS_UNDEFINED;
if (!isUndefined(node->layout.dimensions[dim[mainAxis]])) {
definedMainDim = node->layout.dimensions[dim[mainAxis]] -
getPaddingAndBorderAxis(node, mainAxis);
}
// We want to execute the next two loops one per line with flex-wrap
int startLine = 0;
int endLine = 0;
// int nextOffset = 0;
int alreadyComputedNextLayout = 0;
// We aggregate the total dimensions of the container in those two variables
float linesCrossDim = 0;
float linesMainDim = 0;
int linesCount = 0;
while (endLine < node->children_count) {
// Layout non flexible children and count children by type
// mainContentDim is accumulation of the dimensions and margin of all the
// non flexible children. This will be used in order to either set the
// dimensions of the node if none already exist, or to compute the
// remaining space left for the flexible children.
float mainContentDim = 0;
// There are three kind of children, non flexible, flexible and absolute.
// We need to know how many there are in order to distribute the space.
int flexibleChildrenCount = 0;
float totalFlexible = 0;
int nonFlexibleChildrenCount = 0;
float maxWidth;
for (i = startLine; i < node->children_count; ++i) {
child = node->get_child(node->context, i);
float nextContentDim = 0;
// It only makes sense to consider a child flexible if we have a computed
// dimension for the node->
if (!isUndefined(node->layout.dimensions[dim[mainAxis]]) && isFlex(child)) {
flexibleChildrenCount++;
totalFlexible += getFlex(child);
// Even if we don't know its exact size yet, we already know the padding,
// border and margin. We'll use this partial information, which represents
// the smallest possible size for the child, to compute the remaining
// available space.
nextContentDim = getPaddingAndBorderAxis(child, mainAxis) +
getMarginAxis(child, mainAxis);
} else {
maxWidth = CSS_UNDEFINED;
if (!isRowDirection(mainAxis)) {
maxWidth = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis) -
getPaddingAndBorderAxis(node, resolvedRowAxis);
if (isDimDefined(node, resolvedRowAxis)) {
maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
getPaddingAndBorderAxis(node, resolvedRowAxis);
}
}
// This is the main recursive call. We layout non flexible children.
if (alreadyComputedNextLayout == 0) {
layoutNode(child, maxWidth, direction);
}
// Absolute positioned elements do not take part of the layout, so we
// don't use them to compute mainContentDim
if (getPositionType(child) == CSS_POSITION_RELATIVE) {
nonFlexibleChildrenCount++;
// At this point we know the final size and margin of the element.
nextContentDim = getDimWithMargin(child, mainAxis);
}
}
// The element we are about to add would make us go to the next line
if (isFlexWrap(node) &&
!isUndefined(node->layout.dimensions[dim[mainAxis]]) &&
mainContentDim + nextContentDim > definedMainDim &&
// If there's only one element, then it's bigger than the content
// and needs its own line
i != startLine) {
nonFlexibleChildrenCount--;
alreadyComputedNextLayout = 1;
break;
}
alreadyComputedNextLayout = 0;
mainContentDim += nextContentDim;
endLine = i + 1;
}
// Layout flexible children and allocate empty space
// In order to position the elements in the main axis, we have two
// controls. The space between the beginning and the first element
// and the space between each two elements.
float leadingMainDim = 0;
float betweenMainDim = 0;
// The remaining available space that needs to be allocated
float remainingMainDim = 0;
if (!isUndefined(node->layout.dimensions[dim[mainAxis]])) {
remainingMainDim = definedMainDim - mainContentDim;
} else {
remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;
}
// If there are flexible children in the mix, they are going to fill the
// remaining space
if (flexibleChildrenCount != 0) {
float flexibleMainDim = remainingMainDim / totalFlexible;
float baseMainDim;
float boundMainDim;
// Iterate over every child in the axis. If the flex share of remaining
// space doesn't meet min/max bounds, remove this child from flex
// calculations.
for (i = startLine; i < endLine; ++i) {
child = node->get_child(node->context, i);
if (isFlex(child)) {
baseMainDim = flexibleMainDim * getFlex(child) +
getPaddingAndBorderAxis(child, mainAxis);
boundMainDim = boundAxis(child, mainAxis, baseMainDim);
if (baseMainDim != boundMainDim) {
remainingMainDim -= boundMainDim;
totalFlexible -= getFlex(child);
}
}
}
flexibleMainDim = remainingMainDim / totalFlexible;
// The non flexible children can overflow the container, in this case
// we should just assume that there is no space available.
if (flexibleMainDim < 0) {
flexibleMainDim = 0;
}
// We iterate over the full array and only apply the action on flexible
// children. This is faster than actually allocating a new array that
// contains only flexible children.
for (i = startLine; i < endLine; ++i) {
child = node->get_child(node->context, i);
if (isFlex(child)) {
// At this point we know the final size of the element in the main
// dimension
child->layout.dimensions[dim[mainAxis]] = boundAxis(child, mainAxis,
flexibleMainDim * getFlex(child) + getPaddingAndBorderAxis(child, mainAxis)
);
maxWidth = CSS_UNDEFINED;
if (isDimDefined(node, resolvedRowAxis)) {
maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] -
getPaddingAndBorderAxis(node, resolvedRowAxis);
} else if (!isRowDirection(mainAxis)) {
maxWidth = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis) -
getPaddingAndBorderAxis(node, resolvedRowAxis);
}
// And we recursively call the layout algorithm for this child
layoutNode(child, maxWidth, direction);
}
}
// We use justifyContent to figure out how to allocate the remaining
// space available
} else {
css_justify_t justifyContent = getJustifyContent(node);
if (justifyContent == CSS_JUSTIFY_CENTER) {
leadingMainDim = remainingMainDim / 2;
} else if (justifyContent == CSS_JUSTIFY_FLEX_END) {
leadingMainDim = remainingMainDim;
} else if (justifyContent == CSS_JUSTIFY_SPACE_BETWEEN) {
remainingMainDim = fmaxf(remainingMainDim, 0);
if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 != 0) {
betweenMainDim = remainingMainDim /
(flexibleChildrenCount + nonFlexibleChildrenCount - 1);
} else {
betweenMainDim = 0;
}
} else if (justifyContent == CSS_JUSTIFY_SPACE_AROUND) {
// Space on the edges is half of the space between elements
betweenMainDim = remainingMainDim /
(flexibleChildrenCount + nonFlexibleChildrenCount);
leadingMainDim = betweenMainDim / 2;
}
}
// Position elements in the main axis and compute dimensions
// At this point, all the children have their dimensions set. We need to
// find their position. In order to do that, we accumulate data in
// variables that are also useful to compute the total dimensions of the
// container!
float crossDim = 0;
float mainDim = leadingMainDim +
getLeadingPaddingAndBorder(node, mainAxis);
for (i = startLine; i < endLine; ++i) {
child = node->get_child(node->context, i);
child->line_index = linesCount;
if (getPositionType(child) == CSS_POSITION_ABSOLUTE &&
isPosDefined(child, leading[mainAxis])) {
// In case the child is position absolute and has left/top being
// defined, we override the position to whatever the user said
// (and margin/border).
child->layout.position[pos[mainAxis]] = getPosition(child, leading[mainAxis]) +
getLeadingBorder(node, mainAxis) +
getLeadingMargin(child, mainAxis);
} else {
// If the child is position absolute (without top/left) or relative,
// we put it at the current accumulated offset.
child->layout.position[pos[mainAxis]] += mainDim;
// Define the trailing position accordingly.
if (!isUndefined(node->layout.dimensions[dim[mainAxis]])) {
setTrailingPosition(node, child, mainAxis);
}
}
// Now that we placed the element, we need to update the variables
// We only need to do that for relative elements. Absolute elements
// do not take part in that phase.
if (getPositionType(child) == CSS_POSITION_RELATIVE) {
// The main dimension is the sum of all the elements dimension plus
// the spacing.
mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
// The cross dimension is the max of the elements dimension since there
// can only be one element in that cross dimension.
crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));
}
}
float containerCrossAxis = node->layout.dimensions[dim[crossAxis]];
if (isUndefined(node->layout.dimensions[dim[crossAxis]])) {
containerCrossAxis = fmaxf(
// For the cross dim, we add both sides at the end because the value
// is aggregate via a max function. Intermediate negative values
// can mess this computation otherwise
boundAxis(node, crossAxis, crossDim + getPaddingAndBorderAxis(node, crossAxis)),
getPaddingAndBorderAxis(node, crossAxis)
);
}
// Position elements in the cross axis
for (i = startLine; i < endLine; ++i) {
child = node->get_child(node->context, i);
if (getPositionType(child) == CSS_POSITION_ABSOLUTE &&
isPosDefined(child, leading[crossAxis])) {
// In case the child is absolutely positionned and has a
// top/left/bottom/right being set, we override all the previously
// computed positions to set it correctly.
child->layout.position[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +
getLeadingBorder(node, crossAxis) +
getLeadingMargin(child, crossAxis);
} else {
float leadingCrossDim = getLeadingPaddingAndBorder(node, crossAxis);
// For a relative children, we're either using alignItems (parent) or
// alignSelf (child) in order to determine the position in the cross axis
if (getPositionType(child) == CSS_POSITION_RELATIVE) {
css_align_t alignItem = getAlignItem(node, child);
if (alignItem == CSS_ALIGN_STRETCH) {
// You can only stretch if the dimension has not already been set
// previously.
if (!isDimDefined(child, crossAxis)) {
child->layout.dimensions[dim[crossAxis]] = fmaxf(
boundAxis(child, crossAxis, containerCrossAxis -
getPaddingAndBorderAxis(node, crossAxis) -
getMarginAxis(child, crossAxis)),
// You never want to go smaller than padding
getPaddingAndBorderAxis(child, crossAxis)
);
}
} else if (alignItem != CSS_ALIGN_FLEX_START) {
// The remaining space between the parent dimensions+padding and child
// dimensions+margin.
float remainingCrossDim = containerCrossAxis -
getPaddingAndBorderAxis(node, crossAxis) -
getDimWithMargin(child, crossAxis);
if (alignItem == CSS_ALIGN_CENTER) {
leadingCrossDim += remainingCrossDim / 2;
} else { // CSS_ALIGN_FLEX_END
leadingCrossDim += remainingCrossDim;
}
}
}
// And we apply the position
child->layout.position[pos[crossAxis]] += linesCrossDim + leadingCrossDim;
// Define the trailing position accordingly.
if (!isUndefined(node->layout.dimensions[dim[crossAxis]])) {
setTrailingPosition(node, child, crossAxis);
}
}
}
linesCrossDim += crossDim;
linesMainDim = fmaxf(linesMainDim, mainDim);
linesCount += 1;
startLine = endLine;
}
//
//
// Note(prenaux): More than one line, we need to layout the crossAxis
// according to alignContent.
//
// Note that we could probably remove and handle the one line case
// here too, but for the moment this is safer since it won't interfere with
// previously working code.
//
// See specs:
// http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm
// section 9.4
//
if (linesCount > 1 &&
!isUndefined(node->layout.dimensions[dim[crossAxis]])) {
float nodeCrossAxisInnerSize = node->layout.dimensions[dim[crossAxis]] -
getPaddingAndBorderAxis(node, crossAxis);
float remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;
float crossDimLead = 0;
float currentLead = getLeadingPaddingAndBorder(node, crossAxis);
css_align_t alignContent = getAlignContent(node);
if (alignContent == CSS_ALIGN_FLEX_END) {
currentLead += remainingAlignContentDim;
} else if (alignContent == CSS_ALIGN_CENTER) {
currentLead += remainingAlignContentDim / 2;
} else if (alignContent == CSS_ALIGN_STRETCH) {
if (nodeCrossAxisInnerSize > linesCrossDim) {
crossDimLead = (remainingAlignContentDim / linesCount);
}
}
int endIndex = 0;
for (i = 0; i < linesCount; ++i) {
int startIndex = endIndex;
// compute the line's height and find the endIndex
float lineHeight = 0;
for (ii = startIndex; ii < node->children_count; ++ii) {
child = node->get_child(node->context, ii);
if (getPositionType(child) != CSS_POSITION_RELATIVE) {
continue;
}
if (child->line_index != i) {
break;
}
if (!isUndefined(child->layout.dimensions[dim[crossAxis]])) {
lineHeight = fmaxf(
lineHeight,
child->layout.dimensions[dim[crossAxis]] + getMarginAxis(child, crossAxis)
);
}
}
endIndex = ii;
lineHeight += crossDimLead;
for (ii = startIndex; ii < endIndex; ++ii) {
child = node->get_child(node->context, ii);
if (getPositionType(child) != CSS_POSITION_RELATIVE) {
continue;
}
css_align_t alignContentAlignItem = getAlignItem(node, child);
if (alignContentAlignItem == CSS_ALIGN_FLEX_START) {
child->layout.position[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
} else if (alignContentAlignItem == CSS_ALIGN_FLEX_END) {
child->layout.position[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child->layout.dimensions[dim[crossAxis]];
} else if (alignContentAlignItem == CSS_ALIGN_CENTER) {
float childHeight = child->layout.dimensions[dim[crossAxis]];
child->layout.position[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;
} else if (alignContentAlignItem == CSS_ALIGN_STRETCH) {
child->layout.position[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);
// TODO(prenaux): Correctly set the height of items with undefined
// (auto) crossAxis dimension.
}
}
currentLead += lineHeight;
}
}
bool needsMainTrailingPos = false;
bool needsCrossTrailingPos = false;
// If the user didn't specify a width or height, and it has not been set
// by the container, then we set it via the children.
if (isUndefined(node->layout.dimensions[dim[mainAxis]])) {
node->layout.dimensions[dim[mainAxis]] = fmaxf(
// We're missing the last padding at this point to get the final
// dimension
boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)),
// We can never assign a width smaller than the padding and borders
getPaddingAndBorderAxis(node, mainAxis)
);
needsMainTrailingPos = true;
}
if (isUndefined(node->layout.dimensions[dim[crossAxis]])) {
node->layout.dimensions[dim[crossAxis]] = fmaxf(
// For the cross dim, we add both sides at the end because the value
// is aggregate via a max function. Intermediate negative values
// can mess this computation otherwise
boundAxis(node, crossAxis, linesCrossDim + getPaddingAndBorderAxis(node, crossAxis)),
getPaddingAndBorderAxis(node, crossAxis)
);
needsCrossTrailingPos = true;
}
// Set trailing position if necessary
if (needsMainTrailingPos || needsCrossTrailingPos) {
for (i = 0; i < node->children_count; ++i) {
child = node->get_child(node->context, i);
if (needsMainTrailingPos) {
setTrailingPosition(node, child, mainAxis);
}
if (needsCrossTrailingPos) {
setTrailingPosition(node, child, crossAxis);
}
}
}
// Calculate dimensions for absolutely positioned elements
for (i = 0; i < node->children_count; ++i) {
child = node->get_child(node->context, i);
if (getPositionType(child) == CSS_POSITION_ABSOLUTE) {
// Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both
// left and right or top and bottom).
for (ii = 0; ii < 2; ii++) {
axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
if (!isUndefined(node->layout.dimensions[dim[axis]]) &&
!isDimDefined(child, axis) &&
isPosDefined(child, leading[axis]) &&
isPosDefined(child, trailing[axis])) {
child->layout.dimensions[dim[axis]] = fmaxf(
boundAxis(child, axis, node->layout.dimensions[dim[axis]] -
getBorderAxis(node, axis) -
getMarginAxis(child, axis) -
getPosition(child, leading[axis]) -
getPosition(child, trailing[axis])
),
// You never want to go smaller than padding
getPaddingAndBorderAxis(child, axis)
);
}
}
for (ii = 0; ii < 2; ii++) {
axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;
if (isPosDefined(child, trailing[axis]) &&
!isPosDefined(child, leading[axis])) {
child->layout.position[leading[axis]] =
node->layout.dimensions[dim[axis]] -
child->layout.dimensions[dim[axis]] -
getPosition(child, trailing[axis]);
}
}
}
}
/** END_GENERATED **/
}
void layoutNode(css_node_t *node, float parentMaxWidth, css_direction_t parentDirection) {
css_layout_t *layout = &node->layout;
css_direction_t direction = node->style.direction;
layout->should_update = true;
bool skipLayout =
!node->is_dirty(node->context) &&
eq(layout->last_requested_dimensions[CSS_WIDTH], layout->dimensions[CSS_WIDTH]) &&
eq(layout->last_requested_dimensions[CSS_HEIGHT], layout->dimensions[CSS_HEIGHT]) &&
eq(layout->last_parent_max_width, parentMaxWidth);
eq(layout->last_direction, direction);
if (skipLayout) {
layout->dimensions[CSS_WIDTH] = layout->last_dimensions[CSS_WIDTH];
layout->dimensions[CSS_HEIGHT] = layout->last_dimensions[CSS_HEIGHT];
layout->position[CSS_TOP] = layout->last_position[CSS_TOP];
layout->position[CSS_LEFT] = layout->last_position[CSS_LEFT];
} else {
layout->last_requested_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
layout->last_requested_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
layout->last_parent_max_width = parentMaxWidth;
layout->last_direction = direction;
layoutNodeImpl(node, parentMaxWidth, parentDirection);
layout->last_dimensions[CSS_WIDTH] = layout->dimensions[CSS_WIDTH];
layout->last_dimensions[CSS_HEIGHT] = layout->dimensions[CSS_HEIGHT];
layout->last_position[CSS_TOP] = layout->position[CSS_TOP];
layout->last_position[CSS_LEFT] = layout->position[CSS_LEFT];
}
}
================================================
FILE: Pod/Classes/Extend/FlexboxKit/Layout.h
================================================
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
#ifndef __LAYOUT_H
#define __LAYOUT_H
#include
#ifndef __cplusplus
#include
#endif
// Not defined in MSVC++
#ifndef NAN
static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
#define NAN (*(const float *)__nan)
#endif
#define CSS_UNDEFINED NAN
typedef enum {
CSS_DIRECTION_INHERIT = 0,
CSS_DIRECTION_LTR,
CSS_DIRECTION_RTL
} css_direction_t;
typedef enum {
CSS_FLEX_DIRECTION_COLUMN = 0,
CSS_FLEX_DIRECTION_COLUMN_REVERSE,
CSS_FLEX_DIRECTION_ROW,
CSS_FLEX_DIRECTION_ROW_REVERSE
} css_flex_direction_t;
typedef enum {
CSS_JUSTIFY_FLEX_START = 0,
CSS_JUSTIFY_CENTER,
CSS_JUSTIFY_FLEX_END,
CSS_JUSTIFY_SPACE_BETWEEN,
CSS_JUSTIFY_SPACE_AROUND
} css_justify_t;
// Note: auto is only a valid value for alignSelf. It is NOT a valid value for
// alignItems.
typedef enum {
CSS_ALIGN_AUTO = 0,
CSS_ALIGN_FLEX_START,
CSS_ALIGN_CENTER,
CSS_ALIGN_FLEX_END,
CSS_ALIGN_STRETCH
} css_align_t;
typedef enum {
CSS_POSITION_RELATIVE = 0,
CSS_POSITION_ABSOLUTE
} css_position_type_t;
typedef enum {
CSS_NOWRAP = 0,
CSS_WRAP
} css_wrap_type_t;
// Note: left and top are shared between position[2] and position[4], so
// they have to be before right and bottom.
typedef enum {
CSS_LEFT = 0,
CSS_TOP,
CSS_RIGHT,
CSS_BOTTOM,
CSS_START,
CSS_END,
CSS_POSITION_COUNT
} css_position_t;
typedef enum {
CSS_WIDTH = 0,
CSS_HEIGHT
} css_dimension_t;
typedef struct {
float position[4];
float dimensions[2];
css_direction_t direction;
// Instead of recomputing the entire layout every single time, we
// cache some information to break early when nothing changed
bool should_update;
float last_requested_dimensions[2];
float last_parent_max_width;
float last_dimensions[2];
float last_position[2];
css_direction_t last_direction;
} css_layout_t;
typedef struct {
float dimensions[2];
} css_dim_t;
typedef struct {
css_direction_t direction;
css_flex_direction_t flex_direction;
css_justify_t justify_content;
css_align_t align_content;
css_align_t align_items;
css_align_t align_self;
css_position_type_t position_type;
css_wrap_type_t flex_wrap;
float flex;
float margin[6];
float position[4];
/**
* You should skip all the rules that contain negative values for the
* following attributes. For example:
* {padding: 10, paddingLeft: -5}
* should output:
* {left: 10 ...}
* the following two are incorrect:
* {left: -5 ...}
* {left: 0 ...}
*/
float padding[6];
float border[6];
float dimensions[2];
float minDimensions[2];
float maxDimensions[2];
} css_style_t;
typedef struct css_node {
css_style_t style;
css_layout_t layout;
int children_count;
int line_index;
css_dim_t (*measure)(void *context, float width);
void (*print)(void *context);
struct css_node* (*get_child)(void *context, int i);
bool (*is_dirty)(void *context);
void *context;
} css_node_t;
// Lifecycle of nodes and children
css_node_t *new_css_node(void);
void init_css_node(css_node_t *node);
void free_css_node(css_node_t *node);
// Print utilities
typedef enum {
CSS_PRINT_LAYOUT = 1,
CSS_PRINT_STYLE = 2,
CSS_PRINT_CHILDREN = 4,
} css_print_options_t;
void print_css_node(css_node_t *node, css_print_options_t options);
// Function that computes the layout!
void layoutNode(css_node_t *node, float maxWidth, css_direction_t parentDirection);
bool isUndefined(float value);
#endif
================================================
FILE: Pod/Classes/Extend/FlexboxKit/UIView+FLEXBOX.h
================================================
//
// UIView+FLEXBOX.h
// FlexboxKit
//
// Created by Alex Usbergo on 09/05/15.
// Copyright (c) 2015 Alex Usbergo. All rights reserved.
//
@import UIKit;
#import "FLEXBOXNode.h"
@interface UIView (FLEXBOX)
// Properties
/// YES if this view contains subviews that you wish to layout using the flexbox engine
/// @note You don't need to set this if your view is a FLEXBOXContainerView
@property (nonatomic, assign) BOOL flexContainer;
/// Set this if you wish to have a fixed size for this element
@property (nonatomic, assign) CGSize flexFixedSize;
/// The minumum size for this element
@property (nonatomic, assign) CGSize flexMinimumSize;
/// The maximum size for this element
@property (nonatomic, assign) CGSize flexMaximumSize;
/// It establishes the main-axis, thus defining the direction flex items are placed in the flex container.
/// - row: same as text direction (@see FLEXBOXFlexDirectionColumn)
/// - column (default): same as row but top to bottom (@see FLEXBOXFlexDirectionRow)
/// - row-reverse: (@see FLEXBOXFlexDirectionRowReverse)
/// - column-reverse: (@see FLEXBOXFlexDirectionColumnReverse)
@property (nonatomic, assign) FLEXBOXFlexDirection flexDirection;
/// The margins for this flex item (default is 0)
@property (nonatomic, assign) UIEdgeInsets flexMargin;
/// The padding for this flex item (default is 0)
@property (nonatomic, assign) UIEdgeInsets flexPadding;
/// Make the flexible items wrap if necesarry:
/// - wrap YES
/// - nowrap (default) NO
@property (nonatomic, assign) BOOL flexWrap;
/// It defines the alignment along the main axis. It helps distribute extra free
/// space leftover when either all the flex items on a line are inflexible, or are
/// flexible but have reached their maximum size. It also exerts some control over
/// the alignment of items when they overflow the line.
/// - flex-start (default): items are packed toward the start line (@see FLEXBOXJustificationFlexStart)
/// - flex-end: items are packed toward to end line (@see FLEXBOXJustificationFlexEnd)
/// - center: items are centered along the line (@see FLEXBOXJustificationCenter)
/// - space-between: items are evenly distributed in the line; first item is on the start line, last item on the end line (@see FLEXBOXJustificationSpaceBetween)
/// - space-around: items are evenly distributed in the line with equal space around them (@see FLEXBOXJustificationSpaceAround)
@property (nonatomic, assign) FLEXBOXJustification flexJustifyContent;
/// Center the alignments for one of the items inside a flexible element
/// - auto (default): The element inherits its parent container's align-items property, or "stretch" if it has no parent container (@see FLEXBOXAlignmentAuto)
/// - stretch: The element is positioned to fit the conatiner (@see FLEXBOXAlignmentStretch)
/// - center: The element is positioned at the center of the container (@see FLEXBOXAlignmentCenter)
/// - flex-start: The element is are positioned at the beginning of the container (@see FLEXBOXAlignmentFlexStart)
/// - flex-end: The element is positioned at the end of the container (@see FLEXBOXAlignmentFlexEnd)
@property (nonatomic, assign) FLEXBOXAlignment flexAlignSelf;
/// Center the alignments for all the items of the flexible element:
/// - stretch (default): The element is positioned to fit the conatiner (@see FLEXBOXAlignmentStretch)
/// - center: The element is positioned at the center of the container (@see FLEXBOXAlignmentCenter)
/// - flex-start: The element is are positioned at the beginning of the container (@see FLEXBOXAlignmentFlexStart)
/// - flex-end: The element is positioned at the end of the container (@see FLEXBOXAlignmentFlexEnd)
@property (nonatomic, assign) FLEXBOXAlignment flexAlignItems;
/// The flex property specifies the initial length of a flexible item.
/// A value between 0 and 1 (a ratio e.g. 1/2, 2/3)
@property (nonatomic, assign) CGFloat flex;
/// The node content directon (default is inherit)
@property (nonatomic, assign) FLEXBOXContentDirection flexContentDirection;
// Methods
/// Entry point for defining the size for this flex item
/// @note By default it calls -[UIView sizeThatFits:]
- (CGSize)flexComputeSize:(CGSize)bounds;
/// Call this method in -[UIView layoutSubviews] if you want the flexbox
/// engine to compute the layout
- (void)flexLayoutSubviews;
/// Define this block if you want to specify some custom logic instead of
/// calling -[UIView sizeThatFits:] in -[UIView flexComputeSize:]
@property (nonatomic, copy) CGSize (^flexSizeThatFitsBlock)(CGSize size);
@end
================================================
FILE: Pod/Classes/Extend/FlexboxKit/UIView+FLEXBOX.m
================================================
//
// UIView+FLEXBOX.m
// FlexboxKit
//
// Created by Alex Usbergo on 09/05/15.
// Copyright (c) 2015 Alex Usbergo. All rights reserved.
//
#import "UIView+FLEXBOX.h"
#import "FLEXBOXContainerView.h"
#import
const void *FLEXBOXContainerKey;
const void *FLEXBOXNodeKey;
const void *FLEXBOXOffsetNodeKey;
const void *FLEXBOXOffsetKey;
const void *FLEXBOXSizeKey;
const void *FLEXBOXSizeThatFitsBlock;
@interface UIView (_FLEXBOX)
/// The associated flexbox node
@property (nonatomic, strong) FLEXBOXNode *flexNode;
@property (nonatomic, readonly, getter=isFlexOffsetNodeDefined) BOOL flexNodeDefined;
@end
@implementation UIView (FLEXBOX)
- (FLEXBOXNode*)flexNode
{
FLEXBOXNode *node = objc_getAssociatedObject(self, &FLEXBOXNodeKey);
if (node == nil) {
node = [[FLEXBOXNode alloc] init];
self.flexNode = node;
__weak __typeof(self) weakSelf = self;
self.flexNode.childrenAtIndexBlock = ^FLEXBOXNode*(NSUInteger i) {
return [weakSelf.subviews[i] flexNode];
};
self.flexNode.childrenCountBlock = ^NSUInteger(void) {
return weakSelf.subviews.count;
};
self.flexNode.measureBlock = ^CGSize(CGFloat width) {
return [weakSelf flexComputeSize:(CGSize){width, NAN}];
};
}
return node;
}
- (void)setFlexNode:(FLEXBOXNode*)flexNode
{
objc_setAssociatedObject(self, &FLEXBOXNodeKey, flexNode, OBJC_ASSOCIATION_RETAIN);
}
- (BOOL)flexContainer
{
return [objc_getAssociatedObject(self, &FLEXBOXContainerKey) boolValue];
}
- (void)setFlexContainer:(BOOL)flexContainer
{
objc_setAssociatedObject(self, &FLEXBOXContainerKey, @(flexContainer), OBJC_ASSOCIATION_RETAIN);
self.flex = flexContainer ? 1 : 0;
}
- (CGSize)flexFixedSize
{
NSValue *value = objc_getAssociatedObject(self, &FLEXBOXSizeKey);
if (value != nil) {
return [value CGSizeValue];
} else {
return CGSizeZero;
}
}
- (void)setFlexFixedSize:(CGSize)flexFixedSize
{
return objc_setAssociatedObject(self, &FLEXBOXSizeKey, [NSValue valueWithCGSize:flexFixedSize], OBJC_ASSOCIATION_RETAIN);
}
- (void)setFlexSizeThatFitsBlock:(CGSize (^)(CGSize))sizeThatFitsBlock
{
objc_setAssociatedObject(self, &FLEXBOXSizeThatFitsBlock, [sizeThatFitsBlock copy], OBJC_ASSOCIATION_COPY);
}
- (CGSize (^)(CGSize))flexSizeThatFitsBlock
{
return objc_getAssociatedObject(self, &FLEXBOXSizeThatFitsBlock);
}
- (CGSize)flexComputeSize:(CGSize)bounds
{
if (!CGSizeEqualToSize(self.flexFixedSize, CGSizeZero))
return self.flexFixedSize;
bounds.height = isnan(bounds.height) ? FLT_MAX : bounds.height;
bounds.width = isnan(bounds.width) ? FLT_MAX : bounds.width;
CGSize size = CGSizeZero;
if (self.flexSizeThatFitsBlock != nil) {
size = self.flexSizeThatFitsBlock(bounds);
} else {
size = [self sizeThatFits:bounds];
}
CGSize max = self.flexMaximumSize;
if (!CGSizeEqualToSize(max, CGSizeZero) || !CGSizeEqualToSize(max, (CGSize){FLT_MAX, FLT_MAX})) {
size.height = !isnan(max.height) && fabs(max.height) > FLT_EPSILON && size.height > max.height ? max.height : size.height;
size.width = !isnan(max.width) && fabs(max.width) > FLT_EPSILON && size.width > max.width ? max.width : size.width;
}
CGSize min = self.flexMinimumSize;
if (!CGSizeEqualToSize(min, CGSizeZero) || !CGSizeEqualToSize(max, (CGSize){FLT_MIN, FLT_MIN})) {
size.height = !isnan(min.height) && fabs(min.height) > FLT_EPSILON && size.height < min.height ? min.height : size.height;
size.width = !isnan(min.width) && fabs(min.width) > FLT_EPSILON && size.width < min.width ? min.width : size.width;
}
return size;
}
- (void)flexLayoutSubviews
{
self.flexNode.dimensions = self.bounds.size;
[self _flexLayoutSubviewsFromView:self];
self.frame = (CGRect){self.frame.origin, self.flexNode.frame.size};
}
- (void)_flexLayoutSubviewsFromView:(UIView*)view
{
[view.flexNode layoutConstrainedToMaximumWidth:CGRectGetWidth(view.bounds)];
for (NSUInteger i = 0; i < view.subviews.count; i++) {
UIView *subview = view.subviews[i];
FLEXBOXNode *subnode = subview.flexNode;
subview.frame = CGRectIntegral(subnode.frame);
}
for (NSUInteger i = 0; i < view.subviews.count; i++) {
UIView *subview = view.subviews[i];
if (subview.flexContainer)
[self _flexLayoutSubviewsFromView:subview];
}
}
#pragma mark - Properties
- (FLEXBOXFlexDirection)flexDirection
{
return self.flexNode.flexDirection;
}
- (void)setFlexDirection:(FLEXBOXFlexDirection)flexDirection
{
self.flexNode.flexDirection = flexDirection;
}
- (UIEdgeInsets)flexMargin
{
return self.flexNode.margin;
}
- (void)setFlexMargin:(UIEdgeInsets)flexMargin
{
self.flexNode.margin = flexMargin;
}
- (UIEdgeInsets)flexPadding
{
return self.flexNode.padding;
}
- (void)setFlexPadding:(UIEdgeInsets)flexPadding
{
self.flexNode.padding = flexPadding;
}
- (BOOL)flexWrap
{
return self.flexNode.flexWrap;
}
- (void)setFlexWrap:(BOOL)flexWrap
{
self.flexNode.flexWrap = flexWrap;
}
- (FLEXBOXJustification)flexJustifyContent
{
return self.flexNode.justifyContent;
}
- (void)setFlexJustifyContent:(FLEXBOXJustification)flexJustifyContent
{
self.flexNode.justifyContent = flexJustifyContent;
}
- (FLEXBOXAlignment)flexAlignSelf
{
return self.flexNode.alignSelf;
}
- (void)setFlexAlignSelf:(FLEXBOXAlignment)flexAlignSelf
{
self.flexNode.alignSelf = flexAlignSelf;
}
- (FLEXBOXAlignment)flexAlignItems
{
return self.flexNode.alignItems;
}
- (void)setFlexAlignItems:(FLEXBOXAlignment)flexAlignItems
{
self.flexNode.alignItems = flexAlignItems;
}
- (CGFloat)flex
{
return self.flexNode.flex;
}
- (void)setFlex:(CGFloat)flex
{
self.flexNode.flex = flex;
}
- (CGSize)flexMinimumSize
{
return self.flexNode.minDimensions;
}
- (void)setFlexMinimumSize:(CGSize)flexMinimumSize
{
self.flexNode.minDimensions = flexMinimumSize;
}
- (CGSize)flexMaximumSize
{
return self.flexNode.maxDimensions;
}
- (void)setFlexMaximumSize:(CGSize)flexMaximumSize
{
self.flexNode.maxDimensions = flexMaximumSize;
}
- (FLEXBOXContentDirection)flexContentDirection
{
return self.flexNode.contentDirection;
}
- (void)setFlexContentDirection:(FLEXBOXContentDirection)flexContentDirection
{
self.flexNode.contentDirection = flexContentDirection;
}
@end
================================================
FILE: Pod/Classes/Extend/Pinyin/pinyin.h
================================================
/*
* pinyin.h
* Chinese Pinyin First Letter
*
* Created by George on 4/21/10.
* Copyright 2010 RED/SAFI. All rights reserved.
*
*/
#import
@interface HTFirstLetter : NSObject
+ (char)pinyinFirstLetter:(unsigned short )hanzi;
//获取汉字首字母,如果参数既不是汉字也不是英文字母,则返回 @“#”
+ (NSString *)firstLetter:(NSString *)chineseString;
//返回参数中所有汉字的首字母,遇到其他字符,则用 # 替换
+ (NSString *)firstLetters:(NSString *)chineseString;
@end
================================================
FILE: Pod/Classes/Extend/Pinyin/pinyin.m
================================================
/*
* pinyin.c
* Chinese Pinyin First Letter
*
* Created by George on 4/21/10.
* Copyright 2010 RED/SAFI. All rights reserved.
*
*/
#define HANZI_START 19968
#define HANZI_COUNT 20902
#import "pinyin.h"
static char firstLetterArray[HANZI_COUNT] =
"ydkqsxnwzssxjbymgcczqpssqbycdscdqldylybssjgyqzjjfgcclzznwdwzjljpfyynnjjtmynzwzhflzppqhgccyynmjqyxxgd"
"nnsnsjnjnsnnmlnrxyfsngnnnnqzggllyjlnyzssecykyyhqwjssggyxyqyjtwktjhychmnxjtlhjyqbyxdldwrrjnwysrldzjpc"
"bzjjbrcfslnczstzfxxchtrqggddlyccssymmrjcyqzpwwjjyfcrwfdfzqpyddwyxkyjawjffxjbcftzyhhycyswccyxsclcxxwz"
"cxnbgnnxbxlzsqsbsjpysazdhmdzbqbscwdzzyytzhbtsyyfzgntnxjywqnknphhlxgybfmjnbjhhgqtjcysxstkzglyckglysmz"
"xyalmeldccxgzyrjxjzlnjzcqkcnnjwhjczccqljststbnhbtyxceqxkkwjyflzqlyhjxspsfxlmpbysxxxytccnylllsjxfhjxp"
"jbtffyabyxbcczbzyclwlczggbtssmdtjcxpthyqtgjjxcjfzkjzjqnlzwlslhdzbwjncjzyzsqnycqynzcjjwybrtwpyftwexcs"
"kdzctbyhyzqyyjxzcfbzzmjyxxsdczottbzljwfckscsxfyrlrygmbdthjxsqjccsbxyytswfbjdztnbcnzlcyzzpsacyzzsqqcs"
"hzqydxlbpjllmqxqydzxsqjtzpxlcglqdcwzfhctdjjsfxjejjtlbgxsxjmyjjqpfzasyjnsydjxkjcdjsznbartcclnjqmwnqnc"
"lllkbdbzzsyhqcltwlccrshllzntylnewyzyxczxxgdkdmtcedejtsyyssdqdfmxdbjlkrwnqlybglxnlgtgxbqjdznyjsjyjcjm"
"rnymgrcjczgjmzmgxmmryxkjnymsgmzzymknfxmbdtgfbhcjhkylpfmdxlxjjsmsqgzsjlqdldgjycalcmzcsdjllnxdjffffjcn"
"fnnffpfkhkgdpqxktacjdhhzdddrrcfqyjkqccwjdxhwjlyllzgcfcqjsmlzpbjjblsbcjggdckkdezsqcckjgcgkdjtjllzycxk"
"lqccgjcltfpcqczgwbjdqyzjjbyjhsjddwgfsjgzkcjctllfspkjgqjhzzljplgjgjjthjjyjzccmlzlyqbgjwmljkxzdznjqsyz"
"mljlljkywxmkjlhskjhbmclyymkxjqlbmllkmdxxkwyxwslmlpsjqqjqxyqfjtjdxmxxllcrqbsyjbgwynnggbcnxpjtgpapfgdj"
"qbhbncfjyzjkjkhxqfgqckfhygkhdkllsdjqxpqyaybnqsxqnszswhbsxwhxwbzzxdmndjbsbkbbzklylxgwxjjwaqzmywsjqlsj"
"xxjqwjeqxnchetlzalyyyszzpnkyzcptlshtzcfycyxyljsdcjqagyslcllyyysslqqqnldxzsccscadycjysfsgbfrsszqsbxjp"
"sjysdrckgjlgtkzjzbdktcsyqpyhstcldjnhmymcgxyzhjdctmhltxzhylamoxyjcltyfbqqjpfbdfehthsqhzywwcncxcdwhowg"
"yjlegmdqcwgfjhcsntmydolbygnqwesqpwnmlrydzszzlyqpzgcwxhnxpyxshmdqjgztdppbfbhzhhjyfdzwkgkzbldnzsxhqeeg"
"zxylzmmzyjzgszxkhkhtxexxgylyapsthxdwhzydpxagkydxbhnhnkdnjnmyhylpmgecslnzhkxxlbzzlbmlsfbhhgsgyyggbhsc"
"yajtxglxtzmcwzydqdqmngdnllszhngjzwfyhqswscelqajynytlsxthaznkzzsdhlaxxtwwcjhqqtddwzbcchyqzflxpslzqgpz"
"sznglydqtbdlxntctajdkywnsyzljhhdzckryyzywmhychhhxhjkzwsxhdnxlyscqydpslyzwmypnkxyjlkchtyhaxqsyshxasmc"
"hkdscrsgjpwqsgzjlwwschsjhsqnhnsngndantbaalczmsstdqjcjktscjnxplggxhhgoxzcxpdmmhldgtybynjmxhmrzplxjzck"
"zxshflqxxcdhxwzpckczcdytcjyxqhlxdhypjqxnlsyydzozjnhhqezysjyayxkypdgxddnsppyzndhthrhxydpcjjhtcnnctlhb"
"ynyhmhzllnnxmylllmdcppxhmxdkycyrdltxjchhznxclcclylnzsxnjzzlnnnnwhyqsnjhxynttdkyjpychhyegkcwtwlgjrlgg"
"tgtygyhpyhylqyqgcwyqkpyyettttlhyylltyttsylnyzwgywgpydqqzzdqnnkcqnmjjzzbxtqfjkdffbtkhzkbxdjjkdjjtlbwf"
"zpptkqtztgpdwntpjyfalqmkgxbcclzfhzcllllanpnxtjklcclgyhdzfgyddgcyyfgydxkssendhykdndknnaxxhbpbyyhxccga"
"pfqyjjdmlxcsjzllpcnbsxgjyndybwjspcwjlzkzddtacsbkzdyzypjzqsjnkktknjdjgyepgtlnyqnacdntcyhblgdzhbbydmjr"
"egkzyheyybjmcdtafzjzhgcjnlghldwxjjkytcyksssmtwcttqzlpbszdtwcxgzagyktywxlnlcpbclloqmmzsslcmbjcsdzkydc"
"zjgqjdsmcytzqqlnzqzxssbpkdfqmddzzsddtdmfhtdycnaqjqkypbdjyyxtljhdrqxlmhkydhrnlklytwhllrllrcxylbnsrnzz"
"symqzzhhkyhxksmzsyzgcxfbnbsqlfzxxnnxkxwymsddyqnggqmmyhcdzttfgyyhgsbttybykjdnkyjbelhdypjqnfxfdnkzhqks"
"byjtzbxhfdsbdaswpawajldyjsfhblcnndnqjtjnchxfjsrfwhzfmdrfjyxwzpdjkzyjympcyznynxfbytfyfwygdbnzzzdnytxz"
"emmqbsqehxfznbmflzzsrsyqjgsxwzjsprytjsjgskjjgljjynzjjxhgjkymlpyyycxycgqzswhwlyrjlpxslcxmnsmwklcdnkny"
"npsjszhdzeptxmwywxyysywlxjqcqxzdclaeelmcpjpclwbxsqhfwrtfnjtnqjhjqdxhwlbyccfjlylkyynldxnhycstyywncjtx"
"ywtrmdrqnwqcmfjdxzmhmayxnwmyzqtxtlmrspwwjhanbxtgzypxyyrrclmpamgkqjszycymyjsnxtplnbappypylxmyzkynldgy"
"jzcchnlmzhhanqnbgwqtzmxxmllhgdzxnhxhrxycjmffxywcfsbssqlhnndycannmtcjcypnxnytycnnymnmsxndlylysljnlxys"
"sqmllyzlzjjjkyzzcsfbzxxmstbjgnxnchlsnmcjscyznfzlxbrnnnylmnrtgzqysatswryhyjzmgdhzgzdwybsscskxsyhytsxg"
"cqgxzzbhyxjscrhmkkbsczjyjymkqhzjfnbhmqhysnjnzybknqmcjgqhwlsnzswxkhljhyybqcbfcdsxdldspfzfskjjzwzxsddx"
"jseeegjscssygclxxnwwyllymwwwgydkzjggggggsycknjwnjpcxbjjtqtjwdsspjxcxnzxnmelptfsxtllxcljxjjljsxctnswx"
"lennlyqrwhsycsqnybyaywjejqfwqcqqcjqgxaldbzzyjgkgxbltqyfxjltpydkyqhpmatlcndnkxmtxynhklefxdllegqtymsaw"
"hzmljtkynxlyjzljeeyybqqffnlyxhdsctgjhxywlkllxqkcctnhjlqmkkzgcyygllljdcgydhzwypysjbzjdzgyzzhywyfqdtyz"
"szyezklymgjjhtsmqwyzljyywzcsrkqyqltdxwcdrjalwsqzwbdcqyncjnnszjlncdcdtlzzzacqqzzddxyblxcbqjylzllljddz"
"jgyqyjzyxnyyyexjxksdaznyrdlzyyynjlslldyxjcykywnqcclddnyyynycgczhjxcclgzqjgnwnncqqjysbzzxyjxjnxjfzbsb"
"dsfnsfpzxhdwztdmpptflzzbzdmyypqjrsdzsqzsqxbdgcpzswdwcsqzgmdhzxmwwfybpngphdmjthzsmmbgzmbzjcfzhfcbbnmq"
"dfmbcmcjxlgpnjbbxgyhyyjgptzgzmqbqdcgybjxlwnkydpdymgcftpfxyztzxdzxtgkptybbclbjaskytssqyymscxfjhhlslls"
"jpqjjqaklyldlycctsxmcwfgngbqxllllnyxtyltyxytdpjhnhgnkbyqnfjyyzbyyessessgdyhfhwtcqbsdzjtfdmxhcnjzymqw"
"srxjdzjqbdqbbsdjgnfbknbxdkqhmkwjjjgdllthzhhyyyyhhsxztyyyccbdbpypzyccztjpzywcbdlfwzcwjdxxhyhlhwczxjtc"
"nlcdpxnqczczlyxjjcjbhfxwpywxzpcdzzbdccjwjhmlxbqxxbylrddgjrrctttgqdczwmxfytmmzcwjwxyywzzkybzcccttqnhx"
"nwxxkhkfhtswoccjybcmpzzykbnnzpbthhjdlszddytyfjpxyngfxbyqxzbhxcpxxtnzdnnycnxsxlhkmzxlthdhkghxxsshqyhh"
"cjyxglhzxcxnhekdtgqxqypkdhentykcnymyyjmkqyyyjxzlthhqtbyqhxbmyhsqckwwyllhcyylnneqxqwmcfbdccmljggxdqkt"
"lxkknqcdgcjwyjjlyhhqyttnwchhxcxwherzjydjccdbqcdgdnyxzdhcqrxcbhztqcbxwgqwyybxhmbymykdyecmqkyaqyngyzsl"
"fnkkqgyssqyshngjctxkzycssbkyxhyylstycxqthysmnscpmmgcccccmnztasmgqzjhklosjylswtmqzyqkdzljqqyplzycztcq"
"qpbbcjzclpkhqcyyxxdtdddsjcxffllchqxmjlwcjcxtspycxndtjshjwhdqqqckxyamylsjhmlalygxcyydmamdqmlmcznnyybz"
"xkyflmcncmlhxrcjjhsylnmtjggzgywjxsrxcwjgjqhqzdqjdcjjskjkgdzcgjjyjylxzxxcdqhhheslmhlfsbdjsyyshfyssczq"
"lpbdrfnztzdkykhsccgkwtqzckmsynbcrxqbjyfaxpzzedzcjykbcjwhyjbqzzywnyszptdkzpfpbaztklqnhbbzptpptyzzybhn"
"ydcpzmmcycqmcjfzzdcmnlfpbplngqjtbttajzpzbbdnjkljqylnbzqhksjznggqstzkcxchpzsnbcgzkddzqanzgjkdrtlzldwj"
"njzlywtxndjzjhxnatncbgtzcsskmljpjytsnwxcfjwjjtkhtzplbhsnjssyjbhbjyzlstlsbjhdnwqpslmmfbjdwajyzccjtbnn"
"nzwxxcdslqgdsdpdzgjtqqpsqlyyjzlgyhsdlctcbjtktyczjtqkbsjlgnnzdncsgpynjzjjyyknhrpwszxmtncszzyshbyhyzax"
"ywkcjtllckjjtjhgcssxyqyczbynnlwqcglzgjgqyqcczssbcrbcskydznxjsqgxssjmecnstjtpbdlthzwxqwqczexnqczgwesg"
"ssbybstscslccgbfsdqnzlccglllzghzcthcnmjgyzazcmsksstzmmzckbjygqljyjppldxrkzyxccsnhshhdznlzhzjjcddcbcj"
"xlbfqbczztpqdnnxljcthqzjgylklszzpcjdscqjhjqkdxgpbajynnsmjtzdxlcjyryynhjbngzjkmjxltbsllrzpylssznxjhll"
"hyllqqzqlsymrcncxsljmlzltzldwdjjllnzggqxppskyggggbfzbdkmwggcxmcgdxjmcjsdycabxjdlnbcddygskydqdxdjjyxh"
"saqazdzfslqxxjnqzylblxxwxqqzbjzlfbblylwdsljhxjyzjwtdjcyfqzqzzdzsxzzqlzcdzfxhwspynpqzmlpplffxjjnzzyls"
"jnyqzfpfzgsywjjjhrdjzzxtxxglghtdxcskyswmmtcwybazbjkshfhgcxmhfqhyxxyzftsjyzbxyxpzlchmzmbxhzzssyfdmncw"
"dabazlxktcshhxkxjjzjsthygxsxyyhhhjwxkzxssbzzwhhhcwtzzzpjxsyxqqjgzyzawllcwxznxgyxyhfmkhydwsqmnjnaycys"
"pmjkgwcqhylajgmzxhmmcnzhbhxclxdjpltxyjkdyylttxfqzhyxxsjbjnayrsmxyplckdnyhlxrlnllstycyyqygzhhsccsmcct"
"zcxhyqfpyyrpbflfqnntszlljmhwtcjqyzwtlnmlmdwmbzzsnzrbpdddlqjjbxtcsnzqqygwcsxfwzlxccrszdzmcyggdyqsgtnn"
"nlsmymmsyhfbjdgyxccpshxczcsbsjyygjmpbwaffyfnxhydxzylremzgzzyndsznlljcsqfnxxkptxzgxjjgbmyyssnbtylbnlh"
"bfzdcyfbmgqrrmzszxysjtznnydzzcdgnjafjbdknzblczszpsgcycjszlmnrznbzzldlnllysxsqzqlcxzlsgkbrxbrbzcycxzj"
"zeeyfgklzlnyhgzcgzlfjhgtgwkraajyzkzqtsshjjxdzyznynnzyrzdqqhgjzxsszbtkjbbfrtjxllfqwjgclqtymblpzdxtzag"
"bdhzzrbgjhwnjtjxlkscfsmwlldcysjtxkzscfwjlbnntzlljzllqblcqmqqcgcdfpbphzczjlpyyghdtgwdxfczqyyyqysrclqz"
"fklzzzgffcqnwglhjycjjczlqzzyjbjzzbpdcsnnjgxdqnknlznnnnpsntsdyfwwdjzjysxyyczcyhzwbbyhxrylybhkjksfxtjj"
"mmchhlltnyymsxxyzpdjjycsycwmdjjkqyrhllngpngtlyycljnnnxjyzfnmlrgjjtyzbsyzmsjyjhgfzqmsyxrszcytlrtqzsst"
"kxgqkgsptgxdnjsgcqcqhmxggztqydjjznlbznxqlhyqgggthqscbyhjhhkyygkggcmjdzllcclxqsftgjslllmlcskctbljszsz"
"mmnytpzsxqhjcnnqnyexzqzcpshkzzyzxxdfgmwqrllqxrfztlystctmjcsjjthjnxtnrztzfqrhcgllgcnnnnjdnlnnytsjtlny"
"xsszxcgjzyqpylfhdjsbbdczgjjjqzjqdybssllcmyttmqnbhjqmnygjyeqyqmzgcjkpdcnmyzgqllslnclmholzgdylfzslncnz"
"lylzcjeshnyllnxnjxlyjyyyxnbcljsswcqqnnyllzldjnllzllbnylnqchxyyqoxccqkyjxxxyklksxeyqhcqkkkkcsnyxxyqxy"
"gwtjohthxpxxhsnlcykychzzcbwqbbwjqcscszsslcylgddsjzmmymcytsdsxxscjpqqsqylyfzychdjynywcbtjsydchcyddjlb"
"djjsodzyqyskkyxdhhgqjyohdyxwgmmmazdybbbppbcmnnpnjzsmtxerxjmhqdntpjdcbsnmssythjtslmltrcplzszmlqdsdmjm"
"qpnqdxcfrnnfsdqqyxhyaykqyddlqyyysszbydslntfgtzqbzmchdhczcwfdxtmqqsphqwwxsrgjcwnntzcqmgwqjrjhtqjbbgwz"
"fxjhnqfxxqywyyhyscdydhhqmrmtmwctbszppzzglmzfollcfwhmmsjzttdhlmyffytzzgzyskjjxqyjzqbhmbzclyghgfmshpcf"
"zsnclpbqsnjyzslxxfpmtyjygbxlldlxpzjyzjyhhzcywhjylsjexfszzywxkzjlnadymlymqjpwxxhxsktqjezrpxxzghmhwqpw"
"qlyjjqjjzszcnhjlchhnxjlqwzjhbmzyxbdhhypylhlhlgfwlcfyytlhjjcwmscpxstkpnhjxsntyxxtestjctlsslstdlllwwyh"
"dnrjzsfgxssyczykwhtdhwjglhtzdqdjzxxqgghltzphcsqfclnjtclzpfstpdynylgmjllycqhynspchylhqyqtmzymbywrfqyk"
"jsyslzdnjmpxyyssrhzjnyqtqdfzbwwdwwrxcwggyhxmkmyyyhmxmzhnksepmlqqmtcwctmxmxjpjjhfxyyzsjzhtybmstsyjznq"
"jnytlhynbyqclcycnzwsmylknjxlggnnpjgtysylymzskttwlgsmzsylmpwlcwxwqcssyzsyxyrhssntsrwpccpwcmhdhhxzdzyf"
"jhgzttsbjhgyglzysmyclllxbtyxhbbzjkssdmalhhycfygmqypjyjqxjllljgclzgqlycjcctotyxmtmshllwlqfxymzmklpszz"
"cxhkjyclctyjcyhxsgyxnnxlzwpyjpxhjwpjpwxqqxlxsdhmrslzzydwdtcxknstzshbsccstplwsscjchjlcgchssphylhfhhxj"
"sxallnylmzdhzxylsxlmzykcldyahlcmddyspjtqjzlngjfsjshctsdszlblmssmnyymjqbjhrzwtyydchjljapzwbgqxbkfnbjd"
"llllyylsjydwhxpsbcmljpscgbhxlqhyrljxyswxhhzlldfhlnnymjljyflyjycdrjlfsyzfsllcqyqfgqyhnszlylmdtdjcnhbz"
"llnwlqxygyyhbmgdhxxnhlzzjzxczzzcyqzfngwpylcpkpykpmclgkdgxzgxwqbdxzzkzfbddlzxjtpjpttbythzzdwslcpnhslt"
"jxxqlhyxxxywzyswttzkhlxzxzpyhgzhknfsyhntjrnxfjcpjztwhplshfcrhnslxxjxxyhzqdxqwnnhyhmjdbflkhcxcwhjfyjc"
"fpqcxqxzyyyjygrpynscsnnnnchkzdyhflxxhjjbyzwttxnncyjjymswyxqrmhxzwfqsylznggbhyxnnbwttcsybhxxwxyhhxyxn"
"knyxmlywrnnqlxbbcljsylfsytjzyhyzawlhorjmnsczjxxxyxchcyqryxqzddsjfslyltsffyxlmtyjmnnyyyxltzcsxqclhzxl"
"wyxzhnnlrxkxjcdyhlbrlmbrdlaxksnlljlyxxlynrylcjtgncmtlzllcyzlpzpzyawnjjfybdyyzsepckzzqdqpbpsjpdyttbdb"
"bbyndycncpjmtmlrmfmmrwyfbsjgygsmdqqqztxmkqwgxllpjgzbqrdjjjfpkjkcxbljmswldtsjxldlppbxcwkcqqbfqbccajzg"
"mykbhyhhzykndqzybpjnspxthlfpnsygyjdbgxnhhjhzjhstrstldxskzysybmxjlxyslbzyslzxjhfybqnbylljqkygzmcyzzym"
"ccslnlhzhwfwyxzmwyxtynxjhbyymcysbmhysmydyshnyzchmjjmzcaahcbjbbhblytylsxsnxgjdhkxxtxxnbhnmlngsltxmrhn"
"lxqqxmzllyswqgdlbjhdcgjyqyymhwfmjybbbyjyjwjmdpwhxqldyapdfxxbcgjspckrssyzjmslbzzjfljjjlgxzgyxyxlszqkx"
"bexyxhgcxbpndyhwectwwcjmbtxchxyqqllxflyxlljlssnwdbzcmyjclwswdczpchqekcqbwlcgydblqppqzqfnqdjhymmcxtxd"
"rmzwrhxcjzylqxdyynhyyhrslnrsywwjjymtltllgtqcjzyabtckzcjyccqlysqxalmzynywlwdnzxqdllqshgpjfjljnjabcqzd"
"jgthhsstnyjfbswzlxjxrhgldlzrlzqzgsllllzlymxxgdzhgbdphzpbrlwnjqbpfdwonnnhlypcnjccndmbcpbzzncyqxldomzb"
"lzwpdwyygdstthcsqsccrsssyslfybnntyjszdfndpdhtqzmbqlxlcmyffgtjjqwftmnpjwdnlbzcmmcngbdzlqlpnfhyymjylsd"
"chdcjwjcctljcldtljjcbddpndsszycndbjlggjzxsxnlycybjjxxcbylzcfzppgkcxqdzfztjjfjdjxzbnzyjqctyjwhdyczhym"
"djxttmpxsplzcdwslshxypzgtfmlcjtacbbmgdewycyzxdszjyhflystygwhkjyylsjcxgywjcbllcsnddbtzbsclyzczzssqdll"
"mjyyhfllqllxfdyhabxggnywyypllsdldllbjcyxjznlhljdxyyqytdlllbngpfdfbbqbzzmdpjhgclgmjjpgaehhbwcqxajhhhz"
"chxyphjaxhlphjpgpzjqcqzgjjzzgzdmqyybzzphyhybwhazyjhykfgdpfqsdlzmljxjpgalxzdaglmdgxmmzqwtxdxxpfdmmssy"
"mpfmdmmkxksyzyshdzkjsysmmzzzmdydyzzczxbmlstmdyemxckjmztyymzmzzmsshhdccjewxxkljsthwlsqlyjzllsjssdppmh"
"nlgjczyhmxxhgncjmdhxtkgrmxfwmckmwkdcksxqmmmszzydkmsclcmpcjmhrpxqpzdsslcxkyxtwlkjyahzjgzjwcjnxyhmmbml"
"gjxmhlmlgmxctkzmjlyscjsyszhsyjzjcdajzhbsdqjzgwtkqxfkdmsdjlfmnhkzqkjfeypzyszcdpynffmzqykttdzzefmzlbnp"
"plplpbpszalltnlkckqzkgenjlwalkxydpxnhsxqnwqnkxqclhyxxmlnccwlymqyckynnlcjnszkpyzkcqzqljbdmdjhlasqlbyd"
"wqlwdgbqcryddztjybkbwszdxdtnpjdtcnqnfxqqmgnseclstbhpwslctxxlpwydzklnqgzcqapllkqcylbqmqczqcnjslqzdjxl"
"ddhpzqdljjxzqdjyzhhzlkcjqdwjppypqakjyrmpzbnmcxkllzllfqpylllmbsglzysslrsysqtmxyxzqzbscnysyztffmzzsmzq"
"hzssccmlyxwtpzgxzjgzgsjzgkddhtqggzllbjdzlsbzhyxyzhzfywxytymsdnzzyjgtcmtnxqyxjscxhslnndlrytzlryylxqht"
"xsrtzcgyxbnqqzfhykmzjbzymkbpnlyzpblmcnqyzzzsjztjctzhhyzzjrdyzhnfxklfzslkgjtctssyllgzrzbbjzzklpkbczys"
"nnyxbjfbnjzzxcdwlzyjxzzdjjgggrsnjkmsmzjlsjywqsnyhqjsxpjztnlsnshrnynjtwchglbnrjlzxwjqxqkysjycztlqzybb"
"ybyzjqdwgyzcytjcjxckcwdkkzxsnkdnywwyyjqyytlytdjlxwkcjnklccpzcqqdzzqlcsfqchqqgssmjzzllbjjzysjhtsjdysj"
"qjpdszcdchjkjzzlpycgmzndjxbsjzzsyzyhgxcpbjydssxdzncglqmbtsfcbfdzdlznfgfjgfsmpnjqlnblgqcyyxbqgdjjqsrf"
"kztjdhczklbsdzcfytplljgjhtxzcsszzxstjygkgckgynqxjplzbbbgcgyjzgczqszlbjlsjfzgkqqjcgycjbzqtldxrjnbsxxp"
"zshszycfwdsjjhxmfczpfzhqhqmqnknlyhtycgfrzgnqxcgpdlbzcsczqlljblhbdcypscppdymzzxgyhckcpzjgslzlnscnsldl"
"xbmsdlddfjmkdqdhslzxlsznpqpgjdlybdskgqlbzlnlkyyhzttmcjnqtzzfszqktlljtyyllnllqyzqlbdzlslyyzxmdfszsnxl"
"xznczqnbbwskrfbcylctnblgjpmczzlstlxshtzcyzlzbnfmqnlxflcjlyljqcbclzjgnsstbrmhxzhjzclxfnbgxgtqncztmsfz"
"kjmssncljkbhszjntnlzdntlmmjxgzjyjczxyhyhwrwwqnztnfjscpyshzjfyrdjsfscjzbjfzqzchzlxfxsbzqlzsgyftzdcszx"
"zjbjpszkjrhxjzcgbjkhcggtxkjqglxbxfgtrtylxqxhdtsjxhjzjjcmzlcqsbtxwqgxtxxhxftsdkfjhzyjfjxnzldlllcqsqqz"
"qwqxswqtwgwbzcgcllqzbclmqjtzgzyzxljfrmyzflxnsnxxjkxrmjdzdmmyxbsqbhgzmwfwygmjlzbyytgzyccdjyzxsngnyjyz"
"nbgpzjcqsyxsxrtfyzgrhztxszzthcbfclsyxzlzqmzlmplmxzjssfsbysmzqhxxnxrxhqzzzsslyflczjrcrxhhzxqndshxsjjh"
"qcjjbcynsysxjbqjpxzqplmlxzkyxlxcnlcycxxzzlxdlllmjyhzxhyjwkjrwyhcpsgnrzlfzwfzznsxgxflzsxzzzbfcsyjdbrj"
"krdhhjxjljjtgxjxxstjtjxlyxqfcsgswmsbctlqzzwlzzkxjmltmjyhsddbxgzhdlbmyjfrzfcgclyjbpmlysmsxlszjqqhjzfx"
"gfqfqbphngyyqxgztnqwyltlgwgwwhnlfmfgzjmgmgbgtjflyzzgzyzaflsspmlbflcwbjztljjmzlpjjlymqtmyyyfbgygqzgly"
"zdxqyxrqqqhsxyyqxygjtyxfsfsllgnqcygycwfhcccfxpylypllzqxxxxxqqhhsshjzcftsczjxspzwhhhhhapylqnlpqafyhxd"
"ylnkmzqgggddesrenzltzgchyppcsqjjhclljtolnjpzljlhymhezdydsqycddhgznndzclzywllznteydgnlhslpjjbdgwxpcnn"
"tycklkclwkllcasstknzdnnjttlyyzssysszzryljqkcgdhhyrxrzydgrgcwcgzqffbppjfzynakrgywyjpqxxfkjtszzxswzddf"
"bbqtbgtzkznpzfpzxzpjszbmqhkyyxyldkljnypkyghgdzjxxeaxpnznctzcmxcxmmjxnkszqnmnlwbwwqjjyhclstmcsxnjcxxt"
"pcnfdtnnpglllzcjlspblpgjcdtnjjlyarscffjfqwdpgzdwmrzzcgodaxnssnyzrestyjwjyjdbcfxnmwttbqlwstszgybljpxg"
"lbnclgpcbjftmxzljylzxcltpnclcgxtfzjshcrxsfysgdkntlbyjcyjllstgqcbxnhzxbxklylhzlqzlnzcqwgzlgzjncjgcmnz"
"zgjdzxtzjxycyycxxjyyxjjxsssjstsstdppghtcsxwzdcsynptfbchfbblzjclzzdbxgcjlhpxnfzflsyltnwbmnjhszbmdnbcy"
"sccldnycndqlyjjhmqllcsgljjsyfpyyccyltjantjjpwycmmgqyysxdxqmzhszxbftwwzqswqrfkjlzjqqyfbrxjhhfwjgzyqac"
"myfrhcyybynwlpexcczsyyrlttdmqlrkmpbgmyyjprkznbbsqyxbhyzdjdnghpmfsgbwfzmfqmmbzmzdcgjlnnnxyqgmlrygqccy"
"xzlwdkcjcggmcjjfyzzjhycfrrcmtznzxhkqgdjxccjeascrjthpljlrzdjrbcqhjdnrhylyqjsymhzydwcdfryhbbydtssccwbx"
"glpzmlzjdqsscfjmmxjcxjytycghycjwynsxlfemwjnmkllswtxhyyyncmmcyjdqdjzglljwjnkhpzggflccsczmcbltbhbqjxqd"
"jpdjztghglfjawbzyzjltstdhjhctcbchflqmpwdshyytqwcnntjtlnnmnndyyyxsqkxwyyflxxnzwcxypmaelyhgjwzzjbrxxaq"
"jfllpfhhhytzzxsgqjmhspgdzqwbwpjhzjdyjcqwxkthxsqlzyymysdzgnqckknjlwpnsyscsyzlnmhqsyljxbcxtlhzqzpcycyk"
"pppnsxfyzjjrcemhszmnxlxglrwgcstlrsxbygbzgnxcnlnjlclynymdxwtzpalcxpqjcjwtcyyjlblxbzlqmyljbghdslssdmxm"
"bdczsxyhamlczcpjmcnhjyjnsykchskqmczqdllkablwjqsfmocdxjrrlyqchjmybyqlrhetfjzfrfksryxfjdwtsxxywsqjysly"
"xwjhsdlxyyxhbhawhwjcxlmyljcsqlkydttxbzslfdxgxsjkhsxxybssxdpwncmrptqzczenygcxqfjxkjbdmljzmqqxnoxslyxx"
"lylljdzptymhbfsttqqwlhsgynlzzalzxclhtwrrqhlstmypyxjjxmnsjnnbryxyjllyqyltwylqyfmlkljdnlltfzwkzhljmlhl"
"jnljnnlqxylmbhhlnlzxqchxcfxxlhyhjjgbyzzkbxscqdjqdsndzsygzhhmgsxcsymxfepcqwwrbpyyjqryqcyjhqqzyhmwffhg"
"zfrjfcdbxntqyzpcyhhjlfrzgpbxzdbbgrqstlgdgylcqmgchhmfywlzyxkjlypjhsywmqqggzmnzjnsqxlqsyjtcbehsxfszfxz"
"wfllbcyyjdytdthwzsfjmqqyjlmqsxlldttkghybfpwdyysqqrnqwlgwdebzwcyygcnlkjxtmxmyjsxhybrwfymwfrxyymxysctz"
"ztfykmldhqdlgyjnlcryjtlpsxxxywlsbrrjwxhqybhtydnhhxmmywytycnnmnssccdalwztcpqpyjllqzyjswjwzzmmglmxclmx"
"nzmxmzsqtzppjqblpgxjzhfljjhycjsrxwcxsncdlxsyjdcqzxslqyclzxlzzxmxqrjmhrhzjbhmfljlmlclqnldxzlllfyprgjy"
"nxcqqdcmqjzzxhnpnxzmemmsxykynlxsxtljxyhwdcwdzhqyybgybcyscfgfsjnzdrzzxqxrzrqjjymcanhrjtldbpyzbstjhxxz"
"ypbdwfgzzrpymnnkxcqbyxnbnfyckrjjcmjegrzgyclnnzdnkknsjkcljspgyyclqqjybzssqlllkjftbgtylcccdblsppfylgyd"
"tzjqjzgkntsfcxbdkdxxhybbfytyhbclnnytgdhryrnjsbtcsnyjqhklllzslydxxwbcjqsbxnpjzjzjdzfbxxbrmladhcsnclbj"
"dstblprznswsbxbcllxxlzdnzsjpynyxxyftnnfbhjjjgbygjpmmmmsszljmtlyzjxswxtyledqpjmpgqzjgdjlqjwjqllsdgjgy"
"gmscljjxdtygjqjjjcjzcjgdzdshqgzjggcjhqxsnjlzzbxhsgzxcxyljxyxyydfqqjhjfxdhctxjyrxysqtjxyefyyssyxjxncy"
"zxfxcsxszxyyschshxzzzgzzzgfjdldylnpzgsjaztyqzpbxcbdztzczyxxyhhscjshcggqhjhgxhsctmzmehyxgebtclzkkwytj"
"zrslekestdbcyhqqsayxcjxwwgsphjszsdncsjkqcxswxfctynydpccczjqtcwjqjzzzqzljzhlsbhpydxpsxshhezdxfptjqyzc"
"xhyaxncfzyyhxgnqmywntzsjbnhhgymxmxqcnssbcqsjyxxtyyhybcqlmmszmjzzllcogxzaajzyhjmchhcxzsxsdznleyjjzjbh"
"zwjzsqtzpsxzzdsqjjjlnyazphhyysrnqzthzhnyjyjhdzxzlswclybzyecwcycrylchzhzydzydyjdfrjjhtrsqtxyxjrjhojyn"
"xelxsfsfjzghpzsxzszdzcqzbyyklsgsjhczshdgqgxyzgxchxzjwyqwgyhksseqzzndzfkwyssdclzstsymcdhjxxyweyxczayd"
"mpxmdsxybsqmjmzjmtjqlpjyqzcgqhyjhhhqxhlhdldjqcfdwbsxfzzyyschtytyjbhecxhjkgqfxbhyzjfxhwhbdzfyzbchpnpg"
"dydmsxhkhhmamlnbyjtmpxejmcthqbzyfcgtyhwphftgzzezsbzegpbmdskftycmhbllhgpzjxzjgzjyxzsbbqsczzlzscstpgxm"
"jsfdcczjzdjxsybzlfcjsazfgszlwbczzzbyztzynswyjgxzbdsynxlgzbzfygczxbzhzftpbgzgejbstgkdmfhyzzjhzllzzgjq"
"zlsfdjsscbzgpdlfzfzszyzyzsygcxsnxxchczxtzzljfzgqsqqxcjqccccdjcdszzyqjccgxztdlgscxzsyjjqtcclqdqztqchq"
"qyzynzzzpbkhdjfcjfztypqyqttynlmbdktjcpqzjdzfpjsbnjlgyjdxjdcqkzgqkxclbzjtcjdqbxdjjjstcxnxbxqmslyjcxnt"
"jqwwcjjnjjlllhjcwqtbzqqczczpzzdzyddcyzdzccjgtjfzdprntctjdcxtqzdtjnplzbcllctdsxkjzqdmzlbznbtjdcxfczdb"
"czjjltqqpldckztbbzjcqdcjwynllzlzccdwllxwzlxrxntqjczxkjlsgdnqtddglnlajjtnnynkqlldzntdnycygjwyxdxfrsqs"
"tcdenqmrrqzhhqhdldazfkapbggpzrebzzykyqspeqjjglkqzzzjlysyhyzwfqznlzzlzhwcgkypqgnpgblplrrjyxcccgyhsfzf"
"wbzywtgzxyljczwhncjzplfflgskhyjdeyxhlpllllcygxdrzelrhgklzzyhzlyqszzjzqljzflnbhgwlczcfjwspyxzlzlxgccp"
"zbllcxbbbbnbbcbbcrnnzccnrbbnnldcgqyyqxygmqzwnzytyjhyfwtehznjywlccntzyjjcdedpwdztstnjhtymbjnyjzlxtsst"
"phndjxxbyxqtzqddtjtdyztgwscszqflshlnzbcjbhdlyzjyckwtydylbnydsdsycctyszyyebgexhqddwnygyclxtdcystqnygz"
"ascsszzdzlcclzrqxyywljsbymxshzdembbllyyllytdqyshymrqnkfkbfxnnsbychxbwjyhtqbpbsbwdzylkgzskyghqzjxhxjx"
"gnljkzlyycdxlfwfghljgjybxblybxqpqgntzplncybxdjyqydymrbeyjyyhkxxstmxrczzjwxyhybmcflyzhqyzfwxdbxbcwzms"
"lpdmyckfmzklzcyqycclhxfzlydqzpzygyjyzmdxtzfnnyttqtzhgsfcdmlccytzxjcytjmkslpzhysnwllytpzctzccktxdhxxt"
"qcyfksmqccyyazhtjplylzlyjbjxtfnyljyynrxcylmmnxjsmybcsysslzylljjgyldzdlqhfzzblfndsqkczfyhhgqmjdsxyctt"
"xnqnjpyybfcjtyyfbnxejdgyqbjrcnfyyqpghyjsyzngrhtknlnndzntsmgklbygbpyszbydjzsstjztsxzbhbscsbzczptqfzlq"
"flypybbjgszmnxdjmtsyskkbjtxhjcegbsmjyjzcstmljyxrczqscxxqpyzhmkyxxxjcljyrmyygadyskqlnadhrskqxzxztcggz"
"dlmlwxybwsyctbhjhcfcwzsxwwtgzlxqshnyczjxemplsrcgltnzntlzjcyjgdtclglbllqpjmzpapxyzlaktkdwczzbncctdqqz"
"qyjgmcdxltgcszlmlhbglkznnwzndxnhlnmkydlgxdtwcfrjerctzhydxykxhwfzcqshknmqqhzhhymjdjskhxzjzbzzxympajnm"
"ctbxlsxlzynwrtsqgscbptbsgzwyhtlkssswhzzlyytnxjgmjrnsnnnnlskztxgxlsammlbwldqhylakqcqctmycfjbslxclzjcl"
"xxknbnnzlhjphqplsxsckslnhpsfqcytxjjzljldtzjjzdlydjntptnndskjfsljhylzqqzlbthydgdjfdbyadxdzhzjnthqbykn"
"xjjqczmlljzkspldsclbblnnlelxjlbjycxjxgcnlcqplzlznjtsljgyzdzpltqcssfdmnycxgbtjdcznbgbqyqjwgkfhtnbyqzq"
"gbkpbbyzmtjdytblsqmbsxtbnpdxklemyycjynzdtldykzzxtdxhqshygmzsjycctayrzlpwltlkxslzcggexclfxlkjrtlqjaqz"
"ncmbqdkkcxglczjzxjhptdjjmzqykqsecqzdshhadmlzfmmzbgntjnnlhbyjbrbtmlbyjdzxlcjlpldlpcqdhlhzlycblcxccjad"
"qlmzmmsshmybhbnkkbhrsxxjmxmdznnpklbbrhgghfchgmnklltsyyycqlcskymyehywxnxqywbawykqldnntndkhqcgdqktgpkx"
"hcpdhtwnmssyhbwcrwxhjmkmzngwtmlkfghkjyldyycxwhyyclqhkqhtdqkhffldxqwytyydesbpkyrzpjfyyzjceqdzzdlattpb"
"fjllcxdlmjsdxegwgsjqxcfbssszpdyzcxznyxppzydlyjccpltxlnxyzyrscyyytylwwndsahjsygyhgywwaxtjzdaxysrltdps"
"syxfnejdxyzhlxlllzhzsjnyqyqyxyjghzgjcyjchzlycdshhsgczyjscllnxzjjyyxnfsmwfpyllyllabmddhwzxjmcxztzpmlq"
"chsfwzynctlndywlslxhymmylmbwwkyxyaddxylldjpybpwnxjmmmllhafdllaflbnhhbqqjqzjcqjjdjtffkmmmpythygdrjrdd"
"wrqjxnbysrmzdbyytbjhpymyjtjxaahggdqtmystqxkbtzbkjlxrbyqqhxmjjbdjntgtbxpgbktlgqxjjjcdhxqdwjlwrfmjgwqh"
"cnrxswgbtgygbwhswdwrfhwytjjxxxjyzyslphyypyyxhydqpxshxyxgskqhywbdddpplcjlhqeewjgsyykdpplfjthkjltcyjhh"
"jttpltzzcdlyhqkcjqysteeyhkyzyxxyysddjkllpymqyhqgxqhzrhbxpllnqydqhxsxxwgdqbshyllpjjjthyjkyphthyyktyez"
"yenmdshlzrpqfbnfxzbsftlgxsjbswyysksflxlpplbbblnsfbfyzbsjssylpbbffffsscjdstjsxtryjcyffsyzyzbjtlctsbsd"
"hrtjjbytcxyyeylycbnebjdsysyhgsjzbxbytfzwgenhhhthjhhxfwgcstbgxklstyymtmbyxjskzscdyjrcythxzfhmymcxlzns"
"djtxtxrycfyjsbsdyerxhljxbbdeynjghxgckgscymblxjmsznskgxfbnbbthfjyafxwxfbxmyfhdttcxzzpxrsywzdlybbktyqw"
"qjbzypzjznjpzjlztfysbttslmptzrtdxqsjehbnylndxljsqmlhtxtjecxalzzspktlzkqqyfsyjywpcpqfhjhytqxzkrsgtksq"
"czlptxcdyyzsslzslxlzmacpcqbzyxhbsxlzdltztjtylzjyytbzypltxjsjxhlbmytxcqrblzssfjzztnjytxmyjhlhpblcyxqj"
"qqkzzscpzkswalqsplczzjsxgwwwygyatjbbctdkhqhkgtgpbkqyslbxbbckbmllndzstbklggqkqlzbkktfxrmdkbftpzfrtppm"
"ferqnxgjpzsstlbztpszqzsjdhljqlzbpmsmmsxlqqnhknblrddnhxdkddjcyyljfqgzlgsygmjqjkhbpmxyxlytqwlwjcpbmjxc"
"yzydrjbhtdjyeqshtmgsfyplwhlzffnynnhxqhpltbqpfbjwjdbygpnxtbfzjgnnntjshxeawtzylltyqbwjpgxghnnkndjtmszs"
"qynzggnwqtfhclssgmnnnnynzqqxncjdqgzdlfnykljcjllzlmzznnnnsshthxjlzjbbhqjwwycrdhlyqqjbeyfsjhthnrnwjhwp"
"slmssgzttygrqqwrnlalhmjtqjsmxqbjjzjqzyzkxbjqxbjxshzssfglxmxnxfghkzszggslcnnarjxhnlllmzxelglxydjytlfb"
"kbpnlyzfbbhptgjkwetzhkjjxzxxglljlstgshjjyqlqzfkcgnndjsszfdbctwwseqfhqjbsaqtgypjlbxbmmywxgslzhglsgnyf"
"ljbyfdjfngsfmbyzhqffwjsyfyjjphzbyyzffwotjnlmftwlbzgyzqxcdjygzyyryzynyzwegazyhjjlzrthlrmgrjxzclnnnljj"
"yhtbwjybxxbxjjtjteekhwslnnlbsfazpqqbdlqjjtyyqlyzkdksqjnejzldqcgjqnnjsncmrfqthtejmfctyhypymhydmjncfgy"
"yxwshctxrljgjzhzcyyyjltkttntmjlzclzzayyoczlrlbszywjytsjyhbyshfjlykjxxtmzyyltxxypslqyjzyzyypnhmymdyyl"
"blhlsyygqllnjjymsoycbzgdlyxylcqyxtszegxhzglhwbljheyxtwqmakbpqcgyshhegqcmwyywljyjhyyzlljjylhzyhmgsljl"
"jxcjjyclycjbcpzjzjmmwlcjlnqljjjlxyjmlszljqlycmmgcfmmfpqqmfxlqmcffqmmmmhnznfhhjgtthxkhslnchhyqzxtmmqd"
"cydyxyqmyqylddcyaytazdcymdydlzfffmmycqcwzzmabtbyctdmndzggdftypcgqyttssffwbdttqssystwnjhjytsxxylbyyhh"
"whxgzxwznnqzjzjjqjccchykxbzszcnjtllcqxynjnckycynccqnxyewyczdcjycchyjlbtzyycqwlpgpyllgktltlgkgqbgychj"
"xy";
@interface NSString (enumrateCharater)
- (void)enumerateCharaterUsingBlock:(void(^)(unsigned short letter, BOOL *stop))enumertae;
@end
@implementation NSString (enumrateCharater)
- (void)enumerateCharaterUsingBlock:(void(^)(unsigned short letter, BOOL *stop))enumertae
{
static BOOL stop;
for (NSInteger i = 0; i < [self length]; i++)
{
NSLog(@"letter1:%c", [self characterAtIndex:i]);
enumertae([self characterAtIndex:i], &stop);
if (stop) break;
}
}
@end
@implementation HTFirstLetter
+ (char)pinyinFirstLetter:(unsigned short )hanzi
{
int index = hanzi - HANZI_START;
if (index >= 0 && index <= HANZI_COUNT)
{
return firstLetterArray[index];
}
else
{
return '#';
}
}
+ (NSString *)firstLetter:(NSString *)chineseString
{
NSString *firstLetters = [HTFirstLetter firstLetters:chineseString];
NSArray *firstLetterArray = [firstLetters componentsSeparatedByString:@" "];
if ([firstLetterArray count] > 0)
firstLetters = [firstLetterArray objectAtIndex:0];
return firstLetters;
}
+ (NSString *)firstLetters:(NSString *)chineseString
{
return [HTFirstLetter firstLetterUsingSeperate:@" " chineseString:chineseString];
}
+ (NSString *)firstLetterUsingSeperate:(NSString *)seperate chineseString:(NSString *)chineseString
{
__block NSString *firstLetters = @"";
[chineseString enumerateCharaterUsingBlock:^(unsigned short letter, BOOL *stop) {
int index = letter - HANZI_START;
if (index >= 0 && index <= HANZI_COUNT){
if ([firstLetters length]){
firstLetters = [firstLetters stringByAppendingFormat:@" %c", firstLetterArray[index]];
}else {
firstLetters = [firstLetters stringByAppendingFormat:@"%c", firstLetterArray[index]];
}
}else if ((letter > 'a' && letter < 'z') ||
(letter > 'A' && letter < 'Z')){
if ([firstLetters length]){
firstLetters = [firstLetters stringByAppendingFormat:@" %c", letter];
}else {
firstLetters = [firstLetters stringByAppendingFormat:@"%c", letter];
}
}else {
//如果是字母或其它符号,都返回 #
if ([firstLetters length]){
firstLetters = [firstLetters stringByAppendingFormat:@" %c",true ? '#' : letter];
}else {
firstLetters = [firstLetters stringByAppendingFormat:@"%c", true ? '#' : letter];
}
}
}];
return firstLetters;
}
@end
================================================
FILE: Pod/Classes/Extend/SwiftRegex/Match.swift
================================================
//
// Match.swift
// Cupertino
//
// Created by William Kent on 2/19/15.
// Copyright (c) 2015 William Kent. All rights reserved.
//
import Foundation
private func safeSubstring(whole: String, range: NSRange) -> String? {
if range.location != NSNotFound && range.length != 0 {
return (whole as NSString).substringWithRange(range)
} else {
return nil
}
}
public struct RegexMatch {
private let sourceString: String
private let cocoaMatch: NSTextCheckingResult
internal init(cocoaMatch: NSTextCheckingResult, inString source: String) {
self.sourceString = source
self.cocoaMatch = cocoaMatch
}
public var range: NSRange {
get {
return cocoaMatch.range
}
}
public var entireMatch: String? {
get {
return safeSubstring(sourceString, range: cocoaMatch.range)
}
}
public var subgroupCount: Int {
get {
return cocoaMatch.numberOfRanges - 1
}
}
public func subgroupRangeAtIndex(index: Int) -> NSRange? {
return cocoaMatch.rangeAtIndex(index + 1)
}
public func subgroupMatchAtIndex(index: Int) -> String? {
let range = cocoaMatch.rangeAtIndex(index + 1)
return safeSubstring(sourceString, range: range)
}
}
================================================
FILE: Pod/Classes/Extend/SwiftRegex/Regex.swift
================================================
//
// Regex.swift
// Cupertino
//
// Created by William Kent on 2/19/15.
// Copyright (c) 2015 William Kent. All rights reserved.
//
import Foundation
private func convertRange(range: NSRange, relativeToString string: String) -> Range {
let start = string.startIndex.advancedBy(range.location)
let end = string.startIndex.advancedBy(NSMaxRange(range))
return Range(start: start, end: end)
}
public enum RegexFlags {
case CaseInsensitive
case AllowCommentsAndWhitespace
case IgnoreMetacharacters
case DotMatchesLineSeparators
case AnchorsMatchLines
case UseUnicodeWordBoundaries
}
public struct Regex {
public let pattern: String
public var options: Set
public init(_ pattern: String, options: Set) {
self.pattern = pattern
self.options = options
}
public init(_ pattern: String) {
self.pattern = pattern
self.options = []
}
private var matcherOptions: NSRegularExpressionOptions {
get {
var opts: NSRegularExpressionOptions = NSRegularExpressionOptions.CaseInsensitive
if options.contains(.CaseInsensitive) {
opts = NSRegularExpressionOptions.CaseInsensitive
}
if options.contains(.AllowCommentsAndWhitespace) {
opts = NSRegularExpressionOptions.AllowCommentsAndWhitespace
}
if options.contains(.IgnoreMetacharacters) {
opts = NSRegularExpressionOptions.IgnoreMetacharacters
}
if options.contains(.DotMatchesLineSeparators) {
opts = NSRegularExpressionOptions.DotMatchesLineSeparators
}
if options.contains(.AnchorsMatchLines) {
opts = NSRegularExpressionOptions.AnchorsMatchLines
}
if options.contains(.UseUnicodeWordBoundaries) {
opts = NSRegularExpressionOptions.UseUnicodeWordBoundaries
}
return opts
}
}
private var matcher: NSRegularExpression? {
get {
return try? NSRegularExpression(pattern: self.pattern, options: self.matcherOptions)
}
}
public func test(string: String) -> Bool? {
return test(string, options: [])
}
public func test(string: String, options: NSMatchingOptions) -> Bool? {
// This function returns true if the regex matches, false if the regex does
// not match, or nil if there is a syntax error in the regex itself.
if let matcher = matcher {
return matcher.numberOfMatchesInString(string, options: options, range: NSMakeRange(0, string.characters.count)) != 0
} else {
return nil
}
}
public func match(string: String) -> [RegexMatch]? {
return match(string, options: [])
}
public func match(string: String, options: NSMatchingOptions) -> [RegexMatch]? {
if let matcher = matcher {
let cocoaMatches = matcher.matchesInString(string, options: options, range: NSMakeRange(0, string.characters.count))
var retval = [RegexMatch]()
for match: AnyObject in cocoaMatches {
if let match = match as? NSTextCheckingResult {
retval.append(RegexMatch(cocoaMatch: match, inString: string))
}
}
return retval
} else {
return nil
}
}
public func match(string: String, options: NSMatchingOptions, startPosition: Int) -> [RegexMatch]? {
if let matcher = matcher {
let cocoaMatches = matcher.matchesInString(string, options: options, range: NSMakeRange(startPosition, string.characters.count - startPosition))
var retval = [RegexMatch]()
for match: AnyObject in cocoaMatches {
if let match = match as? NSTextCheckingResult {
retval.append(RegexMatch(cocoaMatch: match, inString: string))
}
}
return retval
} else {
return nil
}
}
public func replace(string: String, withTemplate template: String) -> String? {
return replace(string, options: [], withTemplate: template)
}
public func replace(string: String, options: NSMatchingOptions, withTemplate template: String) -> String? {
if let matcher = matcher {
let workString = NSMutableString(string: string)
matcher.replaceMatchesInString(workString, options: options, range: NSMakeRange(0, workString.length), withTemplate: template)
let retval = workString as NSString
return String(retval)
}
return nil
}
public func replace(string: String, withBlock block: (RegexMatch) -> String) -> String? {
return replace(string, options: [], withBlock: block)
}
public func replace(string: String, options: NSMatchingOptions, withBlock block: (RegexMatch) -> String) -> String? {
if let matches = match(string, options: options) {
var replacements: [(NSRange, String)] = []
for match in matches {
let replacedSubstring = block(match)
replacements.append((match.range, replacedSubstring))
}
// Sort the replacements in order of location, then reverse it.
// By applying the replacements in right-to-left order, I avoid having
// to recalculate all the indices when a replacement changes the length
// of the replaced substring.
replacements.sortInPlace({
(lhs, rhs) -> Bool in
let (leftRange, _) = lhs
let (rightRange, _) = rhs
return leftRange.location < rightRange.location
})
replacements = Array(replacements.reverse())
var retval = string
for pair in replacements {
let (range, substring) = pair
retval.replaceRange(convertRange(range, relativeToString: retval), with: substring)
}
return retval
} else {
return nil
}
}
}
extension Regex: StringLiteralConvertible {
public typealias ExtendedGraphemeClusterLiteralType = StringLiteralType
public typealias UnicodeScalarLiteralType = UnicodeScalar
public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
self.pattern = "\(value)"
self.options = []
}
public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
self.pattern = value
self.options = []
}
public init(stringLiteral value: StringLiteralType) {
self.pattern = value
self.options = []
}
}
================================================
FILE: Pod/Classes/Extend/URLManager/UIViewController+URLManage.h
================================================
//
// UIViewController+URLManage.h
// rssreader
//
// Created by zhuchao on 15/2/11.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
#import
@interface UIViewController (URLManage)
@property(nonatomic,retain)NSURL *originUrl;
@property(nonatomic,retain)NSString *path;
@property(nonatomic,retain)NSDictionary *params;
@property(nonatomic,retain)NSDictionary *dictQuery;
+ (UIViewController *)initFromString:(NSString *)aString fromConfig:(NSDictionary *)config;
+ (UIViewController *)initFromURL:(NSURL *)url fromConfig:(NSDictionary *)config;
+ (UIViewController *)initFromString:(NSString *)aString withQuery:(NSDictionary *)query fromConfig:(NSDictionary *)config;
+ (UIViewController *)initFromURL:(NSURL *)url withQuery:(NSDictionary *)query fromConfig:(NSDictionary *)config;
@end
@interface NSObject (URLManage)
+ (Class)classFromString:(NSString *)className;
+ (NSObject *)objectFromString:(NSString *)className;
@end
================================================
FILE: Pod/Classes/Extend/URLManager/UIViewController+URLManage.m
================================================
//
// UIViewController+URLManage.m
// rssreader
//
// Created by zhuchao on 15/2/11.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
#import "UIViewController+URLManage.h"
#import
static char URLoriginUrl;
static char URLpath;
static char URLparams;
static char URLdictQuery;
@implementation UIViewController (URLManage)
-(void)setOriginUrl:(NSURL *)originUrl{
[self willChangeValueForKey:@"originUrl"];
objc_setAssociatedObject(self, &URLoriginUrl,
originUrl,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self didChangeValueForKey:@"originUrl"];
}
-(NSURL *)originUrl {
return objc_getAssociatedObject(self, &URLoriginUrl);
}
-(NSString *)path {
return objc_getAssociatedObject(self, &URLpath);
}
-(void)setPath:(NSURL *)path{
[self willChangeValueForKey:@"path"];
objc_setAssociatedObject(self, &URLpath,
path,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self didChangeValueForKey:@"path"];
}
-(NSDictionary *)params {
return objc_getAssociatedObject(self, &URLparams);
}
-(void)setParams:(NSDictionary *)params{
[self willChangeValueForKey:@"params"];
objc_setAssociatedObject(self, &URLparams,
params,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self didChangeValueForKey:@"params"];
}
-(NSDictionary *)dictQuery {
return objc_getAssociatedObject(self, &URLdictQuery);
}
-(void)setDictQuery:(NSDictionary *)dictQuery{
[self willChangeValueForKey:@"dictQuery"];
objc_setAssociatedObject(self, &URLdictQuery,
dictQuery,
OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self didChangeValueForKey:@"dictQuery"];
}
-(void)open:(NSURL *)url withQuery:(NSDictionary *)dict{
self.path = [url path];
self.originUrl = url;
self.dictQuery = dict;
NSArray *components = [[url query] componentsSeparatedByString:@"&"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
for (NSString *component in components) {
NSArray *subcomponents = [component componentsSeparatedByString:@"="];
[parameters setObject:[[subcomponents objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
forKey:[[subcomponents objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
self.params = parameters;
}
+ (UIViewController *)initFromString:(NSString *)aString fromConfig:(NSDictionary *)config{
return [UIViewController initFromURL:[NSURL URLWithString:aString] withQuery:nil fromConfig:config];
}
+ (UIViewController *)initFromURL:(NSURL *)url fromConfig:(NSDictionary *)config{
return [UIViewController initFromURL:url withQuery:nil fromConfig:config];
}
+ (UIViewController *)initFromString:(NSString *)aString withQuery:(NSDictionary *)query fromConfig:(NSDictionary *)config{
return [UIViewController initFromURL:[NSURL URLWithString:aString] withQuery:query fromConfig:config] ;
}
+ (UIViewController *)initFromURL:(NSURL *)url withQuery:(NSDictionary *)query fromConfig:(NSDictionary *)config
{
UIViewController* scene = nil;
NSString *home;
if(url.path ==nil){
home = [NSString stringWithFormat:@"%@://%@", url.scheme, url.host];
}else{
home = [NSString stringWithFormat:@"%@://%@%@", url.scheme, url.host,url.path];
}
if([config.allKeys containsObject:url.scheme]){
id cgf = [config objectForKey:url.scheme];
Class class = nil;
if([cgf isKindOfClass:[NSString class]]){
class = [NSObject classFromString:cgf];
}else if([cgf isKindOfClass:[NSDictionary class]]){
NSDictionary *dict = (NSDictionary *)cgf;
if([dict.allKeys containsObject:home]){
class = [NSObject classFromString:[dict objectForKey:home]];
}else{
class = [NSObject classFromString:url.host];
}
}
if(class !=nil){
scene = [[class alloc]init];
if([scene respondsToSelector:@selector(open:withQuery:)]){
[scene open:url withQuery:query];
}
}
}else if([query objectForKey:@"openURL"] || [url.scheme hasPrefix:@"http"]){
[[UIApplication sharedApplication] openURL:url];
}
return scene;
}
@end
@implementation NSObject (URLManage)
+ (Class)classFromString:(NSString *)className {
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"];
NSString *classStringName = [NSString stringWithFormat:@"%@.%@",appName, className];
return NSClassFromString(classStringName);
}
+ (NSObject *)objectFromString:(NSString *)className{
Class clazz = [NSObject classFromString:className];
return [[clazz alloc]init];
}
@end
================================================
FILE: Pod/Classes/Extend/URLManager/URLManager.h
================================================
//
// URLManager.h
// rssreader
//
// Created by zhuchao on 15/3/6.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
#import "URLNavigation.h"
#import "UIViewController+URLManage.h"
@interface URLManager : NSObject
@property(nonatomic,retain)NSDictionary *config;
+ (URLManager *)shareInstance;
+ (void)loadConfigFromPlist:(NSString *)plistPath;
+ (void)pushURLString:(NSString *)urlString animated:(BOOL)animated;
+ (void)pushURLString:(NSString *)urlString animated:(BOOL)animated replace:(BOOL)replace;
+ (void)pushURLString:(NSString *)urlString query:(NSDictionary *)query animated:(BOOL)animated;
+ (void)pushURLString:(NSString *)urlString query:(NSDictionary *)query animated:(BOOL)animated replace:(BOOL)replace;
+ (void)pushURL:(NSURL *)url animated:(BOOL)animated;
+ (void)pushURL:(NSURL *)url animated:(BOOL)animated replace:(BOOL)replace;
+ (void)pushURL:(NSURL *)url query:(NSDictionary *)query animated:(BOOL)animated;
+ (void)pushURL:(NSURL *)url query:(NSDictionary *)query animated:(BOOL)animated replace:(BOOL)replace;
+ (void)presentURL:(NSURL *)url animated:(BOOL)animated;
+ (void)presentURLString:(NSString *)urlString animated:(BOOL)animated;
+ (void)presentURL:(NSURL *)url query:(NSDictionary *)query animated:(BOOL)animated;
+ (void)presentURLString:(NSString *)urlString query:(NSDictionary *)query animated:(BOOL)animated;
+ (void)presentURL:(NSURL *)url animated:(BOOL)animated withNavigationClass:(Class)clazz;
+ (void)presentURLString:(NSString *)urlString animated:(BOOL)animated withNavigationClass:(Class)clazz;
+ (void)presentURL:(NSURL *)url query:(NSDictionary *)query animated:(BOOL)animated withNavigationClass:(Class)clazz;
+ (void)presentURLString:(NSString *)urlString query:(NSDictionary *)query animated:(BOOL)animated withNavigationClass:(Class)clazz;
@end
================================================
FILE: Pod/Classes/Extend/URLManager/URLManager.m
================================================
//
// URLManager.m
// rssreader
//
// Created by zhuchao on 15/3/6.
// Copyright (c) 2015年 zhuchao. All rights reserved.
//
#import "URLManager.h"
@implementation URLManager
+ (URLManager *)shareInstance{
static dispatch_once_t predicate = 0;
static id sharedInstance = nil;
dispatch_once(&predicate, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
+(void)loadConfigFromPlist:(NSString *)plistPath{
[URLManager shareInstance].config = [NSDictionary dictionaryWithContentsOfFile:plistPath];
}
+ (void)pushURLString:(NSString *)urlString animated:(BOOL)animated{
UIViewController *viewController = [UIViewController initFromString:urlString fromConfig:[URLManager shareInstance].config];
[URLNavigation pushViewController:viewController animated:animated];
}
+ (void)pushURL:(NSURL *)url animated:(BOOL)animated{
UIViewController *viewController = [UIViewController initFromURL:url fromConfig:[URLManager shareInstance].config];
[URLNavigation pushViewController:viewController animated:animated];
}
+ (void)pushURLString:(NSString *)urlString animated:(BOOL)animated replace:(BOOL)replace{
UIViewController *viewController = [UIViewController initFromString:urlString fromConfig:[URLManager shareInstance].config];
[URLNavigation pushViewController:viewController animated:YES replace:replace];
}
+ (void)pushURL:(NSURL *)url animated:(BOOL)animated replace:(BOOL)replace{
UIViewController *viewController = [UIViewController initFromURL:url fromConfig:[URLManager shareInstance].config];
[URLNavigation pushViewController:viewController animated:animated replace:replace];
}
+ (void)presentURLString:(NSString *)urlString animated:(BOOL)animated{
UIViewController *viewController = [UIViewController initFromString:urlString fromConfig:[URLManager shareInstance].config];
[URLNavigation presentViewController:viewController animated:animated];
}
+ (void)presentURL:(NSURL *)url animated:(BOOL)animated{
UIViewController *viewController = [UIViewController initFromURL:url fromConfig:[URLManager shareInstance].config];
[URLNavigation presentViewController:viewController animated:animated];
}
+ (void)presentURLString:(NSString *)urlString query:(NSDictionary *)query animated:(BOOL)animated{
UIViewController *viewController = [UIViewController initFromString:urlString withQuery:query fromConfig:[URLManager shareInstance].config];
[URLNavigation presentViewController:viewController animated:animated];
}
+ (void)presentURL:(NSURL *)url query:(NSDictionary *)query animated:(BOOL)animated{
UIViewController *viewController = [UIViewController initFromURL:url withQuery:query fromConfig:[URLManager shareInstance].config];
[URLNavigation presentViewController:viewController animated:animated];
}
+ (void)pushURL:(NSURL *)url query:(NSDictionary *)query animated:(BOOL)animated{
UIViewController *viewController = [UIViewController initFromURL:url withQuery:query fromConfig:[URLManager shareInstance].config];
[URLNavigation pushViewController:viewController animated:animated];
}
+ (void)pushURL:(NSURL *)url query:(NSDictionary *)query animated:(BOOL)animated replace:(BOOL)replace{
UIViewController *viewController = [UIViewController initFromURL:url withQuery:query fromConfig:[URLManager shareInstance].config];
[URLNavigation pushViewController:viewController animated:animated replace:replace];
}
+ (void)pushURLString:(NSString *)urlString query:(NSDictionary *)query animated:(BOOL)animated{
UIViewController *viewController = [UIViewController initFromString:urlString withQuery:query fromConfig:[URLManager shareInstance].config];
[URLNavigation pushViewController:viewController animated:animated];
}
+ (void)pushURLString:(NSString *)urlString query:(NSDictionary *)query animated:(BOOL)animated replace:(BOOL)replace{
UIViewController *viewController = [UIViewController initFromString:urlString withQuery:query fromConfig:[URLManager shareInstance].config];
[URLNavigation pushViewController:viewController animated:animated replace:replace];
}
+ (void)presentURL:(NSURL *)url animated:(BOOL)animated withNavigationClass:(Class)clazz{
UIViewController *viewController = [UIViewController initFromURL:url fromConfig:[URLManager shareInstance].config];
UINavigationController *nav = [[clazz alloc]initWithRootViewController:viewController];
[URLNavigation presentViewController:nav animated:animated];
}
+ (void)presentURL:(NSURL *)url query:(NSDictionary *)query animated:(BOOL)animated withNavigationClass:(Class)clazz{
UIViewController *viewController = [UIViewController initFromURL:url withQuery:query fromConfig:[URLManager shareInstance].config];
UINavigationController *nav = [[clazz alloc]initWithRootViewController:viewController];
[URLNavigation presentViewController:nav animated:animated];
}
+ (void)presentURLString:(NSString *)urlString animated:(BOOL)animated withNavigationClass:(Class)clazz{
UIViewController *viewController = [UIViewController initFromString:urlString fromConfig:[URLManager shareInstance].config];
if ([clazz isSubclassOfClass:[UINavigationController class]]) {
UINavigationController *nav = [[clazz alloc]initWithRootViewController:viewController];
[URLNavigation presentViewController:nav animated:animated];
}
}
+ (void)presentURLString:(NSString *)urlString query:(NSDictionary *)query animated:(BOOL)animated withNavigationClass:(Class)clazz{
UIViewController *viewController = [UIViewController initFromString:urlString withQuery:query fromConfig:[URLManager shareInstance].config];
if ([clazz isSubclassOfClass:[UINavigationController class]]) {
UINavigationController *nav = [[clazz alloc]initWithRootViewController:viewController];
[URLNavigation presentViewController:nav animated:animated];
}
}
@end
================================================
FILE: Pod/Classes/Extend/URLManager/URLNavigation.h
================================================
//
// HKNavigation.h
// Hoko
//
// Created by Hoko, S.A. on 23/07/14.
// Copyright (c) 2015 Hoko, S.A. All rights reserved.
//
#import
/**
* HKNavigation is a helper class which allows you to push, present and set view
* controllers taking basis on your view controller hierararchy. This only takes
* account UITabBarControllers, UINavigationControllers and Modal View Controllers
* in order to traverse the hierarchy.
*
* WARNING: If you have custom navigation you should use your own methods to push and present
* view controllers, this is only a helper class for common navigation based on Apple's default
* view controller hierarchies.
*
*/
@interface URLNavigation : NSObject
/**
* setRootViewController: changes the root view controller of the AppDelegate's window.
*
* @param viewController Your view controller (or hierarchy of).
*/
+ (void)setRootViewController:(UIViewController *)viewController;
/**
* pushViewController:animated: pushes a view controller inside a navigation controller.
* If your viewController is a navigation controller it replaces the rootViewController,
* otherwise it tries to push the viewController if the current view controller is a
* UINavigationController, otherwise it creates it before pushing.
*
* @param viewController Your view controller.
* @param animated If you choose to animate the pushing of the viewController.
*/
+ (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
/**
* pushViewController:animated:replace: pushes a view controller inside a navigation controller.
* If your viewController is a navigation controller it replaces the rootViewController,
* otherwise it tries to push the viewController if the current view controller is a
* UINavigationController, otherwise it creates it before pushing.
* The replace parameter locates the current view controller and replaces it if it is of
* the same class as the viewController parameter being passed, this exists to avoid
* two of the same view controller in a row.
*
* @param viewController Your view controller.
* @param animated If you choose to animate the pushing of the viewController.
*/
+ (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated replace:(BOOL)replace;
/**
* presentViewController:animated: presents a view controller as a modal view controller,
* taking basis on the current view controller to present from.
*
* @param viewController Your view controller.
* @param animated If you choose to animate the presenting of the viewController.
*/
+ (void)presentViewController:(UIViewController *)viewController animated:(BOOL)animated;
+(void)dismissCurrentAnimated:(BOOL)animated;
+(UIViewController*)currentViewController;
+(UINavigationController*)currentNavigationViewController;
@end
================================================
FILE: Pod/Classes/Extend/URLManager/URLNavigation.m
================================================
//
// HKObserver.m
// Hoko
//
// Created by Hoko, S.A. on 23/07/14.
// Copyright (c) 2015 Hoko, S.A. All rights reserved.
//
#import "URLNavigation.h"
@implementation URLNavigation
#pragma mark - Singleton
+ (instancetype)shareInstance{
static dispatch_once_t predicate = 0;
static id sharedInstance = nil;
dispatch_once(&predicate, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
#pragma mark - Public Method
+ (void)setRootViewController:(UIViewController *)viewController
{
[URLNavigation shareInstance].applicationDelegate.window.rootViewController = viewController;
}
+ (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
[self pushViewController:viewController animated:animated replace:NO];
}
+ (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated replace:(BOOL)replace
{
// Check if viewController is a UINavigationController
if([viewController isKindOfClass:[UINavigationController class]])
[URLNavigation setRootViewController:viewController];
else {
// Check if a UINavigationController exists in the view controllers stack.
UINavigationController *navigationController = [URLNavigation shareInstance].currentNavigationViewController;
if (navigationController) {
// In case it should replace, look for the last UIViewController on the UINavigationController, if it's of the same class, replace it with a new one.
if (replace && [navigationController.viewControllers.lastObject isKindOfClass:[viewController class]]) {
NSArray *viewControllers = [navigationController.viewControllers subarrayWithRange:NSMakeRange(0, navigationController.viewControllers.count-1)];
[navigationController setViewControllers:[viewControllers arrayByAddingObject:viewController] animated:animated];
} else {
// Otherwise just push the new viewController
[navigationController pushViewController:viewController animated:animated];
}
} else {
// Create a new UINavigationController to use with the viewController
navigationController = [[UINavigationController alloc]initWithRootViewController:viewController];
[URLNavigation shareInstance].applicationDelegate.window.rootViewController = navigationController;
}
}
}
+ (void)presentViewController:(UIViewController *)viewController animated:(BOOL)animated
{
// Look for the currentViewController
UIViewController *currentViewController = [[URLNavigation shareInstance] currentViewController];
if (currentViewController) {
// Present viewController from currentViewcontroller
[currentViewController presentViewController:viewController animated:animated completion:nil];
} else {
// Otherwise set the window rootViewController
[URLNavigation shareInstance].applicationDelegate.window.rootViewController = viewController;
}
}
+(void)dismissCurrentAnimated:(BOOL)animated{
UIViewController *currentViewController = [[URLNavigation shareInstance] currentViewController];
if(currentViewController){
if(currentViewController.navigationController){
if(currentViewController.navigationController.viewControllers.count == 1){
if(currentViewController.presentingViewController){
[currentViewController dismissViewControllerAnimated:animated completion:nil];
}
}else{
[currentViewController.navigationController popViewControllerAnimated:animated];
}
}else if(currentViewController.presentingViewController){
[currentViewController dismissViewControllerAnimated:animated completion:nil];
}
}
}
#pragma mark - Private Methods
- (id)applicationDelegate
{
return [UIApplication sharedApplication].delegate;
}
+(UIViewController*)currentViewController{
return [[URLNavigation shareInstance] currentViewController];
}
- (UIViewController*)currentViewController
{
UIViewController* rootViewController = self.applicationDelegate.window.rootViewController;
return [self currentViewControllerFrom:rootViewController];
}
+(UIViewController*)currentNavigationViewController{
return [[URLNavigation shareInstance] currentNavigationViewController];
}
- (UINavigationController*)currentNavigationViewController
{
UIViewController* currentViewController = self.currentViewController;
return currentViewController.navigationController;
}
- (UIViewController*)currentViewControllerFrom:(UIViewController*)viewController
{
if ([viewController isKindOfClass:[UINavigationController class]]) {
UINavigationController* navigationController = (UINavigationController *)viewController;
return [self currentViewControllerFrom:navigationController.viewControllers.lastObject];
} else if([viewController isKindOfClass:[UITabBarController class]]) {
UITabBarController* tabBarController = (UITabBarController *)viewController;
return [self currentViewControllerFrom:tabBarController.selectedViewController];
} else if(viewController.presentedViewController != nil) {
return [self currentViewControllerFrom:viewController.presentedViewController];
} else {
return viewController;
}
}
@end
================================================
FILE: Pod/Classes/Private/Gumbo/attribute.c
================================================
// Copyright 2010 Google Inc. All Rights Reserved.
//
// Licensed 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.
//
// Author: jdtang@google.com (Jonathan Tang)
#include "attribute.h"
#include
#include
#include
#include
#include "util.h"
struct GumboInternalParser;
GumboAttribute* gumbo_get_attribute(
const GumboVector* attributes, const char* name) {
for (int i = 0; i < attributes->length; ++i) {
GumboAttribute* attr = attributes->data[i];
if (!strcasecmp(attr->name, name)) {
return attr;
}
}
return NULL;
}
void gumbo_destroy_attribute(
struct GumboInternalParser* parser, GumboAttribute* attribute) {
gumbo_parser_deallocate(parser, (void*) attribute->name);
gumbo_parser_deallocate(parser, (void*) attribute->value);
gumbo_parser_deallocate(parser, (void*) attribute);
}
================================================
FILE: Pod/Classes/Private/Gumbo/attribute.h
================================================
// Copyright 2010 Google Inc. All Rights Reserved.
//
// Licensed 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.
//
// Author: jdtang@google.com (Jonathan Tang)
#ifndef GUMBO_ATTRIBUTE_H_
#define GUMBO_ATTRIBUTE_H_
#include "gumbo.h"
#ifdef __cplusplus
extern "C" {
#endif
struct GumboInternalParser;
// Release the memory used for an GumboAttribute, including the attribute
// itself.
void gumbo_destroy_attribute(
struct GumboInternalParser* parser, GumboAttribute* attribute);
#ifdef __cplusplus
}
#endif
#endif // GUMBO_ATTRIBUTE_H_
================================================
FILE: Pod/Classes/Private/Gumbo/char_ref.c
================================================
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed 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.
//
// Author: jdtang@google.com (Jonathan Tang)
#include "char_ref.h"
#include
#include
#include
#include // Only for debug assertions at present.
#include "error.h"
#include "string_piece.h"
#include "utf8.h"
#include "util.h"
struct GumboInternalParser;
const int kGumboNoChar = -1;
// Table of named character entities, and functions for looking them up.
// http://www.whatwg.org/specs/web-apps/current-work/multipage/named-character-references.html
//
// TODO(jdtang): I'd thought of using more efficient means of this, eg. binary
// searching the table (which can only be done if we know for sure that there's
// enough room in the buffer for our memcmps, otherwise we need to fall back on
// linear search) or compiling the list of named entities to a Ragel state
// machine. But I'll start with the simple approach and optimize only if
// profiling calls for it. The one concession to efficiency is to store the
// length of the entity with it, so that we don't need to run a strlen to detect
// potential buffer overflows.
typedef struct {
const char* name;
size_t length;
OneOrTwoCodepoints codepoints;
} NamedCharRef;
#define CHAR_REF(name, codepoint) { name, sizeof(name) - 1, { codepoint, -1 } }
#define MULTI_CHAR_REF(name, code_point, code_point2) \
{ name, sizeof(name) - 1, { code_point, code_point2 } }
// Versions with the semicolon must come before versions without the semicolon,
// otherwise they'll match the invalid name first and record a parse error.
// TODO(jdtang): Replace with a FSM that'll do longest-match-first and probably
// give better performance besides.
static const NamedCharRef kNamedEntities[] = {
CHAR_REF("AElig", 0xc6),
CHAR_REF("AMP;", 0x26),
CHAR_REF("AMP", 0x26),
CHAR_REF("Aacute;", 0xc1),
CHAR_REF("Aacute", 0xc1),
CHAR_REF("Abreve;", 0x0102),
CHAR_REF("Acirc;", 0xc2),
CHAR_REF("Acirc", 0xc2),
CHAR_REF("Acy;", 0x0410),
CHAR_REF("Afr;", 0x0001d504),
CHAR_REF("Agrave", 0xc0),
CHAR_REF("Agrave;", 0xc0),
CHAR_REF("Alpha;", 0x0391),
CHAR_REF("Amacr;", 0x0100),
CHAR_REF("And;", 0x2a53),
CHAR_REF("Aogon;", 0x0104),
CHAR_REF("Aopf;", 0x0001d538),
CHAR_REF("ApplyFunction;", 0x2061),
CHAR_REF("Aring;", 0xc5),
CHAR_REF("Aring", 0xc5),
CHAR_REF("Ascr;", 0x0001d49c),
CHAR_REF("Assign;", 0x2254),
CHAR_REF("Atilde;", 0xc3),
CHAR_REF("Atilde", 0xc3),
CHAR_REF("Auml;", 0xc4),
CHAR_REF("Auml", 0xc4),
CHAR_REF("Backslash;", 0x2216),
CHAR_REF("Barv;", 0x2ae7),
CHAR_REF("Barwed;", 0x2306),
CHAR_REF("Bcy;", 0x0411),
CHAR_REF("Because;", 0x2235),
CHAR_REF("Bernoullis;", 0x212c),
CHAR_REF("Beta;", 0x0392),
CHAR_REF("Bfr;", 0x0001d505),
CHAR_REF("Bopf;", 0x0001d539),
CHAR_REF("Breve;", 0x02d8),
CHAR_REF("Bscr;", 0x212c),
CHAR_REF("Bumpeq;", 0x224e),
CHAR_REF("CHcy;", 0x0427),
CHAR_REF("COPY;", 0xa9),
CHAR_REF("COPY", 0xa9),
CHAR_REF("Cacute;", 0x0106),
CHAR_REF("Cap;", 0x22d2),
CHAR_REF("CapitalDifferentialD;", 0x2145),
CHAR_REF("Cayleys;", 0x212d),
CHAR_REF("Ccaron;", 0x010c),
CHAR_REF("Ccedil;", 0xc7),
CHAR_REF("Ccedil", 0xc7),
CHAR_REF("Ccirc;", 0x0108),
CHAR_REF("Cconint;", 0x2230),
CHAR_REF("Cdot;", 0x010a),
CHAR_REF("Cedilla;", 0xb8),
CHAR_REF("CenterDot;", 0xb7),
CHAR_REF("Cfr;", 0x212d),
CHAR_REF("Chi;", 0x03a7),
CHAR_REF("CircleDot;", 0x2299),
CHAR_REF("CircleMinus;", 0x2296),
CHAR_REF("CirclePlus;", 0x2295),
CHAR_REF("CircleTimes;", 0x2297),
CHAR_REF("ClockwiseContourIntegral;", 0x2232),
CHAR_REF("CloseCurlyDoubleQuote;", 0x201d),
CHAR_REF("CloseCurlyQuote;", 0x2019),
CHAR_REF("Colon;", 0x2237),
CHAR_REF("Colone;", 0x2a74),
CHAR_REF("Congruent;", 0x2261),
CHAR_REF("Conint;", 0x222f),
CHAR_REF("ContourIntegral;", 0x222e),
CHAR_REF("Copf;", 0x2102),
CHAR_REF("Coproduct;", 0x2210),
CHAR_REF("CounterClockwiseContourIntegral;", 0x2233),
CHAR_REF("Cross;", 0x2a2f),
CHAR_REF("Cscr;", 0x0001d49e),
CHAR_REF("Cup;", 0x22d3),
CHAR_REF("CupCap;", 0x224d),
CHAR_REF("DD;", 0x2145),
CHAR_REF("DDotrahd;", 0x2911),
CHAR_REF("DJcy;", 0x0402),
CHAR_REF("DScy;", 0x0405),
CHAR_REF("DZcy;", 0x040f),
CHAR_REF("Dagger;", 0x2021),
CHAR_REF("Darr;", 0x21a1),
CHAR_REF("Dashv;", 0x2ae4),
CHAR_REF("Dcaron;", 0x010e),
CHAR_REF("Dcy;", 0x0414),
CHAR_REF("Del;", 0x2207),
CHAR_REF("Delta;", 0x0394),
CHAR_REF("Dfr;", 0x0001d507),
CHAR_REF("DiacriticalAcute;", 0xb4),
CHAR_REF("DiacriticalDot;", 0x02d9),
CHAR_REF("DiacriticalDoubleAcute;", 0x02dd),
CHAR_REF("DiacriticalGrave;", 0x60),
CHAR_REF("DiacriticalTilde;", 0x02dc),
CHAR_REF("Diamond;", 0x22c4),
CHAR_REF("DifferentialD;", 0x2146),
CHAR_REF("Dopf;", 0x0001d53b),
CHAR_REF("Dot;", 0xa8),
CHAR_REF("DotDot;", 0x20dc),
CHAR_REF("DotEqual;", 0x2250),
CHAR_REF("DoubleContourIntegral;", 0x222f),
CHAR_REF("DoubleDot;", 0xa8),
CHAR_REF("DoubleDownArrow;", 0x21d3),
CHAR_REF("DoubleLeftArrow;", 0x21d0),
CHAR_REF("DoubleLeftRightArrow;", 0x21d4),
CHAR_REF("DoubleLeftTee;", 0x2ae4),
CHAR_REF("DoubleLongLeftArrow;", 0x27f8),
CHAR_REF("DoubleLongLeftRightArrow;", 0x27fa),
CHAR_REF("DoubleLongRightArrow;", 0x27f9),
CHAR_REF("DoubleRightArrow;", 0x21d2),
CHAR_REF("DoubleRightTee;", 0x22a8),
CHAR_REF("DoubleUpArrow;", 0x21d1),
CHAR_REF("DoubleUpDownArrow;", 0x21d5),
CHAR_REF("DoubleVerticalBar;", 0x2225),
CHAR_REF("DownArrow;", 0x2193),
CHAR_REF("DownArrowBar;", 0x2913),
CHAR_REF("DownArrowUpArrow;", 0x21f5),
CHAR_REF("DownBreve;", 0x0311),
CHAR_REF("DownLeftRightVector;", 0x2950),
CHAR_REF("DownLeftTeeVector;", 0x295e),
CHAR_REF("DownLeftVector;", 0x21bd),
CHAR_REF("DownLeftVectorBar;", 0x2956),
CHAR_REF("DownRightTeeVector;", 0x295f),
CHAR_REF("DownRightVector;", 0x21c1),
CHAR_REF("DownRightVectorBar;", 0x2957),
CHAR_REF("DownTee;", 0x22a4),
CHAR_REF("DownTeeArrow;", 0x21a7),
CHAR_REF("Downarrow;", 0x21d3),
CHAR_REF("Dscr;", 0x0001d49f),
CHAR_REF("Dstrok;", 0x0110),
CHAR_REF("ENG;", 0x014a),
CHAR_REF("ETH;", 0xd0),
CHAR_REF("ETH", 0xd0),
CHAR_REF("Eacute;", 0xc9),
CHAR_REF("Eacute", 0xc9),
CHAR_REF("Ecaron;", 0x011a),
CHAR_REF("Ecirc;", 0xca),
CHAR_REF("Ecirc", 0xca),
CHAR_REF("Ecy;", 0x042d),
CHAR_REF("Edot;", 0x0116),
CHAR_REF("Efr;", 0x0001d508),
CHAR_REF("Egrave;", 0xc8),
CHAR_REF("Egrave", 0xc8),
CHAR_REF("Element;", 0x2208),
CHAR_REF("Emacr;", 0x0112),
CHAR_REF("EmptySmallSquare;", 0x25fb),
CHAR_REF("EmptyVerySmallSquare;", 0x25ab),
CHAR_REF("Eogon;", 0x0118),
CHAR_REF("Eopf;", 0x0001d53c),
CHAR_REF("Epsilon;", 0x0395),
CHAR_REF("Equal;", 0x2a75),
CHAR_REF("EqualTilde;", 0x2242),
CHAR_REF("Equilibrium;", 0x21cc),
CHAR_REF("Escr;", 0x2130),
CHAR_REF("Esim;", 0x2a73),
CHAR_REF("Eta;", 0x0397),
CHAR_REF("Euml;", 0xcb),
CHAR_REF("Euml", 0xcb),
CHAR_REF("Exists;", 0x2203),
CHAR_REF("ExponentialE;", 0x2147),
CHAR_REF("Fcy;", 0x0424),
CHAR_REF("Ffr;", 0x0001d509),
CHAR_REF("FilledSmallSquare;", 0x25fc),
CHAR_REF("FilledVerySmallSquare;", 0x25aa),
CHAR_REF("Fopf;", 0x0001d53d),
CHAR_REF("ForAll;", 0x2200),
CHAR_REF("Fouriertrf;", 0x2131),
CHAR_REF("Fscr;", 0x2131),
CHAR_REF("GJcy;", 0x0403),
CHAR_REF("GT;", 0x3e),
CHAR_REF("GT", 0x3e),
CHAR_REF("Gamma;", 0x0393),
CHAR_REF("Gammad;", 0x03dc),
CHAR_REF("Gbreve;", 0x011e),
CHAR_REF("Gcedil;", 0x0122),
CHAR_REF("Gcirc;", 0x011c),
CHAR_REF("Gcy;", 0x0413),
CHAR_REF("Gdot;", 0x0120),
CHAR_REF("Gfr;", 0x0001d50a),
CHAR_REF("Gg;", 0x22d9),
CHAR_REF("Gopf;", 0x0001d53e),
CHAR_REF("GreaterEqual;", 0x2265),
CHAR_REF("GreaterEqualLess;", 0x22db),
CHAR_REF("GreaterFullEqual;", 0x2267),
CHAR_REF("GreaterGreater;", 0x2aa2),
CHAR_REF("GreaterLess;", 0x2277),
CHAR_REF("GreaterSlantEqual;", 0x2a7e),
CHAR_REF("GreaterTilde;", 0x2273),
CHAR_REF("Gscr;", 0x0001d4a2),
CHAR_REF("Gt;", 0x226b),
CHAR_REF("HARDcy;", 0x042a),
CHAR_REF("Hacek;", 0x02c7),
CHAR_REF("Hat;", 0x5e),
CHAR_REF("Hcirc;", 0x0124),
CHAR_REF("Hfr;", 0x210c),
CHAR_REF("HilbertSpace;", 0x210b),
CHAR_REF("Hopf;", 0x210d),
CHAR_REF("HorizontalLine;", 0x2500),
CHAR_REF("Hscr;", 0x210b),
CHAR_REF("Hstrok;", 0x0126),
CHAR_REF("HumpDownHump;", 0x224e),
CHAR_REF("HumpEqual;", 0x224f),
CHAR_REF("IEcy;", 0x0415),
CHAR_REF("IJlig;", 0x0132),
CHAR_REF("IOcy;", 0x0401),
CHAR_REF("Iacute;", 0xcd),
CHAR_REF("Iacute", 0xcd),
CHAR_REF("Icirc;", 0xce),
CHAR_REF("Icirc", 0xce),
CHAR_REF("Icy;", 0x0418),
CHAR_REF("Idot;", 0x0130),
CHAR_REF("Ifr;", 0x2111),
CHAR_REF("Igrave;", 0xcc),
CHAR_REF("Igrave", 0xcc),
CHAR_REF("Im;", 0x2111),
CHAR_REF("Imacr;", 0x012a),
CHAR_REF("ImaginaryI;", 0x2148),
CHAR_REF("Implies;", 0x21d2),
CHAR_REF("Int;", 0x222c),
CHAR_REF("Integral;", 0x222b),
CHAR_REF("Intersection;", 0x22c2),
CHAR_REF("InvisibleComma;", 0x2063),
CHAR_REF("InvisibleTimes;", 0x2062),
CHAR_REF("Iogon;", 0x012e),
CHAR_REF("Iopf;", 0x0001d540),
CHAR_REF("Iota;", 0x0399),
CHAR_REF("Iscr;", 0x2110),
CHAR_REF("Itilde;", 0x0128),
CHAR_REF("Iukcy;", 0x0406),
CHAR_REF("Iuml;", 0xcf),
CHAR_REF("Iuml", 0xcf),
CHAR_REF("Jcirc;", 0x0134),
CHAR_REF("Jcy;", 0x0419),
CHAR_REF("Jfr;", 0x0001d50d),
CHAR_REF("Jopf;", 0x0001d541),
CHAR_REF("Jscr;", 0x0001d4a5),
CHAR_REF("Jsercy;", 0x0408),
CHAR_REF("Jukcy;", 0x0404),
CHAR_REF("KHcy;", 0x0425),
CHAR_REF("KJcy;", 0x040c),
CHAR_REF("Kappa;", 0x039a),
CHAR_REF("Kcedil;", 0x0136),
CHAR_REF("Kcy;", 0x041a),
CHAR_REF("Kfr;", 0x0001d50e),
CHAR_REF("Kopf;", 0x0001d542),
CHAR_REF("Kscr;", 0x0001d4a6),
CHAR_REF("LJcy;", 0x0409),
CHAR_REF("LT;", 0x3c),
CHAR_REF("LT", 0x3c),
CHAR_REF("Lacute;", 0x0139),
CHAR_REF("Lambda;", 0x039b),
CHAR_REF("Lang;", 0x27ea),
CHAR_REF("Laplacetrf;", 0x2112),
CHAR_REF("Larr;", 0x219e),
CHAR_REF("Lcaron;", 0x013d),
CHAR_REF("Lcedil;", 0x013b),
CHAR_REF("Lcy;", 0x041b),
CHAR_REF("LeftAngleBracket;", 0x27e8),
CHAR_REF("LeftArrow;", 0x2190),
CHAR_REF("LeftArrowBar;", 0x21e4),
CHAR_REF("LeftArrowRightArrow;", 0x21c6),
CHAR_REF("LeftCeiling;", 0x2308),
CHAR_REF("LeftDoubleBracket;", 0x27e6),
CHAR_REF("LeftDownTeeVector;", 0x2961),
CHAR_REF("LeftDownVector;", 0x21c3),
CHAR_REF("LeftDownVectorBar;", 0x2959),
CHAR_REF("LeftFloor;", 0x230a),
CHAR_REF("LeftRightArrow;", 0x2194),
CHAR_REF("LeftRightVector;", 0x294e),
CHAR_REF("LeftTee;", 0x22a3),
CHAR_REF("LeftTeeArrow;", 0x21a4),
CHAR_REF("LeftTeeVector;", 0x295a),
CHAR_REF("LeftTriangle;", 0x22b2),
CHAR_REF("LeftTriangleBar;", 0x29cf),
CHAR_REF("LeftTriangleEqual;", 0x22b4),
CHAR_REF("LeftUpDownVector;", 0x2951),
CHAR_REF("LeftUpTeeVector;", 0x2960),
CHAR_REF("LeftUpVector;", 0x21bf),
CHAR_REF("LeftUpVectorBar;", 0x2958),
CHAR_REF("LeftVector;", 0x21bc),
CHAR_REF("LeftVectorBar;", 0x2952),
CHAR_REF("Leftarrow;", 0x21d0),
CHAR_REF("Leftrightarrow;", 0x21d4),
CHAR_REF("LessEqualGreater;", 0x22da),
CHAR_REF("LessFullEqual;", 0x2266),
CHAR_REF("LessGreater;", 0x2276),
CHAR_REF("LessLess;", 0x2aa1),
CHAR_REF("LessSlantEqual;", 0x2a7d),
CHAR_REF("LessTilde;", 0x2272),
CHAR_REF("Lfr;", 0x0001d50f),
CHAR_REF("Ll;", 0x22d8),
CHAR_REF("Lleftarrow;", 0x21da),
CHAR_REF("Lmidot;", 0x013f),
CHAR_REF("LongLeftArrow;", 0x27f5),
CHAR_REF("LongLeftRightArrow;", 0x27f7),
CHAR_REF("LongRightArrow;", 0x27f6),
CHAR_REF("Longleftarrow;", 0x27f8),
CHAR_REF("Longleftrightarrow;", 0x27fa),
CHAR_REF("Longrightarrow;", 0x27f9),
CHAR_REF("Lopf;", 0x0001d543),
CHAR_REF("LowerLeftArrow;", 0x2199),
CHAR_REF("LowerRightArrow;", 0x2198),
CHAR_REF("Lscr;", 0x2112),
CHAR_REF("Lsh;", 0x21b0),
CHAR_REF("Lstrok;", 0x0141),
CHAR_REF("Lt;", 0x226a),
CHAR_REF("Map;", 0x2905),
CHAR_REF("Mcy;", 0x041c),
CHAR_REF("MediumSpace;", 0x205f),
CHAR_REF("Mellintrf;", 0x2133),
CHAR_REF("Mfr;", 0x0001d510),
CHAR_REF("MinusPlus;", 0x2213),
CHAR_REF("Mopf;", 0x0001d544),
CHAR_REF("Mscr;", 0x2133),
CHAR_REF("Mu;", 0x039c),
CHAR_REF("NJcy;", 0x040a),
CHAR_REF("Nacute;", 0x0143),
CHAR_REF("Ncaron;", 0x0147),
CHAR_REF("Ncedil;", 0x0145),
CHAR_REF("Ncy;", 0x041d),
CHAR_REF("NegativeMediumSpace;", 0x200b),
CHAR_REF("NegativeThickSpace;", 0x200b),
CHAR_REF("NegativeThinSpace;", 0x200b),
CHAR_REF("NegativeVeryThinSpace;", 0x200b),
CHAR_REF("NestedGreaterGreater;", 0x226b),
CHAR_REF("NestedLessLess;", 0x226a),
CHAR_REF("NewLine;", 0x0a),
CHAR_REF("Nfr;", 0x0001d511),
CHAR_REF("NoBreak;", 0x2060),
CHAR_REF("NonBreakingSpace;", 0xa0),
CHAR_REF("Nopf;", 0x2115),
CHAR_REF("Not;", 0x2aec),
CHAR_REF("NotCongruent;", 0x2262),
CHAR_REF("NotCupCap;", 0x226d),
CHAR_REF("NotDoubleVerticalBar;", 0x2226),
CHAR_REF("NotElement;", 0x2209),
CHAR_REF("NotEqual;", 0x2260),
MULTI_CHAR_REF("NotEqualTilde;", 0x2242, 0x0338),
CHAR_REF("NotExists;", 0x2204),
CHAR_REF("NotGreater;", 0x226f),
CHAR_REF("NotGreaterEqual;", 0x2271),
MULTI_CHAR_REF("NotGreaterFullEqual;", 0x2267, 0x0338),
MULTI_CHAR_REF("NotGreaterGreater;", 0x226b, 0x0338),
CHAR_REF("NotGreaterLess;", 0x2279),
MULTI_CHAR_REF("NotGreaterSlantEqual;", 0x2a7e, 0x0338),
CHAR_REF("NotGreaterTilde;", 0x2275),
MULTI_CHAR_REF("NotHumpDownHump;", 0x224e, 0x0338),
MULTI_CHAR_REF("NotHumpEqual;", 0x224f, 0x0338),
CHAR_REF("NotLeftTriangle;", 0x22ea),
MULTI_CHAR_REF("NotLeftTriangleBar;", 0x29cf, 0x0338),
CHAR_REF("NotLeftTriangleEqual;", 0x22ec),
CHAR_REF("NotLess;", 0x226e),
CHAR_REF("NotLessEqual;", 0x2270),
CHAR_REF("NotLessGreater;", 0x2278),
MULTI_CHAR_REF("NotLessLess;", 0x226a, 0x0338),
MULTI_CHAR_REF("NotLessSlantEqual;", 0x2a7d, 0x0338),
CHAR_REF("NotLessTilde;", 0x2274),
MULTI_CHAR_REF("NotNestedGreaterGreater;", 0x2aa2, 0x0338),
MULTI_CHAR_REF("NotNestedLessLess;", 0x2aa1, 0x0338),
CHAR_REF("NotPrecedes;", 0x2280),
MULTI_CHAR_REF("NotPrecedesEqual;", 0x2aaf, 0x0338),
CHAR_REF("NotPrecedesSlantEqual;", 0x22e0),
CHAR_REF("NotReverseElement;", 0x220c),
CHAR_REF("NotRightTriangle;", 0x22eb),
MULTI_CHAR_REF("NotRightTriangleBar;", 0x29d0, 0x0338),
CHAR_REF("NotRightTriangleEqual;", 0x22ed),
MULTI_CHAR_REF("NotSquareSubset;", 0x228f, 0x0338),
CHAR_REF("NotSquareSubsetEqual;", 0x22e2),
MULTI_CHAR_REF("NotSquareSuperset;", 0x2290, 0x0338),
CHAR_REF("NotSquareSupersetEqual;", 0x22e3),
MULTI_CHAR_REF("NotSubset;", 0x2282, 0x20d2),
CHAR_REF("NotSubsetEqual;", 0x2288),
CHAR_REF("NotSucceeds;", 0x2281),
MULTI_CHAR_REF("NotSucceedsEqual;", 0x2ab0, 0x0338),
CHAR_REF("NotSucceedsSlantEqual;", 0x22e1),
MULTI_CHAR_REF("NotSucceedsTilde;", 0x227f, 0x0338),
MULTI_CHAR_REF("NotSuperset;", 0x2283, 0x20d2),
CHAR_REF("NotSupersetEqual;", 0x2289),
CHAR_REF("NotTilde;", 0x2241),
CHAR_REF("NotTildeEqual;", 0x2244),
CHAR_REF("NotTildeFullEqual;", 0x2247),
CHAR_REF("NotTildeTilde;", 0x2249),
CHAR_REF("NotVerticalBar;", 0x2224),
CHAR_REF("Nscr;", 0x0001d4a9),
CHAR_REF("Ntilde;", 0xd1),
CHAR_REF("Ntilde", 0xd1),
CHAR_REF("Nu;", 0x039d),
CHAR_REF("OElig;", 0x0152),
CHAR_REF("Oacute;", 0xd3),
CHAR_REF("Oacute", 0xd3),
CHAR_REF("Ocirc;", 0xd4),
CHAR_REF("Ocirc", 0xd4),
CHAR_REF("Ocy;", 0x041e),
CHAR_REF("Odblac;", 0x0150),
CHAR_REF("Ofr;", 0x0001d512),
CHAR_REF("Ograve;", 0xd2),
CHAR_REF("Ograve", 0xd2),
CHAR_REF("Omacr;", 0x014c),
CHAR_REF("Omega;", 0x03a9),
CHAR_REF("Omicron;", 0x039f),
CHAR_REF("Oopf;", 0x0001d546),
CHAR_REF("OpenCurlyDoubleQuote;", 0x201c),
CHAR_REF("OpenCurlyQuote;", 0x2018),
CHAR_REF("Or;", 0x2a54),
CHAR_REF("Oscr;", 0x0001d4aa),
CHAR_REF("Oslash;", 0xd8),
CHAR_REF("Oslash", 0xd8),
CHAR_REF("Otilde;", 0xd5),
CHAR_REF("Otilde", 0xd5),
CHAR_REF("Otimes;", 0x2a37),
CHAR_REF("Ouml", 0xd6),
CHAR_REF("Ouml;", 0xd6),
CHAR_REF("OverBar;", 0x203e),
CHAR_REF("OverBrace;", 0x23de),
CHAR_REF("OverBracket;", 0x23b4),
CHAR_REF("OverParenthesis;", 0x23dc),
CHAR_REF("PartialD;", 0x2202),
CHAR_REF("Pcy;", 0x041f),
CHAR_REF("Pfr;", 0x0001d513),
CHAR_REF("Phi;", 0x03a6),
CHAR_REF("Pi;", 0x03a0),
CHAR_REF("PlusMinus;", 0xb1),
CHAR_REF("Poincareplane;", 0x210c),
CHAR_REF("Popf;", 0x2119),
CHAR_REF("Pr;", 0x2abb),
CHAR_REF("Precedes;", 0x227a),
CHAR_REF("PrecedesEqual;", 0x2aaf),
CHAR_REF("PrecedesSlantEqual;", 0x227c),
CHAR_REF("PrecedesTilde;", 0x227e),
CHAR_REF("Prime;", 0x2033),
CHAR_REF("Product;", 0x220f),
CHAR_REF("Proportion;", 0x2237),
CHAR_REF("Proportional;", 0x221d),
CHAR_REF("Pscr;", 0x0001d4ab),
CHAR_REF("Psi;", 0x03a8),
CHAR_REF("QUOT;", 0x22),
CHAR_REF("QUOT", 0x22),
CHAR_REF("Qfr;", 0x0001d514),
CHAR_REF("Qopf;", 0x211a),
CHAR_REF("Qscr;", 0x0001d4ac),
CHAR_REF("RBarr;", 0x2910),
CHAR_REF("REG;", 0xae),
CHAR_REF("REG", 0xae),
CHAR_REF("Racute;", 0x0154),
CHAR_REF("Rang;", 0x27eb),
CHAR_REF("Rarr;", 0x21a0),
CHAR_REF("Rarrtl;", 0x2916),
CHAR_REF("Rcaron;", 0x0158),
CHAR_REF("Rcedil;", 0x0156),
CHAR_REF("Rcy;", 0x0420),
CHAR_REF("Re;", 0x211c),
CHAR_REF("ReverseElement;", 0x220b),
CHAR_REF("ReverseEquilibrium;", 0x21cb),
CHAR_REF("ReverseUpEquilibrium;", 0x296f),
CHAR_REF("Rfr;", 0x211c),
CHAR_REF("Rho;", 0x03a1),
CHAR_REF("RightAngleBracket;", 0x27e9),
CHAR_REF("RightArrow;", 0x2192),
CHAR_REF("RightArrowBar;", 0x21e5),
CHAR_REF("RightArrowLeftArrow;", 0x21c4),
CHAR_REF("RightCeiling;", 0x2309),
CHAR_REF("RightDoubleBracket;", 0x27e7),
CHAR_REF("RightDownTeeVector;", 0x295d),
CHAR_REF("RightDownVector;", 0x21c2),
CHAR_REF("RightDownVectorBar;", 0x2955),
CHAR_REF("RightFloor;", 0x230b),
CHAR_REF("RightTee;", 0x22a2),
CHAR_REF("RightTeeArrow;", 0x21a6),
CHAR_REF("RightTeeVector;", 0x295b),
CHAR_REF("RightTriangle;", 0x22b3),
CHAR_REF("RightTriangleBar;", 0x29d0),
CHAR_REF("RightTriangleEqual;", 0x22b5),
CHAR_REF("RightUpDownVector;", 0x294f),
CHAR_REF("RightUpTeeVector;", 0x295c),
CHAR_REF("RightUpVector;", 0x21be),
CHAR_REF("RightUpVectorBar;", 0x2954),
CHAR_REF("RightVector;", 0x21c0),
CHAR_REF("RightVectorBar;", 0x2953),
CHAR_REF("Rightarrow;", 0x21d2),
CHAR_REF("Ropf;", 0x211d),
CHAR_REF("RoundImplies;", 0x2970),
CHAR_REF("Rrightarrow;", 0x21db),
CHAR_REF("Rscr;", 0x211b),
CHAR_REF("Rsh;", 0x21b1),
CHAR_REF("RuleDelayed;", 0x29f4),
CHAR_REF("SHCHcy;", 0x0429),
CHAR_REF("SHcy;", 0x0428),
CHAR_REF("SOFTcy;", 0x042c),
CHAR_REF("Sacute;", 0x015a),
CHAR_REF("Sc;", 0x2abc),
CHAR_REF("Scaron;", 0x0160),
CHAR_REF("Scedil;", 0x015e),
CHAR_REF("Scirc;", 0x015c),
CHAR_REF("Scy;", 0x0421),
CHAR_REF("Sfr;", 0x0001d516),
CHAR_REF("ShortDownArrow;", 0x2193),
CHAR_REF("ShortLeftArrow;", 0x2190),
CHAR_REF("ShortRightArrow;", 0x2192),
CHAR_REF("ShortUpArrow;", 0x2191),
CHAR_REF("Sigma;", 0x03a3),
CHAR_REF("SmallCircle;", 0x2218),
CHAR_REF("Sopf;", 0x0001d54a),
CHAR_REF("Sqrt;", 0x221a),
CHAR_REF("Square;", 0x25a1),
CHAR_REF("SquareIntersection;", 0x2293),
CHAR_REF("SquareSubset;", 0x228f),
CHAR_REF("SquareSubsetEqual;", 0x2291),
CHAR_REF("SquareSuperset;", 0x2290),
CHAR_REF("SquareSupersetEqual;", 0x2292),
CHAR_REF("SquareUnion;", 0x2294),
CHAR_REF("Sscr;", 0x0001d4ae),
CHAR_REF("Star;", 0x22c6),
CHAR_REF("Sub;", 0x22d0),
CHAR_REF("Subset;", 0x22d0),
CHAR_REF("SubsetEqual;", 0x2286),
CHAR_REF("Succeeds;", 0x227b),
CHAR_REF("SucceedsEqual;", 0x2ab0),
CHAR_REF("SucceedsSlantEqual;", 0x227d),
CHAR_REF("SucceedsTilde;", 0x227f),
CHAR_REF("SuchThat;", 0x220b),
CHAR_REF("Sum;", 0x2211),
CHAR_REF("Sup;", 0x22d1),
CHAR_REF("Superset;", 0x2283),
CHAR_REF("SupersetEqual;", 0x2287),
CHAR_REF("Supset;", 0x22d1),
CHAR_REF("THORN;", 0xde),
CHAR_REF("THORN", 0xde),
CHAR_REF("TRADE;", 0x2122),
CHAR_REF("TSHcy;", 0x040b),
CHAR_REF("TScy;", 0x0426),
CHAR_REF("Tab;", 0x09),
CHAR_REF("Tau;", 0x03a4),
CHAR_REF("Tcaron;", 0x0164),
CHAR_REF("Tcedil;", 0x0162),
CHAR_REF("Tcy;", 0x0422),
CHAR_REF("Tfr;", 0x0001d517),
CHAR_REF("Therefore;", 0x2234),
CHAR_REF("Theta;", 0x0398),
MULTI_CHAR_REF("ThickSpace;", 0x205f, 0x200a),
CHAR_REF("ThinSpace;", 0x2009),
CHAR_REF("Tilde;", 0x223c),
CHAR_REF("TildeEqual;", 0x2243),
CHAR_REF("TildeFullEqual;", 0x2245),
CHAR_REF("TildeTilde;", 0x2248),
CHAR_REF("Topf;", 0x0001d54b),
CHAR_REF("TripleDot;", 0x20db),
CHAR_REF("Tscr;", 0x0001d4af),
CHAR_REF("Tstrok;", 0x0166),
CHAR_REF("Uacute;", 0xda),
CHAR_REF("Uacute", 0xda),
CHAR_REF("Uarr;", 0x219f),
CHAR_REF("Uarrocir;", 0x2949),
CHAR_REF("Ubrcy;", 0x040e),
CHAR_REF("Ubreve;", 0x016c),
CHAR_REF("Ucirc;", 0xdb),
CHAR_REF("Ucirc", 0xdb),
CHAR_REF("Ucy;", 0x0423),
CHAR_REF("Udblac;", 0x0170),
CHAR_REF("Ufr;", 0x0001d518),
CHAR_REF("Ugrave;", 0xd9),
CHAR_REF("Ugrave", 0xd9),
CHAR_REF("Umacr;", 0x016a),
CHAR_REF("UnderBar;", 0x5f),
CHAR_REF("UnderBrace;", 0x23df),
CHAR_REF("UnderBracket;", 0x23b5),
CHAR_REF("UnderParenthesis;", 0x23dd),
CHAR_REF("Union;", 0x22c3),
CHAR_REF("UnionPlus;", 0x228e),
CHAR_REF("Uogon;", 0x0172),
CHAR_REF("Uopf;", 0x0001d54c),
CHAR_REF("UpArrow;", 0x2191),
CHAR_REF("UpArrowBar;", 0x2912),
CHAR_REF("UpArrowDownArrow;", 0x21c5),
CHAR_REF("UpDownArrow;", 0x2195),
CHAR_REF("UpEquilibrium;", 0x296e),
CHAR_REF("UpTee;", 0x22a5),
CHAR_REF("UpTeeArrow;", 0x21a5),
CHAR_REF("Uparrow;", 0x21d1),
CHAR_REF("Updownarrow;", 0x21d5),
CHAR_REF("UpperLeftArrow;", 0x2196),
CHAR_REF("UpperRightArrow;", 0x2197),
CHAR_REF("Upsi;", 0x03d2),
CHAR_REF("Upsilon;", 0x03a5),
CHAR_REF("Uring;", 0x016e),
CHAR_REF("Uscr;", 0x0001d4b0),
CHAR_REF("Utilde;", 0x0168),
CHAR_REF("Uuml;", 0xdc),
CHAR_REF("Uuml", 0xdc),
CHAR_REF("VDash;", 0x22ab),
CHAR_REF("Vbar;", 0x2aeb),
CHAR_REF("Vcy;", 0x0412),
CHAR_REF("Vdash;", 0x22a9),
CHAR_REF("Vdashl;", 0x2ae6),
CHAR_REF("Vee;", 0x22c1),
CHAR_REF("Verbar;", 0x2016),
CHAR_REF("Vert;", 0x2016),
CHAR_REF("VerticalBar;", 0x2223),
CHAR_REF("VerticalLine;", 0x7c),
CHAR_REF("VerticalSeparator;", 0x2758),
CHAR_REF("VerticalTilde;", 0x2240),
CHAR_REF("VeryThinSpace;", 0x200a),
CHAR_REF("Vfr;", 0x0001d519),
CHAR_REF("Vopf;", 0x0001d54d),
CHAR_REF("Vscr;", 0x0001d4b1),
CHAR_REF("Vvdash;", 0x22aa),
CHAR_REF("Wcirc;", 0x0174),
CHAR_REF("Wedge;", 0x22c0),
CHAR_REF("Wfr;", 0x0001d51a),
CHAR_REF("Wopf;", 0x0001d54e),
CHAR_REF("Wscr;", 0x0001d4b2),
CHAR_REF("Xfr;", 0x0001d51b),
CHAR_REF("Xi;", 0x039e),
CHAR_REF("Xopf;", 0x0001d54f),
CHAR_REF("Xscr;", 0x0001d4b3),
CHAR_REF("YAcy;", 0x042f),
CHAR_REF("YIcy;", 0x0407),
CHAR_REF("YUcy;", 0x042e),
CHAR_REF("Yacute", 0xdd),
CHAR_REF("Yacute;", 0xdd),
CHAR_REF("Ycirc;", 0x0176),
CHAR_REF("Ycy;", 0x042b),
CHAR_REF("Yfr;", 0x0001d51c),
CHAR_REF("Yopf;", 0x0001d550),
CHAR_REF("Yscr;", 0x0001d4b4),
CHAR_REF("Yuml;", 0x0178),
CHAR_REF("ZHcy;", 0x0416),
CHAR_REF("Zacute;", 0x0179),
CHAR_REF("Zcaron;", 0x017d),
CHAR_REF("Zcy;", 0x0417),
CHAR_REF("Zdot;", 0x017b),
CHAR_REF("ZeroWidthSpace;", 0x200b),
CHAR_REF("Zeta;", 0x0396),
CHAR_REF("Zfr;", 0x2128),
CHAR_REF("Zopf;", 0x2124),
CHAR_REF("Zscr;", 0x0001d4b5),
CHAR_REF("aacute;", 0xe1),
CHAR_REF("aacute", 0xe1),
CHAR_REF("abreve;", 0x0103),
CHAR_REF("ac;", 0x223e),
MULTI_CHAR_REF("acE;", 0x223e, 0x0333),
CHAR_REF("acd;", 0x223f),
CHAR_REF("acirc;", 0xe2),
CHAR_REF("acirc", 0xe2),
CHAR_REF("acute;", 0xb4),
CHAR_REF("acute", 0xb4),
CHAR_REF("acy;", 0x0430),
CHAR_REF("aelig;", 0xe6),
CHAR_REF("aelig", 0xe6),
CHAR_REF("af;", 0x2061),
CHAR_REF("afr;", 0x0001d51e),
CHAR_REF("agrave;", 0xe0),
CHAR_REF("agrave", 0xe0),
CHAR_REF("alefsym;", 0x2135),
CHAR_REF("aleph;", 0x2135),
CHAR_REF("alpha;", 0x03b1),
CHAR_REF("amacr;", 0x0101),
CHAR_REF("amalg;", 0x2a3f),
CHAR_REF("amp;", 0x26),
CHAR_REF("amp", 0x26),
CHAR_REF("and;", 0x2227),
CHAR_REF("andand;", 0x2a55),
CHAR_REF("andd;", 0x2a5c),
CHAR_REF("andslope;", 0x2a58),
CHAR_REF("andv;", 0x2a5a),
CHAR_REF("ang;", 0x2220),
CHAR_REF("ange;", 0x29a4),
CHAR_REF("angle;", 0x2220),
CHAR_REF("angmsd;", 0x2221),
CHAR_REF("angmsdaa;", 0x29a8),
CHAR_REF("angmsdab;", 0x29a9),
CHAR_REF("angmsdac;", 0x29aa),
CHAR_REF("angmsdad;", 0x29ab),
CHAR_REF("angmsdae;", 0x29ac),
CHAR_REF("angmsdaf;", 0x29ad),
CHAR_REF("angmsdag;", 0x29ae),
CHAR_REF("angmsdah;", 0x29af),
CHAR_REF("angrt;", 0x221f),
CHAR_REF("angrtvb;", 0x22be),
CHAR_REF("angrtvbd;", 0x299d),
CHAR_REF("angsph;", 0x2222),
CHAR_REF("angst;", 0xc5),
CHAR_REF("angzarr;", 0x237c),
CHAR_REF("aogon;", 0x0105),
CHAR_REF("aopf;", 0x0001d552),
CHAR_REF("ap;", 0x2248),
CHAR_REF("apE;", 0x2a70),
CHAR_REF("apacir;", 0x2a6f),
CHAR_REF("ape;", 0x224a),
CHAR_REF("apid;", 0x224b),
CHAR_REF("apos;", 0x27),
CHAR_REF("approx;", 0x2248),
CHAR_REF("approxeq;", 0x224a),
CHAR_REF("aring;", 0xe5),
CHAR_REF("aring", 0xe5),
CHAR_REF("ascr;", 0x0001d4b6),
CHAR_REF("ast;", 0x2a),
CHAR_REF("asymp;", 0x2248),
CHAR_REF("asympeq;", 0x224d),
CHAR_REF("atilde;", 0xe3),
CHAR_REF("atilde", 0xe3),
CHAR_REF("auml;", 0xe4),
CHAR_REF("auml", 0xe4),
CHAR_REF("awconint;", 0x2233),
CHAR_REF("awint;", 0x2a11),
CHAR_REF("bNot;", 0x2aed),
CHAR_REF("backcong;", 0x224c),
CHAR_REF("backepsilon;", 0x03f6),
CHAR_REF("backprime;", 0x2035),
CHAR_REF("backsim;", 0x223d),
CHAR_REF("backsimeq;", 0x22cd),
CHAR_REF("barvee;", 0x22bd),
CHAR_REF("barwed;", 0x2305),
CHAR_REF("barwedge;", 0x2305),
CHAR_REF("bbrk;", 0x23b5),
CHAR_REF("bbrktbrk;", 0x23b6),
CHAR_REF("bcong;", 0x224c),
CHAR_REF("bcy;", 0x0431),
CHAR_REF("bdquo;", 0x201e),
CHAR_REF("becaus;", 0x2235),
CHAR_REF("because;", 0x2235),
CHAR_REF("bemptyv;", 0x29b0),
CHAR_REF("bepsi;", 0x03f6),
CHAR_REF("bernou;", 0x212c),
CHAR_REF("beta;", 0x03b2),
CHAR_REF("beth;", 0x2136),
CHAR_REF("between;", 0x226c),
CHAR_REF("bfr;", 0x0001d51f),
CHAR_REF("bigcap;", 0x22c2),
CHAR_REF("bigcirc;", 0x25ef),
CHAR_REF("bigcup;", 0x22c3),
CHAR_REF("bigodot;", 0x2a00),
CHAR_REF("bigoplus;", 0x2a01),
CHAR_REF("bigotimes;", 0x2a02),
CHAR_REF("bigsqcup;", 0x2a06),
CHAR_REF("bigstar;", 0x2605),
CHAR_REF("bigtriangledown;", 0x25bd),
CHAR_REF("bigtriangleup;", 0x25b3),
CHAR_REF("biguplus;", 0x2a04),
CHAR_REF("bigvee;", 0x22c1),
CHAR_REF("bigwedge;", 0x22c0),
CHAR_REF("bkarow;", 0x290d),
CHAR_REF("blacklozenge;", 0x29eb),
CHAR_REF("blacksquare;", 0x25aa),
CHAR_REF("blacktriangle;", 0x25b4),
CHAR_REF("blacktriangledown;", 0x25be),
CHAR_REF("blacktriangleleft;", 0x25c2),
CHAR_REF("blacktriangleright;", 0x25b8),
CHAR_REF("blank;", 0x2423),
CHAR_REF("blk12;", 0x2592),
CHAR_REF("blk14;", 0x2591),
CHAR_REF("blk34;", 0x2593),
CHAR_REF("block;", 0x2588),
MULTI_CHAR_REF("bne;", 0x3d, 0x20e5),
MULTI_CHAR_REF("bnequiv;", 0x2261, 0x20e5),
CHAR_REF("bnot;", 0x2310),
CHAR_REF("bopf;", 0x0001d553),
CHAR_REF("bot;", 0x22a5),
CHAR_REF("bottom;", 0x22a5),
CHAR_REF("bowtie;", 0x22c8),
CHAR_REF("boxDL;", 0x2557),
CHAR_REF("boxDR;", 0x2554),
CHAR_REF("boxDl;", 0x2556),
CHAR_REF("boxDr;", 0x2553),
CHAR_REF("boxH;", 0x2550),
CHAR_REF("boxHD;", 0x2566),
CHAR_REF("boxHU;", 0x2569),
CHAR_REF("boxHd;", 0x2564),
CHAR_REF("boxHu;", 0x2567),
CHAR_REF("boxUL;", 0x255d),
CHAR_REF("boxUR;", 0x255a),
CHAR_REF("boxUl;", 0x255c),
CHAR_REF("boxUr;", 0x2559),
CHAR_REF("boxV;", 0x2551),
CHAR_REF("boxVH;", 0x256c),
CHAR_REF("boxVL;", 0x2563),
CHAR_REF("boxVR;", 0x2560),
CHAR_REF("boxVh;", 0x256b),
CHAR_REF("boxVl;", 0x2562),
CHAR_REF("boxVr;", 0x255f),
CHAR_REF("boxbox;", 0x29c9),
CHAR_REF("boxdL;", 0x2555),
CHAR_REF("boxdR;", 0x2552),
CHAR_REF("boxdl;", 0x2510),
CHAR_REF("boxdr;", 0x250c),
CHAR_REF("boxh;", 0x2500),
CHAR_REF("boxhD;", 0x2565),
CHAR_REF("boxhU;", 0x2568),
CHAR_REF("boxhd;", 0x252c),
CHAR_REF("boxhu;", 0x2534),
CHAR_REF("boxminus;", 0x229f),
CHAR_REF("boxplus;", 0x229e),
CHAR_REF("boxtimes;", 0x22a0),
CHAR_REF("boxuL;", 0x255b),
CHAR_REF("boxuR;", 0x2558),
CHAR_REF("boxul;", 0x2518),
CHAR_REF("boxur;", 0x2514),
CHAR_REF("boxv;", 0x2502),
CHAR_REF("boxvH;", 0x256a),
CHAR_REF("boxvL;", 0x2561),
CHAR_REF("boxvR;", 0x255e),
CHAR_REF("boxvh;", 0x253c),
CHAR_REF("boxvl;", 0x2524),
CHAR_REF("boxvr;", 0x251c),
CHAR_REF("bprime;", 0x2035),
CHAR_REF("breve;", 0x02d8),
CHAR_REF("brvbar;", 0xa6),
CHAR_REF("brvbar", 0xa6),
CHAR_REF("bscr;", 0x0001d4b7),
CHAR_REF("bsemi;", 0x204f),
CHAR_REF("bsim;", 0x223d),
CHAR_REF("bsime;", 0x22cd),
CHAR_REF("bsol;", 0x5c),
CHAR_REF("bsolb;", 0x29c5),
CHAR_REF("bsolhsub;", 0x27c8),
CHAR_REF("bull;", 0x2022),
CHAR_REF("bullet;", 0x2022),
CHAR_REF("bump;", 0x224e),
CHAR_REF("bumpE;", 0x2aae),
CHAR_REF("bumpe;", 0x224f),
CHAR_REF("bumpeq;", 0x224f),
CHAR_REF("cacute;", 0x0107),
CHAR_REF("cap;", 0x2229),
CHAR_REF("capand;", 0x2a44),
CHAR_REF("capbrcup;", 0x2a49),
CHAR_REF("capcap;", 0x2a4b),
CHAR_REF("capcup;", 0x2a47),
CHAR_REF("capdot;", 0x2a40),
MULTI_CHAR_REF("caps;", 0x2229, 0xfe00),
CHAR_REF("caret;", 0x2041),
CHAR_REF("caron;", 0x02c7),
CHAR_REF("ccaps;", 0x2a4d),
CHAR_REF("ccaron;", 0x010d),
CHAR_REF("ccedil;", 0xe7),
CHAR_REF("ccedil", 0xe7),
CHAR_REF("ccirc;", 0x0109),
CHAR_REF("ccups;", 0x2a4c),
CHAR_REF("ccupssm;", 0x2a50),
CHAR_REF("cdot;", 0x010b),
CHAR_REF("cedil;", 0xb8),
CHAR_REF("cedil", 0xb8),
CHAR_REF("cemptyv;", 0x29b2),
CHAR_REF("cent;", 0xa2),
CHAR_REF("cent", 0xa2),
CHAR_REF("centerdot;", 0xb7),
CHAR_REF("cfr;", 0x0001d520),
CHAR_REF("chcy;", 0x0447),
CHAR_REF("check;", 0x2713),
CHAR_REF("checkmark;", 0x2713),
CHAR_REF("chi;", 0x03c7),
CHAR_REF("cir;", 0x25cb),
CHAR_REF("cirE;", 0x29c3),
CHAR_REF("circ;", 0x02c6),
CHAR_REF("circeq;", 0x2257),
CHAR_REF("circlearrowleft;", 0x21ba),
CHAR_REF("circlearrowright;", 0x21bb),
CHAR_REF("circledR;", 0xae),
CHAR_REF("circledS;", 0x24c8),
CHAR_REF("circledast;", 0x229b),
CHAR_REF("circledcirc;", 0x229a),
CHAR_REF("circleddash;", 0x229d),
CHAR_REF("cire;", 0x2257),
CHAR_REF("cirfnint;", 0x2a10),
CHAR_REF("cirmid;", 0x2aef),
CHAR_REF("cirscir;", 0x29c2),
CHAR_REF("clubs;", 0x2663),
CHAR_REF("clubsuit;", 0x2663),
CHAR_REF("colon;", 0x3a),
CHAR_REF("colone;", 0x2254),
CHAR_REF("coloneq;", 0x2254),
CHAR_REF("comma;", 0x2c),
CHAR_REF("commat;", 0x40),
CHAR_REF("comp;", 0x2201),
CHAR_REF("compfn;", 0x2218),
CHAR_REF("complement;", 0x2201),
CHAR_REF("complexes;", 0x2102),
CHAR_REF("cong;", 0x2245),
CHAR_REF("congdot;", 0x2a6d),
CHAR_REF("conint;", 0x222e),
CHAR_REF("copf;", 0x0001d554),
CHAR_REF("coprod;", 0x2210),
CHAR_REF("copy;", 0xa9),
CHAR_REF("copy", 0xa9),
CHAR_REF("copysr;", 0x2117),
CHAR_REF("crarr;", 0x21b5),
CHAR_REF("cross;", 0x2717),
CHAR_REF("cscr;", 0x0001d4b8),
CHAR_REF("csub;", 0x2acf),
CHAR_REF("csube;", 0x2ad1),
CHAR_REF("csup;", 0x2ad0),
CHAR_REF("csupe;", 0x2ad2),
CHAR_REF("ctdot;", 0x22ef),
CHAR_REF("cudarrl;", 0x2938),
CHAR_REF("cudarrr;", 0x2935),
CHAR_REF("cuepr;", 0x22de),
CHAR_REF("cuesc;", 0x22df),
CHAR_REF("cularr;", 0x21b6),
CHAR_REF("cularrp;", 0x293d),
CHAR_REF("cup;", 0x222a),
CHAR_REF("cupbrcap;", 0x2a48),
CHAR_REF("cupcap;", 0x2a46),
CHAR_REF("cupcup;", 0x2a4a),
CHAR_REF("cupdot;", 0x228d),
CHAR_REF("cupor;", 0x2a45),
MULTI_CHAR_REF("cups;", 0x222a, 0xfe00),
CHAR_REF("curarr;", 0x21b7),
CHAR_REF("curarrm;", 0x293c),
CHAR_REF("curlyeqprec;", 0x22de),
CHAR_REF("curlyeqsucc;", 0x22df),
CHAR_REF("curlyvee;", 0x22ce),
CHAR_REF("curlywedge;", 0x22cf),
CHAR_REF("curren;", 0xa4),
CHAR_REF("curren", 0xa4),
CHAR_REF("curvearrowleft;", 0x21b6),
CHAR_REF("curvearrowright;", 0x21b7),
CHAR_REF("cuvee;", 0x22ce),
CHAR_REF("cuwed;", 0x22cf),
CHAR_REF("cwconint;", 0x2232),
CHAR_REF("cwint;", 0x2231),
CHAR_REF("cylcty;", 0x232d),
CHAR_REF("dArr;", 0x21d3),
CHAR_REF("dHar;", 0x2965),
CHAR_REF("dagger;", 0x2020),
CHAR_REF("daleth;", 0x2138),
CHAR_REF("darr;", 0x2193),
CHAR_REF("dash;", 0x2010),
CHAR_REF("dashv;", 0x22a3),
CHAR_REF("dbkarow;", 0x290f),
CHAR_REF("dblac;", 0x02dd),
CHAR_REF("dcaron;", 0x010f),
CHAR_REF("dcy;", 0x0434),
CHAR_REF("dd;", 0x2146),
CHAR_REF("ddagger;", 0x2021),
CHAR_REF("ddarr;", 0x21ca),
CHAR_REF("ddotseq;", 0x2a77),
CHAR_REF("deg;", 0xb0),
CHAR_REF("deg", 0xb0),
CHAR_REF("delta;", 0x03b4),
CHAR_REF("demptyv;", 0x29b1),
CHAR_REF("dfisht;", 0x297f),
CHAR_REF("dfr;", 0x0001d521),
CHAR_REF("dharl;", 0x21c3),
CHAR_REF("dharr;", 0x21c2),
CHAR_REF("diam;", 0x22c4),
CHAR_REF("diamond;", 0x22c4),
CHAR_REF("diamondsuit;", 0x2666),
CHAR_REF("diams;", 0x2666),
CHAR_REF("die;", 0xa8),
CHAR_REF("digamma;", 0x03dd),
CHAR_REF("disin;", 0x22f2),
CHAR_REF("div;", 0xf7),
CHAR_REF("divide;", 0xf7),
CHAR_REF("divide", 0xf7),
CHAR_REF("divideontimes;", 0x22c7),
CHAR_REF("divonx;", 0x22c7),
CHAR_REF("djcy;", 0x0452),
CHAR_REF("dlcorn;", 0x231e),
CHAR_REF("dlcrop;", 0x230d),
CHAR_REF("dollar;", 0x24),
CHAR_REF("dopf;", 0x0001d555),
CHAR_REF("dot;", 0x02d9),
CHAR_REF("doteq;", 0x2250),
CHAR_REF("doteqdot;", 0x2251),
CHAR_REF("dotminus;", 0x2238),
CHAR_REF("dotplus;", 0x2214),
CHAR_REF("dotsquare;", 0x22a1),
CHAR_REF("doublebarwedge;", 0x2306),
CHAR_REF("downarrow;", 0x2193),
CHAR_REF("downdownarrows;", 0x21ca),
CHAR_REF("downharpoonleft;", 0x21c3),
CHAR_REF("downharpoonright;", 0x21c2),
CHAR_REF("drbkarow;", 0x2910),
CHAR_REF("drcorn;", 0x231f),
CHAR_REF("drcrop;", 0x230c),
CHAR_REF("dscr;", 0x0001d4b9),
CHAR_REF("dscy;", 0x0455),
CHAR_REF("dsol;", 0x29f6),
CHAR_REF("dstrok;", 0x0111),
CHAR_REF("dtdot;", 0x22f1),
CHAR_REF("dtri;", 0x25bf),
CHAR_REF("dtrif;", 0x25be),
CHAR_REF("duarr;", 0x21f5),
CHAR_REF("duhar;", 0x296f),
CHAR_REF("dwangle;", 0x29a6),
CHAR_REF("dzcy;", 0x045f),
CHAR_REF("dzigrarr;", 0x27ff),
CHAR_REF("eDDot;", 0x2a77),
CHAR_REF("eDot;", 0x2251),
CHAR_REF("eacute;", 0xe9),
CHAR_REF("eacute", 0xe9),
CHAR_REF("easter;", 0x2a6e),
CHAR_REF("ecaron;", 0x011b),
CHAR_REF("ecir;", 0x2256),
CHAR_REF("ecirc;", 0xea),
CHAR_REF("ecirc", 0xea),
CHAR_REF("ecolon;", 0x2255),
CHAR_REF("ecy;", 0x044d),
CHAR_REF("edot;", 0x0117),
CHAR_REF("ee;", 0x2147),
CHAR_REF("efDot;", 0x2252),
CHAR_REF("efr;", 0x0001d522),
CHAR_REF("eg;", 0x2a9a),
CHAR_REF("egrave;", 0xe8),
CHAR_REF("egrave", 0xe8),
CHAR_REF("egs;", 0x2a96),
CHAR_REF("egsdot;", 0x2a98),
CHAR_REF("el;", 0x2a99),
CHAR_REF("elinters;", 0x23e7),
CHAR_REF("ell;", 0x2113),
CHAR_REF("els;", 0x2a95),
CHAR_REF("elsdot;", 0x2a97),
CHAR_REF("emacr;", 0x0113),
CHAR_REF("empty;", 0x2205),
CHAR_REF("emptyset;", 0x2205),
CHAR_REF("emptyv;", 0x2205),
CHAR_REF("emsp13;", 0x2004),
CHAR_REF("emsp14;", 0x2005),
CHAR_REF("emsp;", 0x2003),
CHAR_REF("eng;", 0x014b),
CHAR_REF("ensp;", 0x2002),
CHAR_REF("eogon;", 0x0119),
CHAR_REF("eopf;", 0x0001d556),
CHAR_REF("epar;", 0x22d5),
CHAR_REF("eparsl;", 0x29e3),
CHAR_REF("eplus;", 0x2a71),
CHAR_REF("epsi;", 0x03b5),
CHAR_REF("epsilon;", 0x03b5),
CHAR_REF("epsiv;", 0x03f5),
CHAR_REF("eqcirc;", 0x2256),
CHAR_REF("eqcolon;", 0x2255),
CHAR_REF("eqsim;", 0x2242),
CHAR_REF("eqslantgtr;", 0x2a96),
CHAR_REF("eqslantless;", 0x2a95),
CHAR_REF("equals;", 0x3d),
CHAR_REF("equest;", 0x225f),
CHAR_REF("equiv;", 0x2261),
CHAR_REF("equivDD;", 0x2a78),
CHAR_REF("eqvparsl;", 0x29e5),
CHAR_REF("erDot;", 0x2253),
CHAR_REF("erarr;", 0x2971),
CHAR_REF("escr;", 0x212f),
CHAR_REF("esdot;", 0x2250),
CHAR_REF("esim;", 0x2242),
CHAR_REF("eta;", 0x03b7),
CHAR_REF("eth;", 0xf0),
CHAR_REF("eth", 0xf0),
CHAR_REF("euml;", 0xeb),
CHAR_REF("euml", 0xeb),
CHAR_REF("euro;", 0x20ac),
CHAR_REF("excl;", 0x21),
CHAR_REF("exist;", 0x2203),
CHAR_REF("expectation;", 0x2130),
CHAR_REF("exponentiale;", 0x2147),
CHAR_REF("fallingdotseq;", 0x2252),
CHAR_REF("fcy;", 0x0444),
CHAR_REF("female;", 0x2640),
CHAR_REF("ffilig;", 0xfb03),
CHAR_REF("fflig;", 0xfb00),
CHAR_REF("ffllig;", 0xfb04),
CHAR_REF("ffr;", 0x0001d523),
CHAR_REF("filig;", 0xfb01),
MULTI_CHAR_REF("fjlig;", 0x66, 0x6a),
CHAR_REF("flat;", 0x266d),
CHAR_REF("fllig;", 0xfb02),
CHAR_REF("fltns;", 0x25b1),
CHAR_REF("fnof;", 0x0192),
CHAR_REF("fopf;", 0x0001d557),
CHAR_REF("forall;", 0x2200),
CHAR_REF("fork;", 0x22d4),
CHAR_REF("forkv;", 0x2ad9),
CHAR_REF("fpartint;", 0x2a0d),
CHAR_REF("frac12", 0xbd),
CHAR_REF("frac12;", 0xbd),
CHAR_REF("frac13;", 0x2153),
CHAR_REF("frac14", 0xbc),
CHAR_REF("frac14;", 0xbc),
CHAR_REF("frac15;", 0x2155),
CHAR_REF("frac16;", 0x2159),
CHAR_REF("frac18;", 0x215b),
CHAR_REF("frac23;", 0x2154),
CHAR_REF("frac25;", 0x2156),
CHAR_REF("frac34", 0xbe),
CHAR_REF("frac34;", 0xbe),
CHAR_REF("frac35;", 0x2157),
CHAR_REF("frac38;", 0x215c),
CHAR_REF("frac45;", 0x2158),
CHAR_REF("frac56;", 0x215a),
CHAR_REF("frac58;", 0x215d),
CHAR_REF("frac78;", 0x215e),
CHAR_REF("frasl;", 0x2044),
CHAR_REF("frown;", 0x2322),
CHAR_REF("fscr;", 0x0001d4bb),
CHAR_REF("gE;", 0x2267),
CHAR_REF("gEl;", 0x2a8c),
CHAR_REF("gacute;", 0x01f5),
CHAR_REF("gamma;", 0x03b3),
CHAR_REF("gammad;", 0x03dd),
CHAR_REF("gap;", 0x2a86),
CHAR_REF("gbreve;", 0x011f),
CHAR_REF("gcirc;", 0x011d),
CHAR_REF("gcy;", 0x0433),
CHAR_REF("gdot;", 0x0121),
CHAR_REF("ge;", 0x2265),
CHAR_REF("gel;", 0x22db),
CHAR_REF("geq;", 0x2265),
CHAR_REF("geqq;", 0x2267),
CHAR_REF("geqslant;", 0x2a7e),
CHAR_REF("ges;", 0x2a7e),
CHAR_REF("gescc;", 0x2aa9),
CHAR_REF("gesdot;", 0x2a80),
CHAR_REF("gesdoto;", 0x2a82),
CHAR_REF("gesdotol;", 0x2a84),
MULTI_CHAR_REF("gesl;", 0x22db, 0xfe00),
CHAR_REF("gesles;", 0x2a94),
CHAR_REF("gfr;", 0x0001d524),
CHAR_REF("gg;", 0x226b),
CHAR_REF("ggg;", 0x22d9),
CHAR_REF("gimel;", 0x2137),
CHAR_REF("gjcy;", 0x0453),
CHAR_REF("gl;", 0x2277),
CHAR_REF("glE;", 0x2a92),
CHAR_REF("gla;", 0x2aa5),
CHAR_REF("glj;", 0x2aa4),
CHAR_REF("gnE;", 0x2269),
CHAR_REF("gnap;", 0x2a8a),
CHAR_REF("gnapprox;", 0x2a8a),
CHAR_REF("gne;", 0x2a88),
CHAR_REF("gneq;", 0x2a88),
CHAR_REF("gneqq;", 0x2269),
CHAR_REF("gnsim;", 0x22e7),
CHAR_REF("gopf;", 0x0001d558),
CHAR_REF("grave;", 0x60),
CHAR_REF("gscr;", 0x210a),
CHAR_REF("gsim;", 0x2273),
CHAR_REF("gsime;", 0x2a8e),
CHAR_REF("gsiml;", 0x2a90),
CHAR_REF("gt;", 0x3e),
CHAR_REF("gt", 0x3e),
CHAR_REF("gtcc;", 0x2aa7),
CHAR_REF("gtcir;", 0x2a7a),
CHAR_REF("gtdot;", 0x22d7),
CHAR_REF("gtlPar;", 0x2995),
CHAR_REF("gtquest;", 0x2a7c),
CHAR_REF("gtrapprox;", 0x2a86),
CHAR_REF("gtrarr;", 0x2978),
CHAR_REF("gtrdot;", 0x22d7),
CHAR_REF("gtreqless;", 0x22db),
CHAR_REF("gtreqqless;", 0x2a8c),
CHAR_REF("gtrless;", 0x2277),
CHAR_REF("gtrsim;", 0x2273),
MULTI_CHAR_REF("gvertneqq;", 0x2269, 0xfe00),
MULTI_CHAR_REF("gvnE;", 0x2269, 0xfe00),
CHAR_REF("hArr;", 0x21d4),
CHAR_REF("hairsp;", 0x200a),
CHAR_REF("half;", 0xbd),
CHAR_REF("hamilt;", 0x210b),
CHAR_REF("hardcy;", 0x044a),
CHAR_REF("harr;", 0x2194),
CHAR_REF("harrcir;", 0x2948),
CHAR_REF("harrw;", 0x21ad),
CHAR_REF("hbar;", 0x210f),
CHAR_REF("hcirc;", 0x0125),
CHAR_REF("hearts;", 0x2665),
CHAR_REF("heartsuit;", 0x2665),
CHAR_REF("hellip;", 0x2026),
CHAR_REF("hercon;", 0x22b9),
CHAR_REF("hfr;", 0x0001d525),
CHAR_REF("hksearow;", 0x2925),
CHAR_REF("hkswarow;", 0x2926),
CHAR_REF("hoarr;", 0x21ff),
CHAR_REF("homtht;", 0x223b),
CHAR_REF("hookleftarrow;", 0x21a9),
CHAR_REF("hookrightarrow;", 0x21aa),
CHAR_REF("hopf;", 0x0001d559),
CHAR_REF("horbar;", 0x2015),
CHAR_REF("hscr;", 0x0001d4bd),
CHAR_REF("hslash;", 0x210f),
CHAR_REF("hstrok;", 0x0127),
CHAR_REF("hybull;", 0x2043),
CHAR_REF("hyphen;", 0x2010),
CHAR_REF("iacute;", 0xed),
CHAR_REF("iacute", 0xed),
CHAR_REF("ic;", 0x2063),
CHAR_REF("icirc;", 0xee),
CHAR_REF("icirc", 0xee),
CHAR_REF("icy;", 0x0438),
CHAR_REF("iecy;", 0x0435),
CHAR_REF("iexcl;", 0xa1),
CHAR_REF("iexcl", 0xa1),
CHAR_REF("iff;", 0x21d4),
CHAR_REF("ifr;", 0x0001d526),
CHAR_REF("igrave;", 0xec),
CHAR_REF("igrave", 0xec),
CHAR_REF("ii;", 0x2148),
CHAR_REF("iiiint;", 0x2a0c),
CHAR_REF("iiint;", 0x222d),
CHAR_REF("iinfin;", 0x29dc),
CHAR_REF("iiota;", 0x2129),
CHAR_REF("ijlig;", 0x0133),
CHAR_REF("imacr;", 0x012b),
CHAR_REF("image;", 0x2111),
CHAR_REF("imagline;", 0x2110),
CHAR_REF("imagpart;", 0x2111),
CHAR_REF("imath;", 0x0131),
CHAR_REF("imof;", 0x22b7),
CHAR_REF("imped;", 0x01b5),
CHAR_REF("in;", 0x2208),
CHAR_REF("incare;", 0x2105),
CHAR_REF("infin;", 0x221e),
CHAR_REF("infintie;", 0x29dd),
CHAR_REF("inodot;", 0x0131),
CHAR_REF("int;", 0x222b),
CHAR_REF("intcal;", 0x22ba),
CHAR_REF("integers;", 0x2124),
CHAR_REF("intercal;", 0x22ba),
CHAR_REF("intlarhk;", 0x2a17),
CHAR_REF("intprod;", 0x2a3c),
CHAR_REF("iocy;", 0x0451),
CHAR_REF("iogon;", 0x012f),
CHAR_REF("iopf;", 0x0001d55a),
CHAR_REF("iota;", 0x03b9),
CHAR_REF("iprod;", 0x2a3c),
CHAR_REF("iquest;", 0xbf),
CHAR_REF("iquest", 0xbf),
CHAR_REF("iscr;", 0x0001d4be),
CHAR_REF("isin;", 0x2208),
CHAR_REF("isinE;", 0x22f9),
CHAR_REF("isindot;", 0x22f5),
CHAR_REF("isins;", 0x22f4),
CHAR_REF("isinsv;", 0x22f3),
CHAR_REF("isinv;", 0x2208),
CHAR_REF("it;", 0x2062),
CHAR_REF("itilde;", 0x0129),
CHAR_REF("iukcy;", 0x0456),
CHAR_REF("iuml;", 0xef),
CHAR_REF("iuml", 0xef),
CHAR_REF("jcirc;", 0x0135),
CHAR_REF("jcy;", 0x0439),
CHAR_REF("jfr;", 0x0001d527),
CHAR_REF("jmath;", 0x0237),
CHAR_REF("jopf;", 0x0001d55b),
CHAR_REF("jscr;", 0x0001d4bf),
CHAR_REF("jsercy;", 0x0458),
CHAR_REF("jukcy;", 0x0454),
CHAR_REF("kappa;", 0x03ba),
CHAR_REF("kappav;", 0x03f0),
CHAR_REF("kcedil;", 0x0137),
CHAR_REF("kcy;", 0x043a),
CHAR_REF("kfr;", 0x0001d528),
CHAR_REF("kgreen;", 0x0138),
CHAR_REF("khcy;", 0x0445),
CHAR_REF("kjcy;", 0x045c),
CHAR_REF("kopf;", 0x0001d55c),
CHAR_REF("kscr;", 0x0001d4c0),
CHAR_REF("lAarr;", 0x21da),
CHAR_REF("lArr;", 0x21d0),
CHAR_REF("lAtail;", 0x291b),
CHAR_REF("lBarr;", 0x290e),
CHAR_REF("lE;", 0x2266),
CHAR_REF("lEg;", 0x2a8b),
CHAR_REF("lHar;", 0x2962),
CHAR_REF("lacute;", 0x013a),
CHAR_REF("laemptyv;", 0x29b4),
CHAR_REF("lagran;", 0x2112),
CHAR_REF("lambda;", 0x03bb),
CHAR_REF("lang;", 0x27e8),
CHAR_REF("langd;", 0x2991),
CHAR_REF("langle;", 0x27e8),
CHAR_REF("lap;", 0x2a85),
CHAR_REF("laquo;", 0xab),
CHAR_REF("laquo", 0xab),
CHAR_REF("larr;", 0x2190),
CHAR_REF("larrb;", 0x21e4),
CHAR_REF("larrbfs;", 0x291f),
CHAR_REF("larrfs;", 0x291d),
CHAR_REF("larrhk;", 0x21a9),
CHAR_REF("larrlp;", 0x21ab),
CHAR_REF("larrpl;", 0x2939),
CHAR_REF("larrsim;", 0x2973),
CHAR_REF("larrtl;", 0x21a2),
CHAR_REF("lat;", 0x2aab),
CHAR_REF("latail;", 0x2919),
CHAR_REF("late;", 0x2aad),
MULTI_CHAR_REF("lates;", 0x2aad, 0xfe00),
CHAR_REF("lbarr;", 0x290c),
CHAR_REF("lbbrk;", 0x2772),
CHAR_REF("lbrace;", 0x7b),
CHAR_REF("lbrack;", 0x5b),
CHAR_REF("lbrke;", 0x298b),
CHAR_REF("lbrksld;", 0x298f),
CHAR_REF("lbrkslu;", 0x298d),
CHAR_REF("lcaron;", 0x013e),
CHAR_REF("lcedil;", 0x013c),
CHAR_REF("lceil;", 0x2308),
CHAR_REF("lcub;", 0x7b),
CHAR_REF("lcy;", 0x043b),
CHAR_REF("ldca;", 0x2936),
CHAR_REF("ldquo;", 0x201c),
CHAR_REF("ldquor;", 0x201e),
CHAR_REF("ldrdhar;", 0x2967),
CHAR_REF("ldrushar;", 0x294b),
CHAR_REF("ldsh;", 0x21b2),
CHAR_REF("le;", 0x2264),
CHAR_REF("leftarrow;", 0x2190),
CHAR_REF("leftarrowtail;", 0x21a2),
CHAR_REF("leftharpoondown;", 0x21bd),
CHAR_REF("leftharpoonup;", 0x21bc),
CHAR_REF("leftleftarrows;", 0x21c7),
CHAR_REF("leftrightarrow;", 0x2194),
CHAR_REF("leftrightarrows;", 0x21c6),
CHAR_REF("leftrightharpoons;", 0x21cb),
CHAR_REF("leftrightsquigarrow;", 0x21ad),
CHAR_REF("leftthreetimes;", 0x22cb),
CHAR_REF("leg;", 0x22da),
CHAR_REF("leq;", 0x2264),
CHAR_REF("leqq;", 0x2266),
CHAR_REF("leqslant;", 0x2a7d),
CHAR_REF("les;", 0x2a7d),
CHAR_REF("lescc;", 0x2aa8),
CHAR_REF("lesdot;", 0x2a7f),
CHAR_REF("lesdoto;", 0x2a81),
CHAR_REF("lesdotor;", 0x2a83),
MULTI_CHAR_REF("lesg;", 0x22da, 0xfe00),
CHAR_REF("lesges;", 0x2a93),
CHAR_REF("lessapprox;", 0x2a85),
CHAR_REF("lessdot;", 0x22d6),
CHAR_REF("lesseqgtr;", 0x22da),
CHAR_REF("lesseqqgtr;", 0x2a8b),
CHAR_REF("lessgtr;", 0x2276),
CHAR_REF("lesssim;", 0x2272),
CHAR_REF("lfisht;", 0x297c),
CHAR_REF("lfloor;", 0x230a),
CHAR_REF("lfr;", 0x0001d529),
CHAR_REF("lg;", 0x2276),
CHAR_REF("lgE;", 0x2a91),
CHAR_REF("lhard;", 0x21bd),
CHAR_REF("lharu;", 0x21bc),
CHAR_REF("lharul;", 0x296a),
CHAR_REF("lhblk;", 0x2584),
CHAR_REF("ljcy;", 0x0459),
CHAR_REF("ll;", 0x226a),
CHAR_REF("llarr;", 0x21c7),
CHAR_REF("llcorner;", 0x231e),
CHAR_REF("llhard;", 0x296b),
CHAR_REF("lltri;", 0x25fa),
CHAR_REF("lmidot;", 0x0140),
CHAR_REF("lmoust;", 0x23b0),
CHAR_REF("lmoustache;", 0x23b0),
CHAR_REF("lnE;", 0x2268),
CHAR_REF("lnap;", 0x2a89),
CHAR_REF("lnapprox;", 0x2a89),
CHAR_REF("lne;", 0x2a87),
CHAR_REF("lneq;", 0x2a87),
CHAR_REF("lneqq;", 0x2268),
CHAR_REF("lnsim;", 0x22e6),
CHAR_REF("loang;", 0x27ec),
CHAR_REF("loarr;", 0x21fd),
CHAR_REF("lobrk;", 0x27e6),
CHAR_REF("longleftarrow;", 0x27f5),
CHAR_REF("longleftrightarrow;", 0x27f7),
CHAR_REF("longmapsto;", 0x27fc),
CHAR_REF("longrightarrow;", 0x27f6),
CHAR_REF("looparrowleft;", 0x21ab),
CHAR_REF("looparrowright;", 0x21ac),
CHAR_REF("lopar;", 0x2985),
CHAR_REF("lopf;", 0x0001d55d),
CHAR_REF("loplus;", 0x2a2d),
CHAR_REF("lotimes;", 0x2a34),
CHAR_REF("lowast;", 0x2217),
CHAR_REF("lowbar;", 0x5f),
CHAR_REF("loz;", 0x25ca),
CHAR_REF("lozenge;", 0x25ca),
CHAR_REF("lozf;", 0x29eb),
CHAR_REF("lpar;", 0x28),
CHAR_REF("lparlt;", 0x2993),
CHAR_REF("lrarr;", 0x21c6),
CHAR_REF("lrcorner;", 0x231f),
CHAR_REF("lrhar;", 0x21cb),
CHAR_REF("lrhard;", 0x296d),
CHAR_REF("lrm;", 0x200e),
CHAR_REF("lrtri;", 0x22bf),
CHAR_REF("lsaquo;", 0x2039),
CHAR_REF("lscr;", 0x0001d4c1),
CHAR_REF("lsh;", 0x21b0),
CHAR_REF("lsim;", 0x2272),
CHAR_REF("lsime;", 0x2a8d),
CHAR_REF("lsimg;", 0x2a8f),
CHAR_REF("lsqb;", 0x5b),
CHAR_REF("lsquo;", 0x2018),
CHAR_REF("lsquor;", 0x201a),
CHAR_REF("lstrok;", 0x0142),
CHAR_REF("lt;", 0x3c),
CHAR_REF("lt", 0x3c),
CHAR_REF("ltcc;", 0x2aa6),
CHAR_REF("ltcir;", 0x2a79),
CHAR_REF("ltdot;", 0x22d6),
CHAR_REF("lthree;", 0x22cb),
CHAR_REF("ltimes;", 0x22c9),
CHAR_REF("ltlarr;", 0x2976),
CHAR_REF("ltquest;", 0x2a7b),
CHAR_REF("ltrPar;", 0x2996),
CHAR_REF("ltri;", 0x25c3),
CHAR_REF("ltrie;", 0x22b4),
CHAR_REF("ltrif;", 0x25c2),
CHAR_REF("lurdshar;", 0x294a),
CHAR_REF("luruhar;", 0x2966),
MULTI_CHAR_REF("lvertneqq;", 0x2268, 0xfe00),
MULTI_CHAR_REF("lvnE;", 0x2268, 0xfe00),
CHAR_REF("mDDot;", 0x223a),
CHAR_REF("macr;", 0xaf),
CHAR_REF("macr", 0xaf),
CHAR_REF("male;", 0x2642),
CHAR_REF("malt;", 0x2720),
CHAR_REF("maltese;", 0x2720),
CHAR_REF("map;", 0x21a6),
CHAR_REF("mapsto;", 0x21a6),
CHAR_REF("mapstodown;", 0x21a7),
CHAR_REF("mapstoleft;", 0x21a4),
CHAR_REF("mapstoup;", 0x21a5),
CHAR_REF("marker;", 0x25ae),
CHAR_REF("mcomma;", 0x2a29),
CHAR_REF("mcy;", 0x043c),
CHAR_REF("mdash;", 0x2014),
CHAR_REF("measuredangle;", 0x2221),
CHAR_REF("mfr;", 0x0001d52a),
CHAR_REF("mho;", 0x2127),
CHAR_REF("micro;", 0xb5),
CHAR_REF("micro", 0xb5),
CHAR_REF("mid;", 0x2223),
CHAR_REF("midast;", 0x2a),
CHAR_REF("midcir;", 0x2af0),
CHAR_REF("middot;", 0xb7),
CHAR_REF("middot", 0xb7),
CHAR_REF("minus;", 0x2212),
CHAR_REF("minusb;", 0x229f),
CHAR_REF("minusd;", 0x2238),
CHAR_REF("minusdu;", 0x2a2a),
CHAR_REF("mlcp;", 0x2adb),
CHAR_REF("mldr;", 0x2026),
CHAR_REF("mnplus;", 0x2213),
CHAR_REF("models;", 0x22a7),
CHAR_REF("mopf;", 0x0001d55e),
CHAR_REF("mp;", 0x2213),
CHAR_REF("mscr;", 0x0001d4c2),
CHAR_REF("mstpos;", 0x223e),
CHAR_REF("mu;", 0x03bc),
CHAR_REF("multimap;", 0x22b8),
CHAR_REF("mumap;", 0x22b8),
MULTI_CHAR_REF("nGg;", 0x22d9, 0x0338),
MULTI_CHAR_REF("nGt;", 0x226b, 0x20d2),
MULTI_CHAR_REF("nGtv;", 0x226b, 0x0338),
CHAR_REF("nLeftarrow;", 0x21cd),
CHAR_REF("nLeftrightarrow;", 0x21ce),
MULTI_CHAR_REF("nLl;", 0x22d8, 0x0338),
MULTI_CHAR_REF("nLt;", 0x226a, 0x20d2),
MULTI_CHAR_REF("nLtv;", 0x226a, 0x0338),
CHAR_REF("nRightarrow;", 0x21cf),
CHAR_REF("nVDash;", 0x22af),
CHAR_REF("nVdash;", 0x22ae),
CHAR_REF("nabla;", 0x2207),
CHAR_REF("nacute;", 0x0144),
MULTI_CHAR_REF("nang;", 0x2220, 0x20d2),
CHAR_REF("nap;", 0x2249),
MULTI_CHAR_REF("napE;", 0x2a70, 0x0338),
MULTI_CHAR_REF("napid;", 0x224b, 0x0338),
CHAR_REF("napos;", 0x0149),
CHAR_REF("napprox;", 0x2249),
CHAR_REF("natur;", 0x266e),
CHAR_REF("natural;", 0x266e),
CHAR_REF("naturals;", 0x2115),
CHAR_REF("nbsp;", 0xa0),
CHAR_REF("nbsp", 0xa0),
MULTI_CHAR_REF("nbump;", 0x224e, 0x0338),
MULTI_CHAR_REF("nbumpe;", 0x224f, 0x0338),
CHAR_REF("ncap;", 0x2a43),
CHAR_REF("ncaron;", 0x0148),
CHAR_REF("ncedil;", 0x0146),
CHAR_REF("ncong;", 0x2247),
MULTI_CHAR_REF("ncongdot;", 0x2a6d, 0x0338),
CHAR_REF("ncup;", 0x2a42),
CHAR_REF("ncy;", 0x043d),
CHAR_REF("ndash;", 0x2013),
CHAR_REF("ne;", 0x2260),
CHAR_REF("neArr;", 0x21d7),
CHAR_REF("nearhk;", 0x2924),
CHAR_REF("nearr;", 0x2197),
CHAR_REF("nearrow;", 0x2197),
MULTI_CHAR_REF("nedot;", 0x2250, 0x0338),
CHAR_REF("nequiv;", 0x2262),
CHAR_REF("nesear;", 0x2928),
MULTI_CHAR_REF("nesim;", 0x2242, 0x0338),
CHAR_REF("nexist;", 0x2204),
CHAR_REF("nexists;", 0x2204),
CHAR_REF("nfr;", 0x0001d52b),
MULTI_CHAR_REF("ngE;", 0x2267, 0x0338),
CHAR_REF("nge;", 0x2271),
CHAR_REF("ngeq;", 0x2271),
MULTI_CHAR_REF("ngeqq;", 0x2267, 0x0338),
MULTI_CHAR_REF("ngeqslant;", 0x2a7e, 0x0338),
MULTI_CHAR_REF("nges;", 0x2a7e, 0x0338),
CHAR_REF("ngsim;", 0x2275),
CHAR_REF("ngt;", 0x226f),
CHAR_REF("ngtr;", 0x226f),
CHAR_REF("nhArr;", 0x21ce),
CHAR_REF("nharr;", 0x21ae),
CHAR_REF("nhpar;", 0x2af2),
CHAR_REF("ni;", 0x220b),
CHAR_REF("nis;", 0x22fc),
CHAR_REF("nisd;", 0x22fa),
CHAR_REF("niv;", 0x220b),
CHAR_REF("njcy;", 0x045a),
CHAR_REF("nlArr;", 0x21cd),
MULTI_CHAR_REF("nlE;", 0x2266, 0x0338),
CHAR_REF("nlarr;", 0x219a),
CHAR_REF("nldr;", 0x2025),
CHAR_REF("nle;", 0x2270),
CHAR_REF("nleftarrow;", 0x219a),
CHAR_REF("nleftrightarrow;", 0x21ae),
CHAR_REF("nleq;", 0x2270),
MULTI_CHAR_REF("nleqq;", 0x2266, 0x0338),
MULTI_CHAR_REF("nleqslant;", 0x2a7d, 0x0338),
MULTI_CHAR_REF("nles;", 0x2a7d, 0x0338),
CHAR_REF("nless;", 0x226e),
CHAR_REF("nlsim;", 0x2274),
CHAR_REF("nlt;", 0x226e),
CHAR_REF("nltri;", 0x22ea),
CHAR_REF("nltrie;", 0x22ec),
CHAR_REF("nmid;", 0x2224),
CHAR_REF("nopf;", 0x0001d55f),
CHAR_REF("not;", 0xac),
CHAR_REF("notin;", 0x2209),
MULTI_CHAR_REF("notinE;", 0x22f9, 0x0338),
MULTI_CHAR_REF("notindot;", 0x22f5, 0x0338),
CHAR_REF("notinva;", 0x2209),
CHAR_REF("notinvb;", 0x22f7),
CHAR_REF("notinvc;", 0x22f6),
CHAR_REF("notni;", 0x220c),
CHAR_REF("notniva;", 0x220c),
CHAR_REF("notnivb;", 0x22fe),
CHAR_REF("notnivc;", 0x22fd),
CHAR_REF("not", 0xac),
CHAR_REF("npar;", 0x2226),
CHAR_REF("nparallel;", 0x2226),
MULTI_CHAR_REF("nparsl;", 0x2afd, 0x20e5),
MULTI_CHAR_REF("npart;", 0x2202, 0x0338),
CHAR_REF("npolint;", 0x2a14),
CHAR_REF("npr;", 0x2280),
CHAR_REF("nprcue;", 0x22e0),
MULTI_CHAR_REF("npre;", 0x2aaf, 0x0338),
CHAR_REF("nprec;", 0x2280),
MULTI_CHAR_REF("npreceq;", 0x2aaf, 0x0338),
CHAR_REF("nrArr;", 0x21cf),
CHAR_REF("nrarr;", 0x219b),
MULTI_CHAR_REF("nrarrc;", 0x2933, 0x0338),
MULTI_CHAR_REF("nrarrw;", 0x219d, 0x0338),
CHAR_REF("nrightarrow;", 0x219b),
CHAR_REF("nrtri;", 0x22eb),
CHAR_REF("nrtrie;", 0x22ed),
CHAR_REF("nsc;", 0x2281),
CHAR_REF("nsccue;", 0x22e1),
MULTI_CHAR_REF("nsce;", 0x2ab0, 0x0338),
CHAR_REF("nscr;", 0x0001d4c3),
CHAR_REF("nshortmid;", 0x2224),
CHAR_REF("nshortparallel;", 0x2226),
CHAR_REF("nsim;", 0x2241),
CHAR_REF("nsime;", 0x2244),
CHAR_REF("nsimeq;", 0x2244),
CHAR_REF("nsmid;", 0x2224),
CHAR_REF("nspar;", 0x2226),
CHAR_REF("nsqsube;", 0x22e2),
CHAR_REF("nsqsupe;", 0x22e3),
CHAR_REF("nsub;", 0x2284),
MULTI_CHAR_REF("nsubE;", 0x2ac5, 0x0338),
CHAR_REF("nsube;", 0x2288),
MULTI_CHAR_REF("nsubset;", 0x2282, 0x20d2),
CHAR_REF("nsubseteq;", 0x2288),
MULTI_CHAR_REF("nsubseteqq;", 0x2ac5, 0x0338),
CHAR_REF("nsucc;", 0x2281),
MULTI_CHAR_REF("nsucceq;", 0x2ab0, 0x0338),
CHAR_REF("nsup;", 0x2285),
MULTI_CHAR_REF("nsupE;", 0x2ac6, 0x0338),
CHAR_REF("nsupe;", 0x2289),
MULTI_CHAR_REF("nsupset;", 0x2283, 0x20d2),
CHAR_REF("nsupseteq;", 0x2289),
MULTI_CHAR_REF("nsupseteqq;", 0x2ac6, 0x0338),
CHAR_REF("ntgl;", 0x2279),
CHAR_REF("ntilde;", 0xf1),
CHAR_REF("ntilde", 0xf1),
CHAR_REF("ntlg;", 0x2278),
CHAR_REF("ntriangleleft;", 0x22ea),
CHAR_REF("ntrianglelefteq;", 0x22ec),
CHAR_REF("ntriangleright;", 0x22eb),
CHAR_REF("ntrianglerighteq;", 0x22ed),
CHAR_REF("nu;", 0x03bd),
CHAR_REF("num;", 0x23),
CHAR_REF("numero;", 0x2116),
CHAR_REF("numsp;", 0x2007),
CHAR_REF("nvDash;", 0x22ad),
CHAR_REF("nvHarr;", 0x2904),
MULTI_CHAR_REF("nvap;", 0x224d, 0x20d2),
CHAR_REF("nvdash;", 0x22ac),
MULTI_CHAR_REF("nvge;", 0x2265, 0x20d2),
MULTI_CHAR_REF("nvgt;", 0x3e, 0x20d2),
CHAR_REF("nvinfin;", 0x29de),
CHAR_REF("nvlArr;", 0x2902),
MULTI_CHAR_REF("nvle;", 0x2264, 0x20d2),
MULTI_CHAR_REF("nvlt;", 0x3c, 0x20d2),
MULTI_CHAR_REF("nvltrie;", 0x22b4, 0x20d2),
CHAR_REF("nvrArr;", 0x2903),
MULTI_CHAR_REF("nvrtrie;", 0x22b5, 0x20d2),
MULTI_CHAR_REF("nvsim;", 0x223c, 0x20d2),
CHAR_REF("nwArr;", 0x21d6),
CHAR_REF("nwarhk;", 0x2923),
CHAR_REF("nwarr;", 0x2196),
CHAR_REF("nwarrow;", 0x2196),
CHAR_REF("nwnear;", 0x2927),
CHAR_REF("oS;", 0x24c8),
CHAR_REF("oacute;", 0xf3),
CHAR_REF("oacute", 0xf3),
CHAR_REF("oast;", 0x229b),
CHAR_REF("ocir;", 0x229a),
CHAR_REF("ocirc;", 0xf4),
CHAR_REF("ocirc", 0xf4),
CHAR_REF("ocy;", 0x043e),
CHAR_REF("odash;", 0x229d),
CHAR_REF("odblac;", 0x0151),
CHAR_REF("odiv;", 0x2a38),
CHAR_REF("odot;", 0x2299),
CHAR_REF("odsold;", 0x29bc),
CHAR_REF("oelig;", 0x0153),
CHAR_REF("ofcir;", 0x29bf),
CHAR_REF("ofr;", 0x0001d52c),
CHAR_REF("ogon;", 0x02db),
CHAR_REF("ograve;", 0xf2),
CHAR_REF("ograve", 0xf2),
CHAR_REF("ogt;", 0x29c1),
CHAR_REF("ohbar;", 0x29b5),
CHAR_REF("ohm;", 0x03a9),
CHAR_REF("oint;", 0x222e),
CHAR_REF("olarr;", 0x21ba),
CHAR_REF("olcir;", 0x29be),
CHAR_REF("olcross;", 0x29bb),
CHAR_REF("oline;", 0x203e),
CHAR_REF("olt;", 0x29c0),
CHAR_REF("omacr;", 0x014d),
CHAR_REF("omega;", 0x03c9),
CHAR_REF("omicron;", 0x03bf),
CHAR_REF("omid;", 0x29b6),
CHAR_REF("ominus;", 0x2296),
CHAR_REF("oopf;", 0x0001d560),
CHAR_REF("opar;", 0x29b7),
CHAR_REF("operp;", 0x29b9),
CHAR_REF("oplus;", 0x2295),
CHAR_REF("or;", 0x2228),
CHAR_REF("orarr;", 0x21bb),
CHAR_REF("ord;", 0x2a5d),
CHAR_REF("order;", 0x2134),
CHAR_REF("orderof;", 0x2134),
CHAR_REF("ordf;", 0xaa),
CHAR_REF("ordf", 0xaa),
CHAR_REF("ordm;", 0xba),
CHAR_REF("ordm", 0xba),
CHAR_REF("origof;", 0x22b6),
CHAR_REF("oror;", 0x2a56),
CHAR_REF("orslope;", 0x2a57),
CHAR_REF("orv;", 0x2a5b),
CHAR_REF("oscr;", 0x2134),
CHAR_REF("oslash;", 0xf8),
CHAR_REF("oslash", 0xf8),
CHAR_REF("osol;", 0x2298),
CHAR_REF("otilde;", 0xf5),
CHAR_REF("otilde", 0xf5),
CHAR_REF("otimes;", 0x2297),
CHAR_REF("otimesas;", 0x2a36),
CHAR_REF("ouml;", 0xf6),
CHAR_REF("ouml", 0xf6),
CHAR_REF("ovbar;", 0x233d),
CHAR_REF("par;", 0x2225),
CHAR_REF("para;", 0xb6),
CHAR_REF("para", 0xb6),
CHAR_REF("parallel;", 0x2225),
CHAR_REF("parsim;", 0x2af3),
CHAR_REF("parsl;", 0x2afd),
CHAR_REF("part;", 0x2202),
CHAR_REF("pcy;", 0x043f),
CHAR_REF("percnt;", 0x25),
CHAR_REF("period;", 0x2e),
CHAR_REF("permil;", 0x2030),
CHAR_REF("perp;", 0x22a5),
CHAR_REF("pertenk;", 0x2031),
CHAR_REF("pfr;", 0x0001d52d),
CHAR_REF("phi;", 0x03c6),
CHAR_REF("phiv;", 0x03d5),
CHAR_REF("phmmat;", 0x2133),
CHAR_REF("phone;", 0x260e),
CHAR_REF("pi;", 0x03c0),
CHAR_REF("pitchfork;", 0x22d4),
CHAR_REF("piv;", 0x03d6),
CHAR_REF("planck;", 0x210f),
CHAR_REF("planckh;", 0x210e),
CHAR_REF("plankv;", 0x210f),
CHAR_REF("plus;", 0x2b),
CHAR_REF("plusacir;", 0x2a23),
CHAR_REF("plusb;", 0x229e),
CHAR_REF("pluscir;", 0x2a22),
CHAR_REF("plusdo;", 0x2214),
CHAR_REF("plusdu;", 0x2a25),
CHAR_REF("pluse;", 0x2a72),
CHAR_REF("plusmn;", 0xb1),
CHAR_REF("plusmn", 0xb1),
CHAR_REF("plussim;", 0x2a26),
CHAR_REF("plustwo;", 0x2a27),
CHAR_REF("pm;", 0xb1),
CHAR_REF("pointint;", 0x2a15),
CHAR_REF("popf;", 0x0001d561),
CHAR_REF("pound;", 0xa3),
CHAR_REF("pound", 0xa3),
CHAR_REF("pr;", 0x227a),
CHAR_REF("prE;", 0x2ab3),
CHAR_REF("prap;", 0x2ab7),
CHAR_REF("prcue;", 0x227c),
CHAR_REF("pre;", 0x2aaf),
CHAR_REF("prec;", 0x227a),
CHAR_REF("precapprox;", 0x2ab7),
CHAR_REF("preccurlyeq;", 0x227c),
CHAR_REF("preceq;", 0x2aaf),
CHAR_REF("precnapprox;", 0x2ab9),
CHAR_REF("precneqq;", 0x2ab5),
CHAR_REF("precnsim;", 0x22e8),
CHAR_REF("precsim;", 0x227e),
CHAR_REF("prime;", 0x2032),
CHAR_REF("primes;", 0x2119),
CHAR_REF("prnE;", 0x2ab5),
CHAR_REF("prnap;", 0x2ab9),
CHAR_REF("prnsim;", 0x22e8),
CHAR_REF("prod;", 0x220f),
CHAR_REF("profalar;", 0x232e),
CHAR_REF("profline;", 0x2312),
CHAR_REF("profsurf;", 0x2313),
CHAR_REF("prop;", 0x221d),
CHAR_REF("propto;", 0x221d),
CHAR_REF("prsim;", 0x227e),
CHAR_REF("prurel;", 0x22b0),
CHAR_REF("pscr;", 0x0001d4c5),
CHAR_REF("psi;", 0x03c8),
CHAR_REF("puncsp;", 0x2008),
CHAR_REF("qfr;", 0x0001d52e),
CHAR_REF("qint;", 0x2a0c),
CHAR_REF("qopf;", 0x0001d562),
CHAR_REF("qprime;", 0x2057),
CHAR_REF("qscr;", 0x0001d4c6),
CHAR_REF("quaternions;", 0x210d),
CHAR_REF("quatint;", 0x2a16),
CHAR_REF("quest;", 0x3f),
CHAR_REF("questeq;", 0x225f),
CHAR_REF("quot;", 0x22),
CHAR_REF("quot", 0x22),
CHAR_REF("rAarr;", 0x21db),
CHAR_REF("rArr;", 0x21d2),
CHAR_REF("rAtail;", 0x291c),
CHAR_REF("rBarr;", 0x290f),
CHAR_REF("rHar;", 0x2964),
MULTI_CHAR_REF("race;", 0x223d, 0x0331),
CHAR_REF("racute;", 0x0155),
CHAR_REF("radic;", 0x221a),
CHAR_REF("raemptyv;", 0x29b3),
CHAR_REF("rang;", 0x27e9),
CHAR_REF("rangd;", 0x2992),
CHAR_REF("range;", 0x29a5),
CHAR_REF("rangle;", 0x27e9),
CHAR_REF("raquo;", 0xbb),
CHAR_REF("raquo", 0xbb),
CHAR_REF("rarr;", 0x2192),
CHAR_REF("rarrap;", 0x2975),
CHAR_REF("rarrb;", 0x21e5),
CHAR_REF("rarrbfs;", 0x2920),
CHAR_REF("rarrc;", 0x2933),
CHAR_REF("rarrfs;", 0x291e),
CHAR_REF("rarrhk;", 0x21aa),
CHAR_REF("rarrlp;", 0x21ac),
CHAR_REF("rarrpl;", 0x2945),
CHAR_REF("rarrsim;", 0x2974),
CHAR_REF("rarrtl;", 0x21a3),
CHAR_REF("rarrw;", 0x219d),
CHAR_REF("ratail;", 0x291a),
CHAR_REF("ratio;", 0x2236),
CHAR_REF("rationals;", 0x211a),
CHAR_REF("rbarr;", 0x290d),
CHAR_REF("rbbrk;", 0x2773),
CHAR_REF("rbrace;", 0x7d),
CHAR_REF("rbrack;", 0x5d),
CHAR_REF("rbrke;", 0x298c),
CHAR_REF("rbrksld;", 0x298e),
CHAR_REF("rbrkslu;", 0x2990),
CHAR_REF("rcaron;", 0x0159),
CHAR_REF("rcedil;", 0x0157),
CHAR_REF("rceil;", 0x2309),
CHAR_REF("rcub;", 0x7d),
CHAR_REF("rcy;", 0x0440),
CHAR_REF("rdca;", 0x2937),
CHAR_REF("rdldhar;", 0x2969),
CHAR_REF("rdquo;", 0x201d),
CHAR_REF("rdquor;", 0x201d),
CHAR_REF("rdsh;", 0x21b3),
CHAR_REF("real;", 0x211c),
CHAR_REF("realine;", 0x211b),
CHAR_REF("realpart;", 0x211c),
CHAR_REF("reals;", 0x211d),
CHAR_REF("rect;", 0x25ad),
CHAR_REF("reg;", 0xae),
CHAR_REF("reg", 0xae),
CHAR_REF("rfisht;", 0x297d),
CHAR_REF("rfloor;", 0x230b),
CHAR_REF("rfr;", 0x0001d52f),
CHAR_REF("rhard;", 0x21c1),
CHAR_REF("rharu;", 0x21c0),
CHAR_REF("rharul;", 0x296c),
CHAR_REF("rho;", 0x03c1),
CHAR_REF("rhov;", 0x03f1),
CHAR_REF("rightarrow;", 0x2192),
CHAR_REF("rightarrowtail;", 0x21a3),
CHAR_REF("rightharpoondown;", 0x21c1),
CHAR_REF("rightharpoonup;", 0x21c0),
CHAR_REF("rightleftarrows;", 0x21c4),
CHAR_REF("rightleftharpoons;", 0x21cc),
CHAR_REF("rightrightarrows;", 0x21c9),
CHAR_REF("rightsquigarrow;", 0x219d),
CHAR_REF("rightthreetimes;", 0x22cc),
CHAR_REF("ring;", 0x02da),
CHAR_REF("risingdotseq;", 0x2253),
CHAR_REF("rlarr;", 0x21c4),
CHAR_REF("rlhar;", 0x21cc),
CHAR_REF("rlm;", 0x200f),
CHAR_REF("rmoust;", 0x23b1),
CHAR_REF("rmoustache;", 0x23b1),
CHAR_REF("rnmid;", 0x2aee),
CHAR_REF("roang;", 0x27ed),
CHAR_REF("roarr;", 0x21fe),
CHAR_REF("robrk;", 0x27e7),
CHAR_REF("ropar;", 0x2986),
CHAR_REF("ropf;", 0x0001d563),
CHAR_REF("roplus;", 0x2a2e),
CHAR_REF("rotimes;", 0x2a35),
CHAR_REF("rpar;", 0x29),
CHAR_REF("rpargt;", 0x2994),
CHAR_REF("rppolint;", 0x2a12),
CHAR_REF("rrarr;", 0x21c9),
CHAR_REF("rsaquo;", 0x203a),
CHAR_REF("rscr;", 0x0001d4c7),
CHAR_REF("rsh;", 0x21b1),
CHAR_REF("rsqb;", 0x5d),
CHAR_REF("rsquo;", 0x2019),
CHAR_REF("rsquor;", 0x2019),
CHAR_REF("rthree;", 0x22cc),
CHAR_REF("rtimes;", 0x22ca),
CHAR_REF("rtri;", 0x25b9),
CHAR_REF("rtrie;", 0x22b5),
CHAR_REF("rtrif;", 0x25b8),
CHAR_REF("rtriltri;", 0x29ce),
CHAR_REF("ruluhar;", 0x2968),
CHAR_REF("rx;", 0x211e),
CHAR_REF("sacute;", 0x015b),
CHAR_REF("sbquo;", 0x201a),
CHAR_REF("sc;", 0x227b),
CHAR_REF("scE;", 0x2ab4),
CHAR_REF("scap;", 0x2ab8),
CHAR_REF("scaron;", 0x0161),
CHAR_REF("sccue;", 0x227d),
CHAR_REF("sce;", 0x2ab0),
CHAR_REF("scedil;", 0x015f),
CHAR_REF("scirc;", 0x015d),
CHAR_REF("scnE;", 0x2ab6),
CHAR_REF("scnap;", 0x2aba),
CHAR_REF("scnsim;", 0x22e9),
CHAR_REF("scpolint;", 0x2a13),
CHAR_REF("scsim;", 0x227f),
CHAR_REF("scy;", 0x0441),
CHAR_REF("sdot;", 0x22c5),
CHAR_REF("sdotb;", 0x22a1),
CHAR_REF("sdote;", 0x2a66),
CHAR_REF("seArr;", 0x21d8),
CHAR_REF("searhk;", 0x2925),
CHAR_REF("searr;", 0x2198),
CHAR_REF("searrow;", 0x2198),
CHAR_REF("sect;", 0xa7),
CHAR_REF("sect", 0xa7),
CHAR_REF("semi;", 0x3b),
CHAR_REF("seswar;", 0x2929),
CHAR_REF("setminus;", 0x2216),
CHAR_REF("setmn;", 0x2216),
CHAR_REF("sext;", 0x2736),
CHAR_REF("sfr;", 0x0001d530),
CHAR_REF("sfrown;", 0x2322),
CHAR_REF("sharp;", 0x266f),
CHAR_REF("shchcy;", 0x0449),
CHAR_REF("shcy;", 0x0448),
CHAR_REF("shortmid;", 0x2223),
CHAR_REF("shortparallel;", 0x2225),
CHAR_REF("shy;", 0xad),
CHAR_REF("shy", 0xad),
CHAR_REF("sigma;", 0x03c3),
CHAR_REF("sigmaf;", 0x03c2),
CHAR_REF("sigmav;", 0x03c2),
CHAR_REF("sim;", 0x223c),
CHAR_REF("simdot;", 0x2a6a),
CHAR_REF("sime;", 0x2243),
CHAR_REF("simeq;", 0x2243),
CHAR_REF("simg;", 0x2a9e),
CHAR_REF("simgE;", 0x2aa0),
CHAR_REF("siml;", 0x2a9d),
CHAR_REF("simlE;", 0x2a9f),
CHAR_REF("simne;", 0x2246),
CHAR_REF("simplus;", 0x2a24),
CHAR_REF("simrarr;", 0x2972),
CHAR_REF("slarr;", 0x2190),
CHAR_REF("smallsetminus;", 0x2216),
CHAR_REF("smashp;", 0x2a33),
CHAR_REF("smeparsl;", 0x29e4),
CHAR_REF("smid;", 0x2223),
CHAR_REF("smile;", 0x2323),
CHAR_REF("smt;", 0x2aaa),
CHAR_REF("smte;", 0x2aac),
MULTI_CHAR_REF("smtes;", 0x2aac, 0xfe00),
CHAR_REF("softcy;", 0x044c),
CHAR_REF("sol;", 0x2f),
CHAR_REF("solb;", 0x29c4),
CHAR_REF("solbar;", 0x233f),
CHAR_REF("sopf;", 0x0001d564),
CHAR_REF("spades;", 0x2660),
CHAR_REF("spadesuit;", 0x2660),
CHAR_REF("spar;", 0x2225),
CHAR_REF("sqcap;", 0x2293),
MULTI_CHAR_REF("sqcaps;", 0x2293, 0xfe00),
CHAR_REF("sqcup;", 0x2294),
MULTI_CHAR_REF("sqcups;", 0x2294, 0xfe00),
CHAR_REF("sqsub;", 0x228f),
CHAR_REF("sqsube;", 0x2291),
CHAR_REF("sqsubset;", 0x228f),
CHAR_REF("sqsubseteq;", 0x2291),
CHAR_REF("sqsup;", 0x2290),
CHAR_REF("sqsupe;", 0x2292),
CHAR_REF("sqsupset;", 0x2290),
CHAR_REF("sqsupseteq;", 0x2292),
CHAR_REF("squ;", 0x25a1),
CHAR_REF("square;", 0x25a1),
CHAR_REF("squarf;", 0x25aa),
CHAR_REF("squf;", 0x25aa),
CHAR_REF("srarr;", 0x2192),
CHAR_REF("sscr;", 0x0001d4c8),
CHAR_REF("ssetmn;", 0x2216),
CHAR_REF("ssmile;", 0x2323),
CHAR_REF("sstarf;", 0x22c6),
CHAR_REF("star;", 0x2606),
CHAR_REF("starf;", 0x2605),
CHAR_REF("straightepsilon;", 0x03f5),
CHAR_REF("straightphi;", 0x03d5),
CHAR_REF("strns;", 0xaf),
CHAR_REF("sub;", 0x2282),
CHAR_REF("subE;", 0x2ac5),
CHAR_REF("subdot;", 0x2abd),
CHAR_REF("sube;", 0x2286),
CHAR_REF("subedot;", 0x2ac3),
CHAR_REF("submult;", 0x2ac1),
CHAR_REF("subnE;", 0x2acb),
CHAR_REF("subne;", 0x228a),
CHAR_REF("subplus;", 0x2abf),
CHAR_REF("subrarr;", 0x2979),
CHAR_REF("subset;", 0x2282),
CHAR_REF("subseteq;", 0x2286),
CHAR_REF("subseteqq;", 0x2ac5),
CHAR_REF("subsetneq;", 0x228a),
CHAR_REF("subsetneqq;", 0x2acb),
CHAR_REF("subsim;", 0x2ac7),
CHAR_REF("subsub;", 0x2ad5),
CHAR_REF("subsup;", 0x2ad3),
CHAR_REF("succ;", 0x227b),
CHAR_REF("succapprox;", 0x2ab8),
CHAR_REF("succcurlyeq;", 0x227d),
CHAR_REF("succeq;", 0x2ab0),
CHAR_REF("succnapprox;", 0x2aba),
CHAR_REF("succneqq;", 0x2ab6),
CHAR_REF("succnsim;", 0x22e9),
CHAR_REF("succsim;", 0x227f),
CHAR_REF("sum;", 0x2211),
CHAR_REF("sung;", 0x266a),
CHAR_REF("sup1;", 0xb9),
CHAR_REF("sup1", 0xb9),
CHAR_REF("sup2;", 0xb2),
CHAR_REF("sup2", 0xb2),
CHAR_REF("sup3;", 0xb3),
CHAR_REF("sup3", 0xb3),
CHAR_REF("sup;", 0x2283),
CHAR_REF("supE;", 0x2ac6),
CHAR_REF("supdot;", 0x2abe),
CHAR_REF("supdsub;", 0x2ad8),
CHAR_REF("supe;", 0x2287),
CHAR_REF("supedot;", 0x2ac4),
CHAR_REF("suphsol;", 0x27c9),
CHAR_REF("suphsub;", 0x2ad7),
CHAR_REF("suplarr;", 0x297b),
CHAR_REF("supmult;", 0x2ac2),
CHAR_REF("supnE;", 0x2acc),
CHAR_REF("supne;", 0x228b),
CHAR_REF("supplus;", 0x2ac0),
CHAR_REF("supset;", 0x2283),
CHAR_REF("supseteq;", 0x2287),
CHAR_REF("supseteqq;", 0x2ac6),
CHAR_REF("supsetneq;", 0x228b),
CHAR_REF("supsetneqq;", 0x2acc),
CHAR_REF("supsim;", 0x2ac8),
CHAR_REF("supsub;", 0x2ad4),
CHAR_REF("supsup;", 0x2ad6),
CHAR_REF("swArr;", 0x21d9),
CHAR_REF("swarhk;", 0x2926),
CHAR_REF("swarr;", 0x2199),
CHAR_REF("swarrow;", 0x2199),
CHAR_REF("swnwar;", 0x292a),
CHAR_REF("szlig;", 0xdf),
CHAR_REF("szlig", 0xdf),
CHAR_REF("target;", 0x2316),
CHAR_REF("tau;", 0x03c4),
CHAR_REF("tbrk;", 0x23b4),
CHAR_REF("tcaron;", 0x0165),
CHAR_REF("tcedil;", 0x0163),
CHAR_REF("tcy;", 0x0442),
CHAR_REF("tdot;", 0x20db),
CHAR_REF("telrec;", 0x2315),
CHAR_REF("tfr;", 0x0001d531),
CHAR_REF("there4;", 0x2234),
CHAR_REF("therefore;", 0x2234),
CHAR_REF("theta;", 0x03b8),
CHAR_REF("thetasym;", 0x03d1),
CHAR_REF("thetav;", 0x03d1),
CHAR_REF("thickapprox;", 0x2248),
CHAR_REF("thicksim;", 0x223c),
CHAR_REF("thinsp;", 0x2009),
CHAR_REF("thkap;", 0x2248),
CHAR_REF("thksim;", 0x223c),
CHAR_REF("thorn;", 0xfe),
CHAR_REF("thorn", 0xfe),
CHAR_REF("tilde;", 0x02dc),
CHAR_REF("times;", 0xd7),
CHAR_REF("times", 0xd7),
CHAR_REF("timesb;", 0x22a0),
CHAR_REF("timesbar;", 0x2a31),
CHAR_REF("timesd;", 0x2a30),
CHAR_REF("tint;", 0x222d),
CHAR_REF("toea;", 0x2928),
CHAR_REF("top;", 0x22a4),
CHAR_REF("topbot;", 0x2336),
CHAR_REF("topcir;", 0x2af1),
CHAR_REF("topf;", 0x0001d565),
CHAR_REF("topfork;", 0x2ada),
CHAR_REF("tosa;", 0x2929),
CHAR_REF("tprime;", 0x2034),
CHAR_REF("trade;", 0x2122),
CHAR_REF("triangle;", 0x25b5),
CHAR_REF("triangledown;", 0x25bf),
CHAR_REF("triangleleft;", 0x25c3),
CHAR_REF("trianglelefteq;", 0x22b4),
CHAR_REF("triangleq;", 0x225c),
CHAR_REF("triangleright;", 0x25b9),
CHAR_REF("trianglerighteq;", 0x22b5),
CHAR_REF("tridot;", 0x25ec),
CHAR_REF("trie;", 0x225c),
CHAR_REF("triminus;", 0x2a3a),
CHAR_REF("triplus;", 0x2a39),
CHAR_REF("trisb;", 0x29cd),
CHAR_REF("tritime;", 0x2a3b),
CHAR_REF("trpezium;", 0x23e2),
CHAR_REF("tscr;", 0x0001d4c9),
CHAR_REF("tscy;", 0x0446),
CHAR_REF("tshcy;", 0x045b),
CHAR_REF("tstrok;", 0x0167),
CHAR_REF("twixt;", 0x226c),
CHAR_REF("twoheadleftarrow;", 0x219e),
CHAR_REF("twoheadrightarrow;", 0x21a0),
CHAR_REF("uArr;", 0x21d1),
CHAR_REF("uHar;", 0x2963),
CHAR_REF("uacute;", 0xfa),
CHAR_REF("uacute", 0xfa),
CHAR_REF("uarr;", 0x2191),
CHAR_REF("ubrcy;", 0x045e),
CHAR_REF("ubreve;", 0x016d),
CHAR_REF("ucirc;", 0xfb),
CHAR_REF("ucirc", 0xfb),
CHAR_REF("ucy;", 0x0443),
CHAR_REF("udarr;", 0x21c5),
CHAR_REF("udblac;", 0x0171),
CHAR_REF("udhar;", 0x296e),
CHAR_REF("ufisht;", 0x297e),
CHAR_REF("ufr;", 0x0001d532),
CHAR_REF("ugrave;", 0xf9),
CHAR_REF("ugrave", 0xf9),
CHAR_REF("uharl;", 0x21bf),
CHAR_REF("uharr;", 0x21be),
CHAR_REF("uhblk;", 0x2580),
CHAR_REF("ulcorn;", 0x231c),
CHAR_REF("ulcorner;", 0x231c),
CHAR_REF("ulcrop;", 0x230f),
CHAR_REF("ultri;", 0x25f8),
CHAR_REF("umacr;", 0x016b),
CHAR_REF("uml;", 0xa8),
CHAR_REF("uml", 0xa8),
CHAR_REF("uogon;", 0x0173),
CHAR_REF("uopf;", 0x0001d566),
CHAR_REF("uparrow;", 0x2191),
CHAR_REF("updownarrow;", 0x2195),
CHAR_REF("upharpoonleft;", 0x21bf),
CHAR_REF("upharpoonright;", 0x21be),
CHAR_REF("uplus;", 0x228e),
CHAR_REF("upsi;", 0x03c5),
CHAR_REF("upsih;", 0x03d2),
CHAR_REF("upsilon;", 0x03c5),
CHAR_REF("upuparrows;", 0x21c8),
CHAR_REF("urcorn;", 0x231d),
CHAR_REF("urcorner;", 0x231d),
CHAR_REF("urcrop;", 0x230e),
CHAR_REF("uring;", 0x016f),
CHAR_REF("urtri;", 0x25f9),
CHAR_REF("uscr;", 0x0001d4ca),
CHAR_REF("utdot;", 0x22f0),
CHAR_REF("utilde;", 0x0169),
CHAR_REF("utri;", 0x25b5),
CHAR_REF("utrif;", 0x25b4),
CHAR_REF("uuarr;", 0x21c8),
CHAR_REF("uuml;", 0xfc),
CHAR_REF("uuml", 0xfc),
CHAR_REF("uwangle;", 0x29a7),
CHAR_REF("vArr;", 0x21d5),
CHAR_REF("vBar;", 0x2ae8),
CHAR_REF("vBarv;", 0x2ae9),
CHAR_REF("vDash;", 0x22a8),
CHAR_REF("vangrt;", 0x299c),
CHAR_REF("varepsilon;", 0x03f5),
CHAR_REF("varkappa;", 0x03f0),
CHAR_REF("varnothing;", 0x2205),
CHAR_REF("varphi;", 0x03d5),
CHAR_REF("varpi;", 0x03d6),
CHAR_REF("varpropto;", 0x221d),
CHAR_REF("varr;", 0x2195),
CHAR_REF("varrho;", 0x03f1),
CHAR_REF("varsigma;", 0x03c2),
MULTI_CHAR_REF("varsubsetneq;", 0x228a, 0xfe00),
MULTI_CHAR_REF("varsubsetneqq;", 0x2acb, 0xfe00),
MULTI_CHAR_REF("varsupsetneq;", 0x228b, 0xfe00),
MULTI_CHAR_REF("varsupsetneqq;", 0x2acc, 0xfe00),
CHAR_REF("vartheta;", 0x03d1),
CHAR_REF("vartriangleleft;", 0x22b2),
CHAR_REF("vartriangleright;", 0x22b3),
CHAR_REF("vcy;", 0x0432),
CHAR_REF("vdash;", 0x22a2),
CHAR_REF("vee;", 0x2228),
CHAR_REF("veebar;", 0x22bb),
CHAR_REF("veeeq;", 0x225a),
CHAR_REF("vellip;", 0x22ee),
CHAR_REF("verbar;", 0x7c),
CHAR_REF("vert;", 0x7c),
CHAR_REF("vfr;", 0x0001d533),
CHAR_REF("vltri;", 0x22b2),
MULTI_CHAR_REF("vnsub;", 0x2282, 0x20d2),
MULTI_CHAR_REF("vnsup;", 0x2283, 0x20d2),
CHAR_REF("vopf;", 0x0001d567),
CHAR_REF("vprop;", 0x221d),
CHAR_REF("vrtri;", 0x22b3),
CHAR_REF("vscr;", 0x0001d4cb),
MULTI_CHAR_REF("vsubnE;", 0x2acb, 0xfe00),
MULTI_CHAR_REF("vsubne;", 0x228a, 0xfe00),
MULTI_CHAR_REF("vsupnE;", 0x2acc, 0xfe00),
MULTI_CHAR_REF("vsupne;", 0x228b, 0xfe00),
CHAR_REF("vzigzag;", 0x299a),
CHAR_REF("wcirc;", 0x0175),
CHAR_REF("wedbar;", 0x2a5f),
CHAR_REF("wedge;", 0x2227),
CHAR_REF("wedgeq;", 0x2259),
CHAR_REF("weierp;", 0x2118),
CHAR_REF("wfr;", 0x0001d534),
CHAR_REF("wopf;", 0x0001d568),
CHAR_REF("wp;", 0x2118),
CHAR_REF("wr;", 0x2240),
CHAR_REF("wreath;", 0x2240),
CHAR_REF("wscr;", 0x0001d4cc),
CHAR_REF("xcap;", 0x22c2),
CHAR_REF("xcirc;", 0x25ef),
CHAR_REF("xcup;", 0x22c3),
CHAR_REF("xdtri;", 0x25bd),
CHAR_REF("xfr;", 0x0001d535),
CHAR_REF("xhArr;", 0x27fa),
CHAR_REF("xharr;", 0x27f7),
CHAR_REF("xi;", 0x03be),
CHAR_REF("xlArr;", 0x27f8),
CHAR_REF("xlarr;", 0x27f5),
CHAR_REF("xmap;", 0x27fc),
CHAR_REF("xnis;", 0x22fb),
CHAR_REF("xodot;", 0x2a00),
CHAR_REF("xopf;", 0x0001d569),
CHAR_REF("xoplus;", 0x2a01),
CHAR_REF("xotime;", 0x2a02),
CHAR_REF("xrArr;", 0x27f9),
CHAR_REF("xrarr;", 0x27f6),
CHAR_REF("xscr;", 0x0001d4cd),
CHAR_REF("xsqcup;", 0x2a06),
CHAR_REF("xuplus;", 0x2a04),
CHAR_REF("xutri;", 0x25b3),
CHAR_REF("xvee;", 0x22c1),
CHAR_REF("xwedge;", 0x22c0),
CHAR_REF("yacute;", 0xfd),
CHAR_REF("yacute", 0xfd),
CHAR_REF("yacy;", 0x044f),
CHAR_REF("ycirc;", 0x0177),
CHAR_REF("ycy;", 0x044b),
CHAR_REF("yen;", 0xa5),
CHAR_REF("yen", 0xa5),
CHAR_REF("yfr;", 0x0001d536),
CHAR_REF("yicy;", 0x0457),
CHAR_REF("yopf;", 0x0001d56a),
CHAR_REF("yscr;", 0x0001d4ce),
CHAR_REF("yucy;", 0x044e),
CHAR_REF("yuml;", 0xff),
CHAR_REF("yuml", 0xff),
CHAR_REF("zacute;", 0x017a),
CHAR_REF("zcaron;", 0x017e),
CHAR_REF("zcy;", 0x0437),
CHAR_REF("zdot;", 0x017c),
CHAR_REF("zeetrf;", 0x2128),
CHAR_REF("zeta;", 0x03b6),
CHAR_REF("zfr;", 0x0001d537),
CHAR_REF("zhcy;", 0x0436),
CHAR_REF("zigrarr;", 0x21dd),
CHAR_REF("zopf;", 0x0001d56b),
CHAR_REF("zscr;", 0x0001d4cf),
CHAR_REF("zwj;", 0x200d),
CHAR_REF("zwnj;", 0x200c),
// Terminator.
CHAR_REF("", -1)
};
// Table of replacement characters. The spec specifies that any occurrence of
// the first character should be replaced by the second character, and a parse
// error recorded.
typedef struct {
int from_char;
int to_char;
} CharReplacement;
static const CharReplacement kCharReplacements[] = {
{ 0x00, 0xfffd },
{ 0x0d, 0x000d },
{ 0x80, 0x20ac },
{ 0x81, 0x0081 },
{ 0x82, 0x201A },
{ 0x83, 0x0192 },
{ 0x84, 0x201E },
{ 0x85, 0x2026 },
{ 0x86, 0x2020 },
{ 0x87, 0x2021 },
{ 0x88, 0x02C6 },
{ 0x89, 0x2030 },
{ 0x8A, 0x0160 },
{ 0x8B, 0x2039 },
{ 0x8C, 0x0152 },
{ 0x8D, 0x008D },
{ 0x8E, 0x017D },
{ 0x8F, 0x008F },
{ 0x90, 0x0090 },
{ 0x91, 0x2018 },
{ 0x92, 0x2019 },
{ 0x93, 0x201C },
{ 0x94, 0x201D },
{ 0x95, 0x2022 },
{ 0x96, 0x2013 },
{ 0x97, 0x2014 },
{ 0x98, 0x02DC },
{ 0x99, 0x2122 },
{ 0x9A, 0x0161 },
{ 0x9B, 0x203A },
{ 0x9C, 0x0153 },
{ 0x9D, 0x009D },
{ 0x9E, 0x017E },
{ 0x9F, 0x0178 },
// Terminator.
{ -1, -1 }
};
static int parse_digit(int c, bool allow_hex) {
if (c >= '0' && c <= '9') {
return c - '0';
}
if (allow_hex && c >= 'a' && c <= 'f') {
return c - 'a' + 10;
}
if (allow_hex && c >= 'A' && c <= 'F') {
return c - 'A' + 10;
}
return -1;
}
static void add_no_digit_error(
struct GumboInternalParser* parser, Utf8Iterator* input) {
GumboError* error = gumbo_add_error(parser);
if (!error) {
return;
}
utf8iterator_fill_error_at_mark(input, error);
error->type = GUMBO_ERR_NUMERIC_CHAR_REF_NO_DIGITS;
}
static void add_codepoint_error(
struct GumboInternalParser* parser, Utf8Iterator* input,
GumboErrorType type, int codepoint) {
GumboError* error = gumbo_add_error(parser);
if (!error) {
return;
}
utf8iterator_fill_error_at_mark(input, error);
error->type = type;
error->v.codepoint = codepoint;
}
static void add_named_reference_error(
struct GumboInternalParser* parser, Utf8Iterator* input,
GumboErrorType type, GumboStringPiece text) {
GumboError* error = gumbo_add_error(parser);
if (!error) {
return;
}
utf8iterator_fill_error_at_mark(input, error);
error->type = type;
error->v.text = text;
}
static int maybe_replace_codepoint(int codepoint) {
for (int i = 0; kCharReplacements[i].from_char != -1; ++i) {
if (kCharReplacements[i].from_char == codepoint) {
return kCharReplacements[i].to_char;
}
}
return -1;
}
static bool consume_numeric_ref(
struct GumboInternalParser* parser, Utf8Iterator* input, int* output) {
utf8iterator_next(input);
bool is_hex = false;
int c = utf8iterator_current(input);
if (c == 'x' || c == 'X') {
is_hex = true;
utf8iterator_next(input);
c = utf8iterator_current(input);
}
int digit = parse_digit(c, is_hex);
if (digit == -1) {
// First digit was invalid; add a parse error and return.
add_no_digit_error(parser, input);
utf8iterator_reset(input);
*output = kGumboNoChar;
return false;
}
int codepoint = 0;
bool status = true;
do {
codepoint = (codepoint * (is_hex ? 16 : 10)) + digit;
utf8iterator_next(input);
digit = parse_digit(utf8iterator_current(input), is_hex);
} while (digit != -1);
if (utf8iterator_current(input) != ';') {
add_codepoint_error(
parser, input, GUMBO_ERR_NUMERIC_CHAR_REF_WITHOUT_SEMICOLON, codepoint);
status = false;
} else {
utf8iterator_next(input);
}
int replacement = maybe_replace_codepoint(codepoint);
if (replacement != -1) {
add_codepoint_error(
parser, input, GUMBO_ERR_NUMERIC_CHAR_REF_INVALID, codepoint);
*output = replacement;
return false;
}
if ((codepoint >= 0xd800 && codepoint <= 0xdfff) || codepoint > 0x10ffff) {
add_codepoint_error(
parser, input, GUMBO_ERR_NUMERIC_CHAR_REF_INVALID, codepoint);
*output = 0xfffd;
return false;
}
if (utf8_is_invalid_code_point(codepoint) || codepoint == 0xb) {
add_codepoint_error(
parser, input, GUMBO_ERR_NUMERIC_CHAR_REF_INVALID, codepoint);
status = false;
// But return it anyway, per spec.
}
*output = codepoint;
return status;
}
static const NamedCharRef* find_named_char_ref(Utf8Iterator* input) {
for (int i = 0; kNamedEntities[i].codepoints.first != -1; ++i) {
const NamedCharRef* current = &kNamedEntities[i];
assert(strlen(current->name) == current->length);
if (utf8iterator_maybe_consume_match(
input, current->name, current->length, true)) {
assert(current->name != NULL);
assert(current->length > 0);
assert(current->codepoints.first != kGumboNoChar);
return current;
}
}
return NULL;
}
static bool is_legal_attribute_char_next(Utf8Iterator* input) {
int c = utf8iterator_current(input);
return c == '=' || isalnum(c);
}
static bool maybe_add_invalid_named_reference(
struct GumboInternalParser* parser, Utf8Iterator* input) {
// The iterator will always be reset in this code path, so we don't need to
// worry about consuming characters.
const char* start = utf8iterator_get_char_pointer(input);
int c = utf8iterator_current(input);
while ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9')) {
utf8iterator_next(input);
c = utf8iterator_current(input);
}
if (c == ';') {
GumboStringPiece bad_ref;
bad_ref.data = start;
bad_ref.length = utf8iterator_get_char_pointer(input) - start;
add_named_reference_error(
parser, input, GUMBO_ERR_NAMED_CHAR_REF_INVALID, bad_ref);
return false;
}
return true;
}
static bool consume_named_ref(
struct GumboInternalParser* parser, Utf8Iterator* input, bool is_in_attribute,
OneOrTwoCodepoints* output) {
assert(output->first == kGumboNoChar);
const NamedCharRef* char_ref = find_named_char_ref(input);
if (char_ref) {
assert(char_ref->length == strlen(char_ref->name));
char last_char = char_ref->name[char_ref->length - 1];
if (last_char == ';') {
*output = char_ref->codepoints;
assert(output->first != kGumboNoChar);
return true;
} else if (is_in_attribute && is_legal_attribute_char_next(input)) {
utf8iterator_reset(input);
return true;
} else {
GumboStringPiece bad_ref;
bad_ref.data = char_ref->name;
bad_ref.length = char_ref->length;
add_named_reference_error(
parser, input, GUMBO_ERR_NAMED_CHAR_REF_WITHOUT_SEMICOLON, bad_ref);
*output = char_ref->codepoints;
assert(output->first != kGumboNoChar);
return false;
}
} else {
bool status = maybe_add_invalid_named_reference(parser, input);
utf8iterator_reset(input);
return status;
}
}
bool consume_char_ref(
struct GumboInternalParser* parser, struct GumboInternalUtf8Iterator* input,
int additional_allowed_char, bool is_in_attribute,
OneOrTwoCodepoints* output) {
utf8iterator_mark(input);
utf8iterator_next(input);
int c = utf8iterator_current(input);
output->first = kGumboNoChar;
output->second = kGumboNoChar;
if (c == additional_allowed_char) {
utf8iterator_reset(input);
output->first = kGumboNoChar;
return true;
}
switch (utf8iterator_current(input)) {
case '\t':
case '\n':
case '\f':
case ' ':
case '<':
case '&':
case -1:
utf8iterator_reset(input);
return true;
case '#':
return consume_numeric_ref(parser, input, &output->first);
default:
return consume_named_ref(parser, input, is_in_attribute, output);
}
}
================================================
FILE: Pod/Classes/Private/Gumbo/char_ref.h
================================================
// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed 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.
//
// Author: jdtang@google.com (Jonathan Tang)
//
// Internal header for character reference handling; this should not be exposed
// transitively by any public API header. This is why the functions aren't
// namespaced.
#ifndef GUMBO_CHAR_REF_H_
#define GUMBO_CHAR_REF_H_
#include
#ifdef __cplusplus
extern "C" {
#endif
struct GumboInternalParser;
struct GumboInternalUtf8Iterator;
// Value that indicates no character was produced.
extern const int kGumboNoChar;
// Certain named character references generate two codepoints, not one, and so
// the consume_char_ref subroutine needs to return this instead of an int. The
// first field will be kGumboNoChar if no character reference was found; the
// second field will be kGumboNoChar if that is the case or if the character
// reference returns only a single codepoint.
typedef struct {
int first;
int second;
} OneOrTwoCodepoints;
// Implements the "consume a character reference" section of the spec.
// This reads in characters from the input as necessary, and fills in a
// OneOrTwoCodepoints struct containing the characters read. It may add parse
// errors to the GumboParser's errors vector, if the spec calls for it. Pass a
// space for the "additional allowed char" when the spec says "with no
// additional allowed char". Returns false on parse error, true otherwise.
bool consume_char_ref(
struct GumboInternalParser* parser, struct GumboInternalUtf8Iterator* input,
int additional_allowed_char, bool is_in_attribute,
OneOrTwoCodepoints* output);
#ifdef __cplusplus
}
#endif
#endif // GUMBO_CHAR_REF_H_
================================================
FILE: Pod/Classes/Private/Gumbo/error.c
================================================
// Copyright 2010 Google Inc. All Rights Reserved.
//
// Licensed 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.
//
// Author: jdtang@google.com (Jonathan Tang)
#include "error.h"
#include
#include
#include
#include
#include "gumbo.h"
#include "parser.h"
#include "string_buffer.h"
#include "util.h"
#include "vector.h"
//static const size_t kMessageBufferSize = 256;
// Prints a formatted message to a StringBuffer. This automatically resizes the
// StringBuffer as necessary to fit the message. Returns the number of bytes
// written.
static int print_message(GumboParser* parser, GumboStringBuffer* output,
const char* format, ...) {
va_list args;
va_start(args, format);
unsigned long remaining_capacity = output->capacity - output->length;
int bytes_written = vsnprintf(output->data + output->length,
remaining_capacity, format, args);
if (bytes_written > remaining_capacity) {
gumbo_string_buffer_reserve(
parser, output->capacity + bytes_written, output);
remaining_capacity = output->capacity - output->length;
bytes_written = vsnprintf(output->data + output->length,
remaining_capacity, format, args);
}
output->length += bytes_written;
va_end(args);
return bytes_written;
}
static void print_tag_stack(
GumboParser* parser, const GumboParserError* error,
GumboStringBuffer* output) {
print_message(parser, output, " Currently open tags: ");
for (int i = 0; i < error->tag_stack.length; ++i) {
if (i) {
print_message(parser, output, ", ");
}
GumboTag tag = (GumboTag) error->tag_stack.data[i];
print_message(parser, output, gumbo_normalized_tagname(tag));
}
gumbo_string_buffer_append_codepoint(parser, '.', output);
}
static void handle_parser_error(GumboParser* parser,
const GumboParserError* error,
GumboStringBuffer* output) {
if (error->parser_state == GUMBO_INSERTION_MODE_INITIAL &&
error->input_type != GUMBO_TOKEN_DOCTYPE) {
print_message(parser, output,
"The doctype must be the first token in the document");
return;
}
switch (error->input_type) {
case GUMBO_TOKEN_DOCTYPE:
print_message(parser, output, "This is not a legal doctype");
return;
case GUMBO_TOKEN_COMMENT:
// Should never happen; comments are always legal.
assert(0);
// But just in case...
print_message(parser, output, "Comments aren't legal here");
return;
case GUMBO_TOKEN_WHITESPACE:
case GUMBO_TOKEN_CHARACTER:
print_message(parser, output, "Character tokens aren't legal here");
return;
case GUMBO_TOKEN_NULL:
print_message(parser, output, "Null bytes are not allowed in HTML5");
return;
case GUMBO_TOKEN_EOF:
if (error->parser_state == GUMBO_INSERTION_MODE_INITIAL) {
print_message(parser, output, "You must provide a doctype");
} else {
print_message(parser, output, "Premature end of file");
print_tag_stack(parser, error, output);
}
return;
case GUMBO_TOKEN_START_TAG:
case GUMBO_TOKEN_END_TAG:
print_message(parser, output, "That tag isn't allowed here");
print_tag_stack(parser, error, output);
// TODO(jdtang): Give more specific messaging.
return;
}
}
// Finds the preceding newline in an original source buffer from a given byte
// location. Returns a character pointer to the character after that, or a
// pointer to the beginning of the string if this is the first line.
static const char* find_last_newline(
const char* original_text, const char* error_location) {
assert(error_location >= original_text);
const char* c = error_location;
for (; c != original_text && *c != '\n'; --c) {
// There may be an error at EOF, which would be a nul byte.
assert(*c || c == error_location);
}
return c == original_text ? c : c + 1;
}
// Finds the next newline in the original source buffer from a given byte
// location. Returns a character pointer to that newline, or a pointer to the
// terminating null byte if this is the last line.
static const char* find_next_newline(
const char* original_text, const char* error_location) {
const char* c = error_location;
for (; *c && *c != '\n'; ++c);
return c;
}
GumboError* gumbo_add_error(GumboParser* parser) {
int max_errors = parser->_options->max_errors;
if (max_errors < 0 && parser->_output->errors.length >= max_errors) {
return NULL;
}
GumboError* error = gumbo_parser_allocate(parser, sizeof(GumboError));
gumbo_vector_add(parser, error, &parser->_output->errors);
return error;
}
void gumbo_error_to_string(
GumboParser* parser, const GumboError* error, GumboStringBuffer* output) {
print_message(parser, output, "@%d:%d: ",
error->position.line, error->position.column);
switch (error->type) {
case GUMBO_ERR_UTF8_INVALID:
print_message(parser, output, "Invalid UTF8 character 0x%x",
error->v.codepoint);
break;
case GUMBO_ERR_UTF8_TRUNCATED:
print_message(parser, output,
"Input stream ends with a truncated UTF8 character 0x%x",
error->v.codepoint);
break;
case GUMBO_ERR_NUMERIC_CHAR_REF_NO_DIGITS:
print_message(parser, output,
"No digits after in numeric character reference");
break;
case GUMBO_ERR_NUMERIC_CHAR_REF_WITHOUT_SEMICOLON:
print_message(parser, output,
"The numeric character reference %d should be followed "
"by a semicolon", error->v.codepoint);
break;
case GUMBO_ERR_NUMERIC_CHAR_REF_INVALID:
print_message(parser, output,
"The numeric character reference %d; encodes an invalid "
"unicode codepoint", error->v.codepoint);
break;
case GUMBO_ERR_NAMED_CHAR_REF_WITHOUT_SEMICOLON:
// The textual data came from one of the literal strings in the table, and
// so it'll be null-terminated.
print_message(parser, output,
"The named character reference &%.*s should be followed by a "
"semicolon", (int) error->v.text.length, error->v.text.data);
break;
case GUMBO_ERR_NAMED_CHAR_REF_INVALID:
print_message(parser, output,
"The named character reference &%.*s; is not a valid entity name",
(int) error->v.text.length, error->v.text.data);
break;
case GUMBO_ERR_DUPLICATE_ATTR:
print_message(parser, output,
"Attribute %s occurs multiple times, at positions %d and %d",
error->v.duplicate_attr.name,
error->v.duplicate_attr.original_index,
error->v.duplicate_attr.new_index);
break;
case GUMBO_ERR_PARSER:
case GUMBO_ERR_UNACKNOWLEDGED_SELF_CLOSING_TAG:
handle_parser_error(parser, &error->v.parser, output);
break;
default:
print_message(parser, output,
"Tokenizer error with an unimplemented error message");
break;
}
gumbo_string_buffer_append_codepoint(parser, '.', output);
}
void gumbo_caret_diagnostic_to_string(
GumboParser* parser, const GumboError* error,
const char* source_text, GumboStringBuffer* output) {
gumbo_error_to_string(parser, error, output);
const char* line_start =
find_last_newline(source_text, error->original_text);
const char* line_end =
find_next_newline(source_text, error->original_text);
GumboStringPiece original_line;
original_line.data = line_start;
original_line.length = line_end - line_start;
gumbo_string_buffer_append_codepoint(parser, '\n', output);
gumbo_string_buffer_append_string(parser, &original_line, output);
gumbo_string_buffer_append_codepoint(parser, '\n', output);
gumbo_string_buffer_reserve(
parser, output->length + error->position.column, output);
int num_spaces = error->position.column - 1;
memset(output->data + output->length, ' ', num_spaces);
output->length += num_spaces;
gumbo_string_buffer_append_codepoint(parser, '^', output);
gumbo_string_buffer_append_codepoint(parser, '\n', output);
}
void gumbo_print_caret_diagnostic(
GumboParser* parser, const GumboError* error, const char* source_text) {
GumboStringBuffer text;
gumbo_string_buffer_init(parser, &text);
gumbo_caret_diagnostic_to_string(parser, error, source_text, &text);
printf("%.*s", (int) text.length, text.data);
gumbo_string_buffer_destroy(parser, &text);
}
void gumbo_error_destroy(GumboParser* parser, GumboError* error) {
if (error->type == GUMBO_ERR_PARSER ||
error->type == GUMBO_ERR_UNACKNOWLEDGED_SELF_CLOSING_TAG) {
gumbo_vector_destroy(parser, &error->v.parser.tag_stack);
} else if (error->type == GUMBO_ERR_DUPLICATE_ATTR) {
gumbo_parser_deallocate(parser, (void*) error->v.duplicate_attr.name);
}
gumbo_parser_deallocate(parser, error);
}
void gumbo_init_errors(GumboParser* parser) {
gumbo_vector_init(parser, 5, &parser->_output->errors);
}
void gumbo_destroy_errors(GumboParser* parser) {
for (int i = 0; i < parser->_output->errors.length; ++i) {
gumbo_error_destroy(parser, parser->_output->errors.data[i]);
}
gumbo_vector_destroy(parser, &parser->_output->errors);
}
================================================
FILE: Pod/Classes/Private/Gumbo/error.h
================================================
// Copyright 2010 Google Inc. All Rights Reserved.
//
// Licensed 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.
//
// Author: jdtang@google.com (Jonathan Tang)
//
// Error types, enums, and handling functions.
#ifndef GUMBO_ERROR_H_
#define GUMBO_ERROR_H_
#include
#include "gumbo.h"
#include "insertion_mode.h"
#include "string_buffer.h"
#include "token_type.h"
#ifdef __cplusplus
extern "C" {
#endif
struct GumboInternalParser;
typedef enum {
GUMBO_ERR_UTF8_INVALID,
GUMBO_ERR_UTF8_TRUNCATED,
GUMBO_ERR_UTF8_NULL,
GUMBO_ERR_NUMERIC_CHAR_REF_NO_DIGITS,
GUMBO_ERR_NUMERIC_CHAR_REF_WITHOUT_SEMICOLON,
GUMBO_ERR_NUMERIC_CHAR_REF_INVALID,
GUMBO_ERR_NAMED_CHAR_REF_WITHOUT_SEMICOLON,
GUMBO_ERR_NAMED_CHAR_REF_INVALID,
GUMBO_ERR_TAG_STARTS_WITH_QUESTION,
GUMBO_ERR_TAG_EOF,
GUMBO_ERR_TAG_INVALID,
GUMBO_ERR_CLOSE_TAG_EMPTY,
GUMBO_ERR_CLOSE_TAG_EOF,
GUMBO_ERR_CLOSE_TAG_INVALID,
GUMBO_ERR_SCRIPT_EOF,
GUMBO_ERR_ATTR_NAME_EOF,
GUMBO_ERR_ATTR_NAME_INVALID,
GUMBO_ERR_ATTR_DOUBLE_QUOTE_EOF,
GUMBO_ERR_ATTR_SINGLE_QUOTE_EOF,
GUMBO_ERR_ATTR_UNQUOTED_EOF,
GUMBO_ERR_ATTR_UNQUOTED_RIGHT_BRACKET,
GUMBO_ERR_ATTR_UNQUOTED_EQUALS,
GUMBO_ERR_ATTR_AFTER_EOF,
GUMBO_ERR_ATTR_AFTER_INVALID,
GUMBO_ERR_DUPLICATE_ATTR,
GUMBO_ERR_SOLIDUS_EOF,
GUMBO_ERR_SOLIDUS_INVALID,
GUMBO_ERR_DASHES_OR_DOCTYPE,
GUMBO_ERR_COMMENT_EOF,
GUMBO_ERR_COMMENT_INVALID,
GUMBO_ERR_COMMENT_BANG_AFTER_DOUBLE_DASH,
GUMBO_ERR_COMMENT_DASH_AFTER_DOUBLE_DASH,
GUMBO_ERR_COMMENT_SPACE_AFTER_DOUBLE_DASH,
GUMBO_ERR_COMMENT_END_BANG_EOF,
GUMBO_ERR_DOCTYPE_EOF,
GUMBO_ERR_DOCTYPE_INVALID,
GUMBO_ERR_DOCTYPE_SPACE,
GUMBO_ERR_DOCTYPE_RIGHT_BRACKET,
GUMBO_ERR_DOCTYPE_SPACE_OR_RIGHT_BRACKET,
GUMBO_ERR_DOCTYPE_END,
GUMBO_ERR_PARSER,
GUMBO_ERR_UNACKNOWLEDGED_SELF_CLOSING_TAG,
} GumboErrorType;
// Additional data for duplicated attributes.
typedef struct GumboInternalDuplicateAttrError {
// The name of the attribute. Owned by this struct.
const char* name;
// The (0-based) index within the attributes vector of the original
// occurrence.
unsigned int original_index;
// The (0-based) index where the new occurrence would be.
unsigned int new_index;
} GumboDuplicateAttrError;
// A simplified representation of the tokenizer state, designed to be more
// useful to clients of this library than the internal representation. This
// condenses the actual states used in the tokenizer state machine into a few
// values that will be familiar to users of HTML.
typedef enum {
GUMBO_ERR_TOKENIZER_DATA,
GUMBO_ERR_TOKENIZER_CHAR_REF,
GUMBO_ERR_TOKENIZER_RCDATA,
GUMBO_ERR_TOKENIZER_RAWTEXT,
GUMBO_ERR_TOKENIZER_PLAINTEXT,
GUMBO_ERR_TOKENIZER_SCRIPT,
GUMBO_ERR_TOKENIZER_TAG,
GUMBO_ERR_TOKENIZER_SELF_CLOSING_TAG,
GUMBO_ERR_TOKENIZER_ATTR_NAME,
GUMBO_ERR_TOKENIZER_ATTR_VALUE,
GUMBO_ERR_TOKENIZER_MARKUP_DECLARATION,
GUMBO_ERR_TOKENIZER_COMMENT,
GUMBO_ERR_TOKENIZER_DOCTYPE,
GUMBO_ERR_TOKENIZER_CDATA,
} GumboTokenizerErrorState;
// Additional data for tokenizer errors.
// This records the current state and codepoint encountered - this is usually
// enough to reconstruct what went wrong and provide a friendly error message.
typedef struct GumboInternalTokenizerError {
// The bad codepoint encountered.
int codepoint;
// The state that the tokenizer was in at the time.
GumboTokenizerErrorState state;
} GumboTokenizerError;
// Additional data for parse errors.
typedef struct GumboInternalParserError {
// The type of input token that resulted in this error.
GumboTokenType input_type;
// The HTML tag of the input token. TAG_UNKNOWN if this was not a tag token.
GumboTag input_tag;
// The insertion mode that the parser was in at the time.
GumboInsertionMode parser_state;
// The tag stack at the point of the error. Note that this is an GumboVector
// of GumboTag's *stored by value* - cast the void* to an GumboTag directly to
// get at the tag.
GumboVector /* GumboTag */ tag_stack;
} GumboParserError;
// The overall error struct representing an error in decoding/tokenizing/parsing
// the HTML. This contains an enumerated type flag, a source position, and then
// a union of fields containing data specific to the error.
typedef struct GumboInternalError {
// The type of error.
GumboErrorType type;
// The position within the source file where the error occurred.
GumboSourcePosition position;
// A pointer to the byte within the original source file text where the error
// occurred (note that this is not the same as position.offset, as that gives
// character-based instead of byte-based offsets).
const char* original_text;
// Type-specific error information.
union {
// The code point we encountered, for:
// * GUMBO_ERR_UTF8_INVALID
// * GUMBO_ERR_UTF8_TRUNCATED
// * GUMBO_ERR_NUMERIC_CHAR_REF_WITHOUT_SEMICOLON
// * GUMBO_ERR_NUMERIC_CHAR_REF_INVALID
uint64_t codepoint;
// Tokenizer errors.
GumboTokenizerError tokenizer;
// Short textual data, for:
// * GUMBO_ERR_NAMED_CHAR_REF_WITHOUT_SEMICOLON
// * GUMBO_ERR_NAMED_CHAR_REF_INVALID
GumboStringPiece text;
// Duplicate attribute data, for GUMBO_ERR_DUPLICATE_ATTR.
GumboDuplicateAttrError duplicate_attr;
// Parser state, for GUMBO_ERR_PARSER and
// GUMBO_ERR_UNACKNOWLEDGE_SELF_CLOSING_TAG.
struct GumboInternalParserError parser;
} v;
} GumboError;
// Adds a new error to the parser's error list, and returns a pointer to it so
// that clients can fill out the rest of its fields. May return NULL if we're
// already over the max_errors field specified in GumboOptions.
GumboError* gumbo_add_error(struct GumboInternalParser* parser);
// Initializes the errors vector in the parser.
void gumbo_init_errors(struct GumboInternalParser* errors);
// Frees all the errors in the 'errors_' field of the parser.
void gumbo_destroy_errors(struct GumboInternalParser* errors);
// Frees the memory used for a single GumboError.
void gumbo_error_destroy(struct GumboInternalParser* parser, GumboError* error);
// Prints an error to a string. This fills an empty GumboStringBuffer with a
// freshly-allocated buffer containing the error message text. The caller is
// responsible for deleting the buffer. (Note that the buffer is allocated with
// the allocator specified in the GumboParser config and hence should be freed
// by gumbo_parser_deallocate().)
void gumbo_error_to_string(
struct GumboInternalParser* parser, const GumboError* error,
GumboStringBuffer* output);
// Prints a caret diagnostic to a string. This fills an empty GumboStringBuffer
// with a freshly-allocated buffer containing the error message text. The
// caller is responsible for deleting the buffer. (Note that the buffer is
// allocated with the allocator specified in the GumboParser config and hence
// should be freed by gumbo_parser_deallocate().)
void gumbo_caret_diagnostic_to_string(
struct GumboInternalParser* parser, const GumboError* error,
const char* source_text, GumboStringBuffer* output);
// Like gumbo_caret_diagnostic_to_string, but prints the text to stdout instead
// of writing to a string.
void gumbo_print_caret_diagnostic(
struct GumboInternalParser* parser, const GumboError* error,
const char* source_text);
#ifdef __cplusplus
}
#endif
#endif // GUMBO_ERROR_H_
================================================
FILE: Pod/Classes/Private/Gumbo/gumbo.h
================================================
// Copyright 2010 Google Inc. All Rights Reserved.
//
// Licensed 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.
//
// Author: jdtang@google.com (Jonathan Tang)
//
// We use Gumbo as a prefix for types, gumbo_ as a prefix for functions, and
// GUMBO_ as a prefix for enum constants (static constants get the Google-style
// kGumbo prefix).
/**
* @file
* @mainpage Gumbo HTML Parser
*
* This provides a conformant, no-dependencies implementation of the HTML5
* parsing algorithm. It supports only UTF8; if you need to parse a different
* encoding, run a preprocessing step to convert to UTF8. It returns a parse
* tree made of the structs in this file.
*
* Example:
* @code
* GumboOutput* output = gumbo_parse(input);
* do_something_with_doctype(output->document);
* do_something_with_html_tree(output->root);
* gumbo_destroy_output(&options, output);
* @endcode
* HTML5 Spec:
*
* http://www.whatwg.org/specs/web-apps/current-work/multipage/syntax.html
*/
#ifndef GUMBO_GUMBO_H_
#define GUMBO_GUMBO_H_
#include
#include
#ifdef __cplusplus
extern "C" {
#endif
/**
* A struct representing a character position within the original text buffer.
* Line and column numbers are 1-based and offsets are 0-based, which matches
* how most editors and command-line tools work. Also, columns measure
* positions in terms of characters while offsets measure by bytes; this is
* because the offset field is often used to pull out a particular region of
* text (which in most languages that bind to C implies pointer arithmetic on a
* buffer of bytes), while the column field is often used to reference a
* particular column on a printable display, which nowadays is usually UTF-8.
*/
typedef struct {
unsigned int line;
unsigned int column;
unsigned int offset;
} GumboSourcePosition;
/**
* A SourcePosition used for elements that have no source position, i.e.
* parser-inserted elements.
*/
extern const GumboSourcePosition kGumboEmptySourcePosition;
/**
* A struct representing a string or part of a string. Strings within the
* parser are represented by a char* and a length; the char* points into
* an existing data buffer owned by some other code (often the original input).
* GumboStringPieces are assumed (by convention) to be immutable, because they
* may share data. Use GumboStringBuffer if you need to construct a string.
* Clients should assume that it is not NUL-terminated, and should always use
* explicit lengths when manipulating them.
*/
typedef struct {
/** A pointer to the beginning of the string. NULL iff length == 0. */
const char* data;
/** The length of the string fragment, in bytes. May be zero. */
size_t length;
} GumboStringPiece;
/** A constant to represent a 0-length null string. */
extern const GumboStringPiece kGumboEmptyString;
/**
* Compares two GumboStringPieces, and returns true if they're equal or false
* otherwise.
*/
bool gumbo_string_equals(
const GumboStringPiece* str1, const GumboStringPiece* str2);
/**
* Compares two GumboStringPieces ignoring case, and returns true if they're
* equal or false otherwise.
*/
bool gumbo_string_equals_ignore_case(
const GumboStringPiece* str1, const GumboStringPiece* str2);
/**
* A simple vector implementation. This stores a pointer to a data array and a
* length. All elements are stored as void*; client code must cast to the
* appropriate type. Overflows upon addition result in reallocation of the data
* array, with the size doubling to maintain O(1) amortized cost. There is no
* removal function, as this isn't needed for any of the operations within this
* library. Iteration can be done through inspecting the structure directly in
* a for-loop.
*/
typedef struct {
/** Data elements. This points to a dynamically-allocated array of capacity
* elements, each a void* to the element itself.
*/
void** data;
/** Number of elements currently in the vector. */
unsigned int length;
/** Current array capacity. */
unsigned int capacity;
} GumboVector;
/** An empty (0-length, 0-capacity) GumboVector. */
extern const GumboVector kGumboEmptyVector;
/**
* Returns the first index at which an element appears in this vector (testing
* by pointer equality), or -1 if it never does.
*/
int gumbo_vector_index_of(GumboVector* vector, void* element);
/**
* An enum for all the tags defined in the HTML5 standard. These correspond to
* the tag names themselves. Enum constants exist only for tags which appear in
* the spec itself (or for tags with special handling in the SVG and MathML
* namespaces); any other tags appear as GUMBO_TAG_UNKNOWN and the actual tag
* name can be obtained through original_tag.
*
* This is mostly for API convenience, so that clients of this library don't
* need to perform a strcasecmp to find the normalized tag name. It also has
* efficiency benefits, by letting the parser work with enums instead of
* strings.
*/
typedef enum {
// http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#the-root-element
GUMBO_TAG_HTML,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/semantics.html#document-metadata
GUMBO_TAG_HEAD,
GUMBO_TAG_TITLE,
GUMBO_TAG_BASE,
GUMBO_TAG_LINK,
GUMBO_TAG_META,
GUMBO_TAG_STYLE,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/scripting-1.html#scripting-1
GUMBO_TAG_SCRIPT,
GUMBO_TAG_NOSCRIPT,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/sections.html#sections
GUMBO_TAG_BODY,
GUMBO_TAG_SECTION,
GUMBO_TAG_NAV,
GUMBO_TAG_ARTICLE,
GUMBO_TAG_ASIDE,
GUMBO_TAG_H1,
GUMBO_TAG_H2,
GUMBO_TAG_H3,
GUMBO_TAG_H4,
GUMBO_TAG_H5,
GUMBO_TAG_H6,
GUMBO_TAG_HGROUP,
GUMBO_TAG_HEADER,
GUMBO_TAG_FOOTER,
GUMBO_TAG_ADDRESS,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/grouping-content.html#grouping-content
GUMBO_TAG_P,
GUMBO_TAG_HR,
GUMBO_TAG_PRE,
GUMBO_TAG_BLOCKQUOTE,
GUMBO_TAG_OL,
GUMBO_TAG_UL,
GUMBO_TAG_LI,
GUMBO_TAG_DL,
GUMBO_TAG_DT,
GUMBO_TAG_DD,
GUMBO_TAG_FIGURE,
GUMBO_TAG_FIGCAPTION,
GUMBO_TAG_DIV,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/text-level-semantics.html#text-level-semantics
GUMBO_TAG_A,
GUMBO_TAG_EM,
GUMBO_TAG_STRONG,
GUMBO_TAG_SMALL,
GUMBO_TAG_S,
GUMBO_TAG_CITE,
GUMBO_TAG_Q,
GUMBO_TAG_DFN,
GUMBO_TAG_ABBR,
GUMBO_TAG_TIME,
GUMBO_TAG_CODE,
GUMBO_TAG_VAR,
GUMBO_TAG_SAMP,
GUMBO_TAG_KBD,
GUMBO_TAG_SUB,
GUMBO_TAG_SUP,
GUMBO_TAG_I,
GUMBO_TAG_B,
GUMBO_TAG_MARK,
GUMBO_TAG_RUBY,
GUMBO_TAG_RT,
GUMBO_TAG_RP,
GUMBO_TAG_BDI,
GUMBO_TAG_BDO,
GUMBO_TAG_SPAN,
GUMBO_TAG_BR,
GUMBO_TAG_WBR,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/edits.html#edits
GUMBO_TAG_INS,
GUMBO_TAG_DEL,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/embedded-content-1.html#embedded-content-1
GUMBO_TAG_IMAGE,
GUMBO_TAG_IMG,
GUMBO_TAG_IFRAME,
GUMBO_TAG_EMBED,
GUMBO_TAG_OBJECT,
GUMBO_TAG_PARAM,
GUMBO_TAG_VIDEO,
GUMBO_TAG_AUDIO,
GUMBO_TAG_SOURCE,
GUMBO_TAG_TRACK,
GUMBO_TAG_CANVAS,
GUMBO_TAG_MAP,
GUMBO_TAG_AREA,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-map-element.html#mathml
GUMBO_TAG_MATH,
GUMBO_TAG_MI,
GUMBO_TAG_MO,
GUMBO_TAG_MN,
GUMBO_TAG_MS,
GUMBO_TAG_MTEXT,
GUMBO_TAG_MGLYPH,
GUMBO_TAG_MALIGNMARK,
GUMBO_TAG_ANNOTATION_XML,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-map-element.html#svg-0
GUMBO_TAG_SVG,
GUMBO_TAG_FOREIGNOBJECT,
GUMBO_TAG_DESC,
// SVG title tags will have GUMBO_TAG_TITLE as with HTML.
// http://www.whatwg.org/specs/web-apps/current-work/multipage/tabular-data.html#tabular-data
GUMBO_TAG_TABLE,
GUMBO_TAG_CAPTION,
GUMBO_TAG_COLGROUP,
GUMBO_TAG_COL,
GUMBO_TAG_TBODY,
GUMBO_TAG_THEAD,
GUMBO_TAG_TFOOT,
GUMBO_TAG_TR,
GUMBO_TAG_TD,
GUMBO_TAG_TH,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#forms
GUMBO_TAG_FORM,
GUMBO_TAG_FIELDSET,
GUMBO_TAG_LEGEND,
GUMBO_TAG_LABEL,
GUMBO_TAG_INPUT,
GUMBO_TAG_BUTTON,
GUMBO_TAG_SELECT,
GUMBO_TAG_DATALIST,
GUMBO_TAG_OPTGROUP,
GUMBO_TAG_OPTION,
GUMBO_TAG_TEXTAREA,
GUMBO_TAG_KEYGEN,
GUMBO_TAG_OUTPUT,
GUMBO_TAG_PROGRESS,
GUMBO_TAG_METER,
// http://www.whatwg.org/specs/web-apps/current-work/multipage/interactive-elements.html#interactive-elements
GUMBO_TAG_DETAILS,
GUMBO_TAG_SUMMARY,
GUMBO_TAG_COMMAND,
GUMBO_TAG_MENU,
// Non-conforming elements that nonetheless appear in the HTML5 spec.
// http://www.whatwg.org/specs/web-apps/current-work/multipage/obsolete.html#non-conforming-features
GUMBO_TAG_APPLET,
GUMBO_TAG_ACRONYM,
GUMBO_TAG_BGSOUND,
GUMBO_TAG_DIR,
GUMBO_TAG_FRAME,
GUMBO_TAG_FRAMESET,
GUMBO_TAG_NOFRAMES,
GUMBO_TAG_ISINDEX,
GUMBO_TAG_LISTING,
GUMBO_TAG_XMP,
GUMBO_TAG_NEXTID,
GUMBO_TAG_NOEMBED,
GUMBO_TAG_PLAINTEXT,
GUMBO_TAG_RB,
GUMBO_TAG_STRIKE,
GUMBO_TAG_BASEFONT,
GUMBO_TAG_BIG,
GUMBO_TAG_BLINK,
GUMBO_TAG_CENTER,
GUMBO_TAG_FONT,
GUMBO_TAG_MARQUEE,
GUMBO_TAG_MULTICOL,
GUMBO_TAG_NOBR,
GUMBO_TAG_SPACER,
GUMBO_TAG_TT,
GUMBO_TAG_U,
// Used for all tags that don't have special handling in HTML.
GUMBO_TAG_UNKNOWN,
// A marker value to indicate the end of the enum, for iterating over it.
// Also used as the terminator for varargs functions that take tags.
GUMBO_TAG_LAST,
} GumboTag;
/**
* Returns the normalized (usually all-lowercased, except for foreign content)
* tag name for an GumboTag enum. Return value is static data owned by the
* library.
*/
const char* gumbo_normalized_tagname(GumboTag tag);
/**
* Extracts the tag name from the original_text field of an element or token by
* stripping off > characters and attributes and adjusting the passed-in
* GumboStringPiece appropriately. The tag name is in the original case and
* shares a buffer with the original text, to simplify memory management.
* Behavior is undefined if a string-piece that doesn't represent an HTML tag
* ( or ) is passed in. If the string piece is completely
* empty (NULL data pointer), then this function will exit successfully as a
* no-op.
*/
void gumbo_tag_from_original_text(GumboStringPiece* text);
/**
* Fixes the case of SVG elements that are not all lowercase.
* http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#parsing-main-inforeign
* This is not done at parse time because there's no place to store a mutated
* tag name. tag_name is an enum (which will be TAG_UNKNOWN for most SVG tags
* without special handling), while original_tag_name is a pointer into the
* original buffer. Instead, we provide this helper function that clients can
* use to rename SVG tags as appropriate.
* Returns the case-normalized SVG tagname if a replacement is found, or NULL if
* no normalization is called for. The return value is static data and owned by
* the library.
*/
const char* gumbo_normalize_svg_tagname(const GumboStringPiece* tagname);
/**
* Converts a tag name string (which may be in upper or mixed case) to a tag
* enum.
*/
GumboTag gumbo_tag_enum(const char* tagname);
/**
* Attribute namespaces.
* HTML includes special handling for XLink, XML, and XMLNS namespaces on
* attributes. Everything else goes in the generatic "NONE" namespace.
*/
typedef enum {
GUMBO_ATTR_NAMESPACE_NONE,
GUMBO_ATTR_NAMESPACE_XLINK,
GUMBO_ATTR_NAMESPACE_XML,
GUMBO_ATTR_NAMESPACE_XMLNS,
} GumboAttributeNamespaceEnum;
/**
* A struct representing a single attribute on an HTML tag. This is a
* name-value pair, but also includes information about source locations and
* original source text.
*/
typedef struct {
/**
* The namespace for the attribute. This will usually be
* GUMBO_ATTR_NAMESPACE_NONE, but some XLink/XMLNS/XML attributes take special
* values, per:
* http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adjust-foreign-attributes
*/
GumboAttributeNamespaceEnum attr_namespace;
/**
* The name of the attribute. This is in a freshly-allocated buffer to deal
* with case-normalization, and is null-terminated.
*/
const char* name;
/**
* The original text of the attribute name, as a pointer into the original
* source buffer.
*/
GumboStringPiece original_name;
/**
* The value of the attribute. This is in a freshly-allocated buffer to deal
* with unescaping, and is null-terminated. It does not include any quotes
* that surround the attribute. If the attribute has no value (for example,
* 'selected' on a checkbox), this will be an empty string.
*/
const char* value;
/**
* The original text of the value of the attribute. This points into the
* original source buffer. It includes any quotes that surround the
* attribute, and you can look at original_value.data[0] and
* original_value.data[original_value.length - 1] to determine what the quote
* characters were. If the attribute has no value, this will be a 0-length
* string.
*/
GumboStringPiece original_value;
/** The starting position of the attribute name. */
GumboSourcePosition name_start;
/**
* The ending position of the attribute name. This is not always derivable
* from the starting position of the value because of the possibility of
* whitespace around the = sign.
*/
GumboSourcePosition name_end;
/** The starting position of the attribute value. */
GumboSourcePosition value_start;
/** The ending position of the attribute value. */
GumboSourcePosition value_end;
} GumboAttribute;
/**
* Given a vector of GumboAttributes, look up the one with the specified name
* and return it, or NULL if no such attribute exists. This uses a
* case-insensitive match, as HTML is case-insensitive.
*/
GumboAttribute* gumbo_get_attribute(const GumboVector* attrs, const char* name);
/**
* Enum denoting the type of node. This determines the type of the node.v
* union.
*/
typedef enum {
/** Document node. v will be a GumboDocument. */
GUMBO_NODE_DOCUMENT,
/** Element node. v will be a GumboElement. */
GUMBO_NODE_ELEMENT,
/** Text node. v will be a GumboText. */
GUMBO_NODE_TEXT,
/** CDATA node. v will be a GumboText. */
GUMBO_NODE_CDATA,
/** Comment node. v. will be a GumboText, excluding comment delimiters. */
GUMBO_NODE_COMMENT,
/** Text node, where all contents is whitespace. v will be a GumboText. */
GUMBO_NODE_WHITESPACE
} GumboNodeType;
/**
* Forward declaration of GumboNode so it can be used recursively in
* GumboNode.parent.
*/
typedef struct GumboInternalNode GumboNode;
/** http://www.whatwg.org/specs/web-apps/current-work/complete/dom.html#quirks-mode */
typedef enum {
GUMBO_DOCTYPE_NO_QUIRKS,
GUMBO_DOCTYPE_QUIRKS,
GUMBO_DOCTYPE_LIMITED_QUIRKS
} GumboQuirksModeEnum;
/**
* Namespaces.
* Unlike in X(HT)ML, namespaces in HTML5 are not denoted by a prefix. Rather,
* anything inside an