{"action":"created","comment":{"url":"https://api.github.com/repos/cocos-creator/engine/pulls/comments/76382061","id":76382061,"diff_hunk":"@@ -0,0 +1,664 @@\n+/****************************************************************************\n+ Copyright (c) 2013-2016 Chukong Technologies Inc.\n+\n+ http://www.cocos.com\n+\n+ Permission is hereby granted, free of charge, to any person obtaining a copy\n+ of this software and associated engine source code (the \"Software\"), a limited,\n+  worldwide, royalty-free, non-assignable, revocable and  non-exclusive license\n+ to use Cocos Creator solely to develop games on your target platforms. You shall\n+  not use Cocos Creator software for developing other software or tools that's\n+  used for developing games. You are not granted to publish, distribute,\n+  sublicense, and/or sell copies of Cocos Creator.\n+\n+ The software or tools in this License Agreement are licensed, not sold.\n+ Chukong Aipu reserves all rights not expressly granted to you.\n+\n+ THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n+ THE SOFTWARE.\n+ ****************************************************************************/\n+var HorizontalAlign = cc.TextAlignment;\n+var VerticalAlign = cc.VerticalTextAlignment;\n+\n+var label_wrapinspection = true;\n+var label_wordRex = /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+|\\S)/;\n+var label_symbolRex = /^[!,.:;}\\]%\\?>、‘“》？。，！]/;\n+var label_lastWordRex = /([a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+|\\S)$/;\n+var label_lastEnglish = /[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]+$/;\n+var label_firsrEnglish = /^[a-zA-Z0-9ÄÖÜäöüßéèçàùêâîôû]/;\n+\n+// Returns a function, that, as long as it continues to be invoked, will not\n+// be triggered. The function will be called after it stops being called for\n+// N milliseconds. If `immediate` is passed, trigger the function on the\n+// leading edge, instead of the trailing.\n+function debounce(func, wait, immediate) {\n+    var timeout;\n+    return function() {\n+        var context = this, args = arguments;\n+        var later = function() {\n+            timeout = null;\n+            if (!immediate) func.apply(context, args);\n+        };\n+        var callNow = immediate && !timeout;\n+        clearTimeout(timeout);\n+        timeout = setTimeout(later, wait);\n+        if (callNow) func.apply(context, args);\n+    };\n+}\n+\n+/**\n+ * !#en The RichText Component.\n+ * !#zh 富文本组件\n+ * @class RichText\n+ * @extends Component\n+ */\n+var RichText = cc.Class({\n+    name: 'cc.RichText',\n+    extends: cc._RendererUnderSG,\n+\n+    ctor: function() {\n+        this._textArray = null;\n+\n+        this._resetState();\n+    },\n+\n+    editor: CC_EDITOR && {\n+        menu: 'i18n:MAIN_MENU.component.renderers/RichText',\n+        help: 'i18n:COMPONENT.help_url.richtext',\n+    },\n+\n+\n+    properties: {\n+        _useOriginalSize: true,\n+        /**\n+         * !#en Content string of RichText.\n+         * !#zh 富文本显示的文本内容。\n+         * @property {String} string\n+         */\n+        string: {\n+            default: '<color=#00ff00>Rich</c><color=#0fffff>Text</color>',\n+            multiline: true,\n+            tooltip: 'i18n:COMPONENT.richtext.string',\n+            notify: function () {\n+                this._updateRichTextStatus();\n+            }\n+        },\n+\n+        /**\n+         * !#en Horizontal Alignment of each line in RichText.\n+         * !#zh 文本内容的水平对齐方式。\n+         * @property {RichText.HorizontalAlign} horizontalAlign\n+         */\n+        horizontalAlign: {\n+            default: HorizontalAlign.LEFT,\n+            type: HorizontalAlign,\n+            tooltip: 'i18n:COMPONENT.richtext.horizontal_align',\n+            animatable: false,\n+            notify: function () {\n+                this._layoutDirty = true;\n+                this._updateRichTextStatus();\n+            }\n+        },\n+\n+        /**\n+         * !#en Font size of RichText.\n+         * !#zh 富文本字体大小。\n+         * @property {Number} fontSize\n+         */\n+        fontSize: {\n+            default: 40,\n+            tooltip: 'i18n:COMPONENT.richtext.font_size',\n+            notify: function () {\n+                this._layoutDirty = true;\n+                this._updateRichTextStatus();\n+            }\n+        },\n+\n+        /**\n+         * !#en The maximize width of the RichText\n+         * !#zh 富文本的最大宽度\n+         * @property {Number} maxWidth\n+         */\n+        maxWidth: {\n+            default: 0,\n+            tooltip: 'i18n:COMPONENT.richtext.max_width',\n+            notify: function () {\n+                this._layoutDirty = true;\n+                this._updateRichTextStatus();\n+            }\n+        },\n+\n+        /**\n+         * !#en Line Height of RichText.\n+         * !#zh 富文本行高。\n+         * @property {Number} lineHeight\n+         */\n+        lineHeight: {\n+            default: 40,\n+            tooltip: 'i18n:COMPONENT.richtext.line_height',\n+            notify: function () {\n+                this._layoutDirty = true;\n+                this._updateRichTextStatus();\n+            }\n+        }\n+    },\n+\n+    _updateRichTextStatus: function () {\n+        if(this._sgNode) {\n+            if(CC_EDITOR) {\n+                this._debouncedUpdateRichText();\n+            } else {\n+                this._updateRichText();\n+            }\n+        }\n+    },\n+\n+    statics: {\n+        HorizontalAlign: HorizontalAlign,\n+        VerticalAlign: VerticalAlign\n+    },\n+\n+    _createSgNode: function () {\n+        return null;\n+    },\n+\n+    __preload: function () {\n+        this._super();\n+        if(CC_EDITOR) {\n+            this._debouncedUpdateRichText = debounce(this._updateRichText, 200);\n+        } else {\n+            this._registerEvents();\n+        }\n+\n+    },\n+\n+    _updateLabelSegmentTextAttributes: function() {\n+        this._labelSegments.forEach(function(item) {\n+            this._applyTextAttribute(item);\n+        }.bind(this));\n+    },\n+\n+    _initSgNode: function () {\n+\n+        this._resetState();\n+\n+        var sgNode = this._sgNode = new _ccsg.Node();\n+        sgNode.setVisible(false);\n+        sgNode.setCascadeOpacityEnabled(true);\n+\n+        var self = this;\n+        sgNode.setColor = function () {\n+            self._updateLabelSegmentTextAttributes();\n+        };\n+\n+        sgNode._setContentSize = sgNode.setContentSize;\n+        sgNode.setContentSize = function () {};\n+\n+        this._updateRichText();\n+\n+        if(CC_JSB) {\n+            sgNode.retain();\n+        }\n+    },\n+\n+    _computeAlignmentOffset: function() {\n+        this._linesOffsetX = [];\n+        switch (this.horizontalAlign) {\n+          case cc.TextAlignment.LEFT:\n+              for (var i = 0; i < this._lineCount; ++i) {\n+                  this._linesOffsetX.push(0);\n+              }\n+              break;\n+          case cc.TextAlignment.CENTER:\n+              this._linesWidth.forEach(function(lineWidth) {\n+                  this._linesOffsetX.push((this._labelWidth - lineWidth) / 2);\n+              }.bind(this));\n+              break;\n+          case cc.TextAlignment.RIGHT:\n+              this._linesWidth.forEach(function(lineWidth) {\n+                  this._linesOffsetX.push(this._labelWidth - lineWidth);\n+              }.bind(this));\n+              break;\n+          default:\n+              break;\n+        }\n+    },\n+\n+    _measureText: function (string, styleIndex) {\n+        var label = new _ccsg.Label(string);\n+        label._styleIndex = styleIndex;\n+        this._applyTextAttribute(label);\n+        var labelSize = label.getContentSize();\n+        return labelSize.width;\n+    },\n+\n+\n+    _onTouchEnded: function (event) {\n+        if(!this.enabledInHierarchy) return;\n+\n+        var components = this.node.getComponents(cc.Component);\n+\n+        for (var i = 0; i < this._labelSegments.length; ++i ) {\n+            var labelSegment = this._labelSegments[i];\n+            var clickHandler = labelSegment._clickHandler;\n+            if (clickHandler && this._containsTouchLocation(labelSegment, event.touch.getLocation())) {\n+                components.forEach(function(component) {\n+                    if(component.enabledInHierarchy && component[clickHandler]) {\n+                        component[clickHandler](event);\n+                    }\n+                });\n+            }\n+        }\n+    },\n+\n+    _containsTouchLocation:function (label, point) {\n+        var myRect = label.getBoundingBoxToWorld();\n+\n+        return cc.rectContainsPoint(myRect, point);\n+    },\n+\n+    _registerEvents: function () {\n+        this.node.on(cc.Node.EventType.TOUCH_END, this._onTouchEnded, this);\n+    },\n+\n+    _fragmentText: function (stringToken, allWidth, styleIndex) {\n+        //check the first character\n+        var wrappedWords = [];\n+        //fast return if strArr is empty\n+        if(stringToken.length === 0 || this.maxWidth < 0) {\n+            wrappedWords.push('');\n+            return wrappedWords;\n+        }\n+\n+        var text = stringToken;\n+        while (allWidth > this.maxWidth && text.length > 1) {\n+\n+            var fuzzyLen = text.length * ( this.maxWidth / allWidth ) | 0;\n+            var tmpText = text.substr(fuzzyLen);\n+            var width = allWidth - this._measureText(tmpText, styleIndex);\n+            var sLine = tmpText;\n+            var pushNum = 0;\n+\n+            var checkWhile = 0;\n+            var checkCount = 10;\n+\n+            //Exceeded the size\n+            while (width > this.maxWidth && checkWhile++ < checkCount) {\n+                fuzzyLen *= this.maxWidth / width;\n+                fuzzyLen = fuzzyLen | 0;\n+                tmpText = text.substr(fuzzyLen);\n+                width = allWidth - this._measureText(tmpText, styleIndex);\n+            }\n+\n+            checkWhile = 0;\n+\n+            //Find the truncation point\n+            while (width < this.maxWidth && checkWhile++ < checkCount) {\n+                if (tmpText) {\n+                    var exec = label_wordRex.exec(tmpText);\n+                    pushNum = exec ? exec[0].length : 1;\n+                    sLine = tmpText;\n+                }\n+\n+                fuzzyLen = fuzzyLen + pushNum;\n+                tmpText = text.substr(fuzzyLen);\n+                width = allWidth - this._measureText(tmpText, styleIndex);\n+            }\n+\n+            fuzzyLen -= pushNum;\n+            if (fuzzyLen === 0) {\n+                fuzzyLen = 1;\n+                sLine = sLine.substr(1);\n+            }\n+\n+            var sText = text.substr(0, fuzzyLen), result;\n+\n+            //symbol in the first\n+            if (label_wrapinspection) {\n+                if (label_symbolRex.test(sLine || tmpText)) {\n+                    result = label_lastWordRex.exec(sText);\n+                    fuzzyLen -= result ? result[0].length : 0;\n+                    if (fuzzyLen === 0) fuzzyLen = 1;\n+\n+                    sLine = text.substr(fuzzyLen);\n+                    sText = text.substr(0, fuzzyLen);\n+                }\n+            }\n+\n+            //To judge whether a English words are truncated\n+            if (label_firsrEnglish.test(sLine)) {\n+                result = label_lastEnglish.exec(sText);\n+                if (result && sText !== result[0]) {\n+                    fuzzyLen -= result[0].length;\n+                    sLine = text.substr(fuzzyLen);\n+                    sText = text.substr(0, fuzzyLen);\n+                }\n+            }\n+            if (sText.trim().length > 0) {\n+                wrappedWords.push(sText);\n+            }\n+            text = sLine || tmpText;\n+            allWidth = this._measureText(text, styleIndex);\n+        }\n+        if (text.length > 0) {\n+            wrappedWords.push(text);\n+        }\n+\n+        return wrappedWords;\n+    },\n+\n+    _resetState: function () {\n+        var sgNode = this._sgNode;\n+        if(sgNode) {\n+            sgNode.removeAllChildren();\n+        }\n+\n+        this._labelSegments = [];\n+        this._linesWidth = [];\n+        this._lineOffsetX = 0;\n+        this._lineCount = 1;\n+        this._labelWidth = 0;\n+        this._labelHeight = 0;\n+        this._layoutDirty = true;\n+    },\n+\n+    _addLabelSegment: function(stringToken, styleIndex) {\n+        var labelSegment = new _ccsg.Label(stringToken);\n+        labelSegment._styleIndex = styleIndex;\n+        labelSegment._lineCount = this._lineCount;\n+\n+        this._applyTextAttribute(labelSegment);\n+\n+        labelSegment.setAnchorPoint(cc.p(0, 0));\n+        this._sgNode.addChild(labelSegment);\n+        this._labelSegments.push(labelSegment);\n+\n+        if(CC_JSB) {\n+            labelSegment.setOverflow(1);\n+            var size = labelSegment.getContentSize();\n+            labelSegment.setContentSize(size.width, this.lineHeight);\n+        }\n+\n+        return labelSegment;\n+    },\n+\n+    _updateRichTextWithMaxWidth: function (labelString, labelWidth, styleIndex) {\n+        var fragmentWidth = labelWidth;\n+        var labelSegment;\n+\n+        if (this._lineOffsetX > 0 && fragmentWidth + this._lineOffsetX > this.maxWidth) {\n+            //concat previous line\n+            var checkStartIndex = 0;\n+            while (this._lineOffsetX < this.maxWidth) {\n+                var checkEndIndex = this._getFirstWordLen(labelString, checkStartIndex, labelString.length);\n+                var checkString = labelString.substr(checkStartIndex, checkEndIndex);\n+                var checkStringWidth = this._measureText(checkString, styleIndex);\n+\n+                if(this._lineOffsetX + checkStringWidth < this.maxWidth) {\n+                    this._lineOffsetX += checkStringWidth;\n+                    checkStartIndex += checkEndIndex;\n+                } else {\n+\n+                    if(checkStartIndex > 0) {\n+                        var remainingString = labelString.substr(0, checkStartIndex);\n+\n+                        this._addLabelSegment(remainingString, styleIndex);\n+\n+                        labelString = labelString.substr(checkStartIndex, labelString.length);\n+                        fragmentWidth = this._measureText(labelString, styleIndex);\n+                    }\n+                    this._updateLineInfo();\n+                    break;\n+                }\n+            }\n+        }\n+        if(fragmentWidth > this.maxWidth) {\n+            var fragments = this._fragmentText(labelString, fragmentWidth, styleIndex);\n+            for(var k = 0; k < fragments.length; ++k) {\n+                var splitString = fragments[k];\n+\n+                labelSegment =  this._addLabelSegment(splitString, styleIndex);\n+\n+                var labelSize = labelSegment.getContentSize();\n+\n+                this._lineOffsetX += labelSize.width;\n+\n+                if(fragments.length > 1 && k < fragments.length - 1) {\n+                    this._updateLineInfo();\n+                }\n+            }\n+        } else {\n+            this._lineOffsetX += fragmentWidth;\n+\n+            this._addLabelSegment(labelString, styleIndex);\n+        }\n+\n+    },\n+\n+    _isLastComponentCR: function(stringToken) {\n+        return stringToken.length -1 === stringToken.lastIndexOf(\"\\n\");\n+    },\n+\n+    _updateLineInfo: function () {\n+        this._linesWidth.push(this._lineOffsetX);\n+        this._lineOffsetX = 0;\n+        this._lineCount++;\n+    },\n+\n+    _needsUpdateTextLayout: function (newTextArray) {\n+        if(this._layoutDirty || !this._textArray || !newTextArray) {\n+            return true;\n+        }\n+\n+        if(this._textArray.length !== newTextArray.length) {\n+            return true;\n+        }\n+\n+        for(var i = 0; i < this._textArray.length; ++i) {\n+            var oldItem = this._textArray[i];\n+            var newItem = newTextArray[i];\n+            if(oldItem.text != newItem.text) {\n+                return true;\n+            } else {\n+                if (oldItem.style) {\n+                    if (newItem.style) {\n+                        //TODO: add more when adding bold/italic/underline\n+                        if(oldItem.style.size != newItem.style.size) {\n+                            return true;\n+                        }\n+                    } else {\n+                        if(oldItem.style.size) {\n+                            return true;\n+                        }\n+                    }\n+                } else {\n+                    if (newItem.style) {\n+                        if(newItem.style.size) {\n+                            return true;\n+                        }\n+                    }\n+                }\n+            }\n+        }\n+        return false;\n+    },\n+\n+    _updateRichText: function () {\n+        var newTextArray = cc.htmlTextParser.parse(this.string);\n+        if(!this._needsUpdateTextLayout(newTextArray)) {\n+            this._textArray = newTextArray;\n+            this._updateLabelSegmentTextAttributes();\n+            return;\n+        }\n+\n+        this._textArray = newTextArray;\n+        var sgNode = this._sgNode;\n+        this._resetState();\n+\n+        var lastEmptyLine = false;\n+        var label;\n+        var labelSize;\n+\n+        for (var i = 0; i < this._textArray.length; ++i) {\n+            var text = this._textArray[i].text;\n+            var multilineTexts = text.split(\"\\n\");\n+\n+            for (var j = 0; j < multilineTexts.length; ++j) {\n+                var labelString = multilineTexts[j];\n+                if(labelString === \"\") {\n+                    //for continues \\n\n+                    if(this._isLastComponentCR(text) && j == multilineTexts.length - 1) {\n+                        continue;\n+                    }\n+                    this._updateLineInfo();\n+                    lastEmptyLine = true;\n+                    continue;\n+                }\n+                lastEmptyLine = false;\n+\n+                if(this.maxWidth > 0) {\n+                    var labelWidth = this._measureText(labelString, i);\n+                    this._updateRichTextWithMaxWidth(labelString, labelWidth, i);\n+\n+                    if(multilineTexts.length > 1 && j < multilineTexts.length - 1) {\n+                        this._updateLineInfo();\n+                    }\n+                } else {\n+                    label = this._addLabelSegment(labelString, i);\n+                    labelSize = label.getContentSize();\n+\n+                    this._lineOffsetX += labelSize.width;\n+                    if(this._lineOffsetX > this._labelWidth) {\n+                        this._labelWidth = this._lineOffsetX;\n+                    }\n+\n+                    if(multilineTexts.length > 1 && j < multilineTexts.length - 1) {\n+                        this._updateLineInfo();\n+                    }\n+                }\n+            }\n+        }\n+        if(!lastEmptyLine) {\n+            this._linesWidth.push(this._lineOffsetX);\n+        }\n+\n+        if(this.maxWidth > 0) {\n+            this._labelWidth = this.maxWidth;\n+        }\n+        this._labelHeight =this._lineCount * this.lineHeight;\n+\n+        sgNode._setContentSize(cc.size(this._labelWidth, this._labelHeight));\n+\n+        this._updateRichTextPosition();\n+        this._layoutDirty = false;\n+    },\n+\n+    _isCJK_unicode: function(ch) {\n+        var __CHINESE_REG = /^[\\u4E00-\\u9FFF\\u3400-\\u4DFF]+$/;\n+        var __JAPANESE_REG = /[\\u3000-\\u303F]|[\\u3040-\\u309F]|[\\u30A0-\\u30FF]|[\\uFF00-\\uFFEF]|[\\u4E00-\\u9FAF]|[\\u2605-\\u2606]|[\\u2190-\\u2195]|\\u203B/g;\n+        var __KOREAN_REG = /^[\\u1100-\\u11FF]|[\\u3130-\\u318F]|[\\uA960-\\uA97F]|[\\uAC00-\\uD7AF]|[\\uD7B0-\\uD7FF]+$/;\n+        return __CHINESE_REG.test(ch) || __JAPANESE_REG.test(ch) || __KOREAN_REG.test(ch);\n+    },\n+\n+    //Checking whether the character is a whitespace\n+    _isspace_unicode: function(ch) {\n+        ch = ch.charCodeAt(0);\n+        return ((ch >= 9 && ch <= 13) || ch === 32 || ch === 133 || ch === 160 || ch === 5760 || (ch >= 8192 && ch <= 8202) || ch === 8232 || ch === 8233 || ch === 8239 || ch === 8287 || ch === 12288);\n+    },\n+\n+    _getFirstWordLen: function(text, startIndex, textLen) {\n+        var character = text.charAt(startIndex);\n+        if (this._isCJK_unicode(character) || this._isspace_unicode(character)) {\n+            return 1;\n+        }\n+\n+        var len = 1;\n+        for (var index = startIndex + 1; index < textLen; ++index) {\n+            character = text.charAt(index);\n+            if (this._isspace_unicode(character) || this._isCJK_unicode(character)) {\n+                break;\n+            }\n+            len++;\n+        }\n+\n+        return len;\n+    },\n+\n+    _updateRichTextPosition: function () {\n+        this._computeAlignmentOffset();\n+\n+        var nextTokenX = 0;\n+        var nextLineIndex = 1;\n+        var totalLineCount = this._lineCount;\n+        for(var i = 0; i < this._labelSegments.length; ++i) {\n+            var label = this._labelSegments[i];\n+            var lineCount = label._lineCount;\n+            if (lineCount > nextLineIndex) {\n+                nextTokenX = 0;\n+                nextLineIndex = lineCount;\n+            }\n+            var lineOffsetX = this._linesOffsetX[lineCount - 1];","path":"cocos2d/core/components/CCRichText.js","position":605,"original_position":605,"commit_id":"ad3cf8076ddad9c52fbda672c2839b33870ad60f","original_commit_id":"ad3cf8076ddad9c52fbda672c2839b33870ad60f","user":{"login":"zilongshanren","id":785541,"avatar_url":"https://avatars.githubusercontent.com/u/785541?v=3","gravatar_id":"","url":"https://api.github.com/users/zilongshanren","html_url":"https://github.com/zilongshanren","followers_url":"https://api.github.com/users/zilongshanren/followers","following_url":"https://api.github.com/users/zilongshanren/following{/other_user}","gists_url":"https://api.github.com/users/zilongshanren/gists{/gist_id}","starred_url":"https://api.github.com/users/zilongshanren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zilongshanren/subscriptions","organizations_url":"https://api.github.com/users/zilongshanren/orgs","repos_url":"https://api.github.com/users/zilongshanren/repos","events_url":"https://api.github.com/users/zilongshanren/events{/privacy}","received_events_url":"https://api.github.com/users/zilongshanren/received_events","type":"User","site_admin":false},"body":"恩 放在这里计算也可以，节约一点内存。","created_at":"2016-08-26T08:25:34Z","updated_at":"2016-08-26T08:25:34Z","html_url":"https://github.com/cocos-creator/engine/pull/1046#discussion_r76382061","pull_request_url":"https://api.github.com/repos/cocos-creator/engine/pulls/1046","_links":{"self":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/comments/76382061"},"html":{"href":"https://github.com/cocos-creator/engine/pull/1046#discussion_r76382061"},"pull_request":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/1046"}}},"pull_request":{"url":"https://api.github.com/repos/cocos-creator/engine/pulls/1046","id":81434277,"html_url":"https://github.com/cocos-creator/engine/pull/1046","diff_url":"https://github.com/cocos-creator/engine/pull/1046.diff","patch_url":"https://github.com/cocos-creator/engine/pull/1046.patch","issue_url":"https://api.github.com/repos/cocos-creator/engine/issues/1046","number":1046,"state":"open","locked":false,"title":"[WIP] Add RichText Support","user":{"login":"zilongshanren","id":785541,"avatar_url":"https://avatars.githubusercontent.com/u/785541?v=3","gravatar_id":"","url":"https://api.github.com/users/zilongshanren","html_url":"https://github.com/zilongshanren","followers_url":"https://api.github.com/users/zilongshanren/followers","following_url":"https://api.github.com/users/zilongshanren/following{/other_user}","gists_url":"https://api.github.com/users/zilongshanren/gists{/gist_id}","starred_url":"https://api.github.com/users/zilongshanren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zilongshanren/subscriptions","organizations_url":"https://api.github.com/users/zilongshanren/orgs","repos_url":"https://api.github.com/users/zilongshanren/repos","events_url":"https://api.github.com/users/zilongshanren/events{/privacy}","received_events_url":"https://api.github.com/users/zilongshanren/received_events","type":"User","site_admin":false},"body":"Re: cocos-creator/fireball#3448\r\n\r\nChanges proposed in this pull request:\r\n - [x] add bbcode parser\r\n - [x] add color/size/\r\n - [x] add event support\r\n -  [x] add example cases : cocos-creator/example-cases#228\r\n -  [x] add i18n, panel tooltip and prefab\r\n -  [ ] add docs\r\n\r\n\r\n@cocos-creator/engine-admins\r\n","created_at":"2016-08-16T08:42:48Z","updated_at":"2016-08-26T08:25:34Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b277c1681931520972f837d06520362fc0228651","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/cocos-creator/engine/pulls/1046/commits","review_comments_url":"https://api.github.com/repos/cocos-creator/engine/pulls/1046/comments","review_comment_url":"https://api.github.com/repos/cocos-creator/engine/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cocos-creator/engine/issues/1046/comments","statuses_url":"https://api.github.com/repos/cocos-creator/engine/statuses/ad3cf8076ddad9c52fbda672c2839b33870ad60f","head":{"label":"zilongshanren:fix-issue-3615","ref":"fix-issue-3615","sha":"ad3cf8076ddad9c52fbda672c2839b33870ad60f","user":{"login":"zilongshanren","id":785541,"avatar_url":"https://avatars.githubusercontent.com/u/785541?v=3","gravatar_id":"","url":"https://api.github.com/users/zilongshanren","html_url":"https://github.com/zilongshanren","followers_url":"https://api.github.com/users/zilongshanren/followers","following_url":"https://api.github.com/users/zilongshanren/following{/other_user}","gists_url":"https://api.github.com/users/zilongshanren/gists{/gist_id}","starred_url":"https://api.github.com/users/zilongshanren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zilongshanren/subscriptions","organizations_url":"https://api.github.com/users/zilongshanren/orgs","repos_url":"https://api.github.com/users/zilongshanren/repos","events_url":"https://api.github.com/users/zilongshanren/events{/privacy}","received_events_url":"https://api.github.com/users/zilongshanren/received_events","type":"User","site_admin":false},"repo":{"id":54608207,"name":"engine","full_name":"zilongshanren/engine","owner":{"login":"zilongshanren","id":785541,"avatar_url":"https://avatars.githubusercontent.com/u/785541?v=3","gravatar_id":"","url":"https://api.github.com/users/zilongshanren","html_url":"https://github.com/zilongshanren","followers_url":"https://api.github.com/users/zilongshanren/followers","following_url":"https://api.github.com/users/zilongshanren/following{/other_user}","gists_url":"https://api.github.com/users/zilongshanren/gists{/gist_id}","starred_url":"https://api.github.com/users/zilongshanren/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zilongshanren/subscriptions","organizations_url":"https://api.github.com/users/zilongshanren/orgs","repos_url":"https://api.github.com/users/zilongshanren/repos","events_url":"https://api.github.com/users/zilongshanren/events{/privacy}","received_events_url":"https://api.github.com/users/zilongshanren/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/zilongshanren/engine","description":"The engine for Cocos Creator","fork":true,"url":"https://api.github.com/repos/zilongshanren/engine","forks_url":"https://api.github.com/repos/zilongshanren/engine/forks","keys_url":"https://api.github.com/repos/zilongshanren/engine/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zilongshanren/engine/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zilongshanren/engine/teams","hooks_url":"https://api.github.com/repos/zilongshanren/engine/hooks","issue_events_url":"https://api.github.com/repos/zilongshanren/engine/issues/events{/number}","events_url":"https://api.github.com/repos/zilongshanren/engine/events","assignees_url":"https://api.github.com/repos/zilongshanren/engine/assignees{/user}","branches_url":"https://api.github.com/repos/zilongshanren/engine/branches{/branch}","tags_url":"https://api.github.com/repos/zilongshanren/engine/tags","blobs_url":"https://api.github.com/repos/zilongshanren/engine/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zilongshanren/engine/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zilongshanren/engine/git/refs{/sha}","trees_url":"https://api.github.com/repos/zilongshanren/engine/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zilongshanren/engine/statuses/{sha}","languages_url":"https://api.github.com/repos/zilongshanren/engine/languages","stargazers_url":"https://api.github.com/repos/zilongshanren/engine/stargazers","contributors_url":"https://api.github.com/repos/zilongshanren/engine/contributors","subscribers_url":"https://api.github.com/repos/zilongshanren/engine/subscribers","subscription_url":"https://api.github.com/repos/zilongshanren/engine/subscription","commits_url":"https://api.github.com/repos/zilongshanren/engine/commits{/sha}","git_commits_url":"https://api.github.com/repos/zilongshanren/engine/git/commits{/sha}","comments_url":"https://api.github.com/repos/zilongshanren/engine/comments{/number}","issue_comment_url":"https://api.github.com/repos/zilongshanren/engine/issues/comments{/number}","contents_url":"https://api.github.com/repos/zilongshanren/engine/contents/{+path}","compare_url":"https://api.github.com/repos/zilongshanren/engine/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zilongshanren/engine/merges","archive_url":"https://api.github.com/repos/zilongshanren/engine/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zilongshanren/engine/downloads","issues_url":"https://api.github.com/repos/zilongshanren/engine/issues{/number}","pulls_url":"https://api.github.com/repos/zilongshanren/engine/pulls{/number}","milestones_url":"https://api.github.com/repos/zilongshanren/engine/milestones{/number}","notifications_url":"https://api.github.com/repos/zilongshanren/engine/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zilongshanren/engine/labels{/name}","releases_url":"https://api.github.com/repos/zilongshanren/engine/releases{/id}","deployments_url":"https://api.github.com/repos/zilongshanren/engine/deployments","created_at":"2016-03-24T02:22:57Z","updated_at":"2016-03-24T02:23:01Z","pushed_at":"2016-08-26T06:48:30Z","git_url":"git://github.com/zilongshanren/engine.git","ssh_url":"git@github.com:zilongshanren/engine.git","clone_url":"https://github.com/zilongshanren/engine.git","svn_url":"https://github.com/zilongshanren/engine","homepage":"http://www.cocos2d-x.org/creator","size":24982,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"cocos-creator:master","ref":"master","sha":"b588dc20b8f5715585c348576f31ee1491865f20","user":{"login":"cocos-creator","id":6937061,"avatar_url":"https://avatars.githubusercontent.com/u/6937061?v=3","gravatar_id":"","url":"https://api.github.com/users/cocos-creator","html_url":"https://github.com/cocos-creator","followers_url":"https://api.github.com/users/cocos-creator/followers","following_url":"https://api.github.com/users/cocos-creator/following{/other_user}","gists_url":"https://api.github.com/users/cocos-creator/gists{/gist_id}","starred_url":"https://api.github.com/users/cocos-creator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cocos-creator/subscriptions","organizations_url":"https://api.github.com/users/cocos-creator/orgs","repos_url":"https://api.github.com/users/cocos-creator/repos","events_url":"https://api.github.com/users/cocos-creator/events{/privacy}","received_events_url":"https://api.github.com/users/cocos-creator/received_events","type":"Organization","site_admin":false},"repo":{"id":47440536,"name":"engine","full_name":"cocos-creator/engine","owner":{"login":"cocos-creator","id":6937061,"avatar_url":"https://avatars.githubusercontent.com/u/6937061?v=3","gravatar_id":"","url":"https://api.github.com/users/cocos-creator","html_url":"https://github.com/cocos-creator","followers_url":"https://api.github.com/users/cocos-creator/followers","following_url":"https://api.github.com/users/cocos-creator/following{/other_user}","gists_url":"https://api.github.com/users/cocos-creator/gists{/gist_id}","starred_url":"https://api.github.com/users/cocos-creator/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cocos-creator/subscriptions","organizations_url":"https://api.github.com/users/cocos-creator/orgs","repos_url":"https://api.github.com/users/cocos-creator/repos","events_url":"https://api.github.com/users/cocos-creator/events{/privacy}","received_events_url":"https://api.github.com/users/cocos-creator/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cocos-creator/engine","description":"The engine for Cocos Creator","fork":false,"url":"https://api.github.com/repos/cocos-creator/engine","forks_url":"https://api.github.com/repos/cocos-creator/engine/forks","keys_url":"https://api.github.com/repos/cocos-creator/engine/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cocos-creator/engine/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cocos-creator/engine/teams","hooks_url":"https://api.github.com/repos/cocos-creator/engine/hooks","issue_events_url":"https://api.github.com/repos/cocos-creator/engine/issues/events{/number}","events_url":"https://api.github.com/repos/cocos-creator/engine/events","assignees_url":"https://api.github.com/repos/cocos-creator/engine/assignees{/user}","branches_url":"https://api.github.com/repos/cocos-creator/engine/branches{/branch}","tags_url":"https://api.github.com/repos/cocos-creator/engine/tags","blobs_url":"https://api.github.com/repos/cocos-creator/engine/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cocos-creator/engine/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cocos-creator/engine/git/refs{/sha}","trees_url":"https://api.github.com/repos/cocos-creator/engine/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cocos-creator/engine/statuses/{sha}","languages_url":"https://api.github.com/repos/cocos-creator/engine/languages","stargazers_url":"https://api.github.com/repos/cocos-creator/engine/stargazers","contributors_url":"https://api.github.com/repos/cocos-creator/engine/contributors","subscribers_url":"https://api.github.com/repos/cocos-creator/engine/subscribers","subscription_url":"https://api.github.com/repos/cocos-creator/engine/subscription","commits_url":"https://api.github.com/repos/cocos-creator/engine/commits{/sha}","git_commits_url":"https://api.github.com/repos/cocos-creator/engine/git/commits{/sha}","comments_url":"https://api.github.com/repos/cocos-creator/engine/comments{/number}","issue_comment_url":"https://api.github.com/repos/cocos-creator/engine/issues/comments{/number}","contents_url":"https://api.github.com/repos/cocos-creator/engine/contents/{+path}","compare_url":"https://api.github.com/repos/cocos-creator/engine/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cocos-creator/engine/merges","archive_url":"https://api.github.com/repos/cocos-creator/engine/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cocos-creator/engine/downloads","issues_url":"https://api.github.com/repos/cocos-creator/engine/issues{/number}","pulls_url":"https://api.github.com/repos/cocos-creator/engine/pulls{/number}","milestones_url":"https://api.github.com/repos/cocos-creator/engine/milestones{/number}","notifications_url":"https://api.github.com/repos/cocos-creator/engine/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cocos-creator/engine/labels{/name}","releases_url":"https://api.github.com/repos/cocos-creator/engine/releases{/id}","deployments_url":"https://api.github.com/repos/cocos-creator/engine/deployments","created_at":"2015-12-05T03:28:59Z","updated_at":"2016-08-24T11:22:22Z","pushed_at":"2016-08-26T06:48:30Z","git_url":"git://github.com/cocos-creator/engine.git","ssh_url":"git@github.com:cocos-creator/engine.git","clone_url":"https://github.com/cocos-creator/engine.git","svn_url":"https://github.com/cocos-creator/engine","homepage":"http://www.cocos2d-x.org/creator","size":25793,"stargazers_count":105,"watchers_count":105,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":68,"mirror_url":null,"open_issues_count":15,"forks":68,"open_issues":15,"watchers":105,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/1046"},"html":{"href":"https://github.com/cocos-creator/engine/pull/1046"},"issue":{"href":"https://api.github.com/repos/cocos-creator/engine/issues/1046"},"comments":{"href":"https://api.github.com/repos/cocos-creator/engine/issues/1046/comments"},"review_comments":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/1046/comments"},"review_comment":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cocos-creator/engine/pulls/1046/commits"},"statuses":{"href":"https://api.github.com/repos/cocos-creator/engine/statuses/ad3cf8076ddad9c52fbda672c2839b33870ad60f"}}}}
{"actor":{"display_login":"zilongshanren"}}