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  }