github.com/qichengzx/mattermost-server@v4.5.1-0.20180604164826-2c75247c97d0+incompatible/utils/markdown/links.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package markdown 5 6 import ( 7 "unicode/utf8" 8 ) 9 10 func parseLinkDestination(markdown string, position int) (raw Range, next int, ok bool) { 11 if position >= len(markdown) { 12 return 13 } 14 15 if markdown[position] == '<' { 16 isEscaped := false 17 18 for offset, c := range []byte(markdown[position+1:]) { 19 if isEscaped { 20 isEscaped = false 21 if isEscapableByte(c) { 22 continue 23 } 24 } 25 26 if c == '\\' { 27 isEscaped = true 28 } else if c == '<' { 29 break 30 } else if c == '>' { 31 return Range{position + 1, position + 1 + offset}, position + 1 + offset + 1, true 32 } else if isWhitespaceByte(c) { 33 break 34 } 35 } 36 } 37 38 openCount := 0 39 isEscaped := false 40 for offset, c := range []byte(markdown[position:]) { 41 if isEscaped { 42 isEscaped = false 43 if isEscapableByte(c) { 44 continue 45 } 46 } 47 48 switch c { 49 case '\\': 50 isEscaped = true 51 case '(': 52 openCount++ 53 case ')': 54 if openCount < 1 { 55 return Range{position, position + offset}, position + offset, true 56 } 57 openCount-- 58 default: 59 if isWhitespaceByte(c) { 60 return Range{position, position + offset}, position + offset, true 61 } 62 } 63 } 64 return Range{position, len(markdown)}, len(markdown), true 65 } 66 67 func parseLinkTitle(markdown string, position int) (raw Range, next int, ok bool) { 68 if position >= len(markdown) { 69 return 70 } 71 72 originalPosition := position 73 74 var closer byte 75 switch markdown[position] { 76 case '"', '\'': 77 closer = markdown[position] 78 case '(': 79 closer = ')' 80 default: 81 return 82 } 83 position++ 84 85 for position < len(markdown) { 86 switch markdown[position] { 87 case '\\': 88 position++ 89 if position < len(markdown) && isEscapableByte(markdown[position]) { 90 position++ 91 } 92 case closer: 93 return Range{originalPosition + 1, position}, position + 1, true 94 default: 95 position++ 96 } 97 } 98 99 return 100 } 101 102 func parseLinkLabel(markdown string, position int) (raw Range, next int, ok bool) { 103 if position >= len(markdown) || markdown[position] != '[' { 104 return 105 } 106 107 originalPosition := position 108 position++ 109 110 for position < len(markdown) { 111 switch markdown[position] { 112 case '\\': 113 position++ 114 if position < len(markdown) && isEscapableByte(markdown[position]) { 115 position++ 116 } 117 case '[': 118 return 119 case ']': 120 if position-originalPosition >= 1000 && utf8.RuneCountInString(markdown[originalPosition:position]) >= 1000 { 121 return 122 } 123 return Range{originalPosition + 1, position}, position + 1, true 124 default: 125 position++ 126 } 127 } 128 129 return 130 }