// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. package markdown type ReferenceDefinition struct { RawDestination Range markdown string rawLabel string rawTitle string } func (d *ReferenceDefinition) Destination() string { return Unescape(d.markdown[d.RawDestination.Position:d.RawDestination.End]) } func (d *ReferenceDefinition) Label() string { return d.rawLabel } func (d *ReferenceDefinition) Title() string { return Unescape(d.rawTitle) } func parseReferenceDefinition(markdown string, ranges []Range) (*ReferenceDefinition, []Range) { raw := "" for _, r := range ranges { raw += markdown[r.Position:r.End] } label, next, ok := parseLinkLabel(raw, 0) if !ok { return nil, nil } position := next if position >= len(raw) || raw[position] != ':' { return nil, nil } position++ destination, next, ok := parseLinkDestination(raw, nextNonWhitespace(raw, position)) if !ok { return nil, nil } position = next absoluteDestination := relativeToAbsolutePosition(ranges, destination.Position) ret := &ReferenceDefinition{ RawDestination: Range{absoluteDestination, absoluteDestination + destination.End - destination.Position}, markdown: markdown, rawLabel: raw[label.Position:label.End], } if position < len(raw) && isWhitespaceByte(raw[position]) { title, next, ok := parseLinkTitle(raw, nextNonWhitespace(raw, position)) if !ok { if nextLine, skippedNonWhitespace := nextLine(raw, position); !skippedNonWhitespace { return ret, trimBytesFromRanges(ranges, nextLine) } return nil, nil } if nextLine, skippedNonWhitespace := nextLine(raw, next); !skippedNonWhitespace { ret.rawTitle = raw[title.Position:title.End] return ret, trimBytesFromRanges(ranges, nextLine) } } if nextLine, skippedNonWhitespace := nextLine(raw, position); !skippedNonWhitespace { return ret, trimBytesFromRanges(ranges, nextLine) } return nil, nil }