/// <summary>
        /// Collapses internal whitespace to single space, removes leading/trailing whitespace, folds case.
        /// </summary>
        private static string NormalizeReference(StringPart s)
        {
            if (s.Length == 0)
                return string.Empty;

            return NormalizeWhitespace(s.Source, s.StartIndex, s.Length).ToUpperInvariant();
        }
        /// <summary>
        /// Adds a new reference to the dictionary, if the label does not already exist there.
        /// Assumes that the length of the label does not exceed <see cref="Reference.MaximumReferenceLabelLength"/>.
        /// </summary>
        private static void AddReference(Dictionary<string, Reference> refmap, StringPart label, string url, string title)
        {
            var normalizedLabel = NormalizeReference(label);
            if (refmap.ContainsKey(normalizedLabel))
                return;

            refmap.Add(normalizedLabel, new Reference(normalizedLabel, url, title));
        }
        /// <summary>
        /// Checks if the reference dictionary contains a reference with the given label and returns it,
        /// otherwise returns <c>null</c>.
        /// Returns <see cref="Reference.InvalidReference"/> if the reference label is not valid.
        /// </summary>
        private static Reference LookupReference(Dictionary<string, Reference> refmap, StringPart lab)
        {
            if (refmap == null)
                return null;

            if (lab.Length > Reference.MaximumReferenceLabelLength)
                return Reference.InvalidReference;

            string label = NormalizeReference(lab);

            Reference r;
            if (refmap.TryGetValue(label, out r))
                return r;

            return null;
        }
Esempio n. 4
0
        /// <summary>
        /// Checks if the reference dictionary contains a reference with the given label and returns it,
        /// otherwise returns <see langword="null"/>.
        /// Returns <see cref="Reference.InvalidReference"/> if the reference label is not valid.
        /// </summary>
        private static Reference LookupReference(DocumentData data, StringPart lab)
        {
            if (data?.ReferenceMap == null)
                return null;

            if (lab.Length > Reference.MaximumReferenceLabelLength)
                return Reference.InvalidReference;

            string label = NormalizeReference(lab);

            Reference r;
            if (data.ReferenceMap.TryGetValue(label, out r))
                return r;

            return null;
        }
Esempio n. 5
0
        public void Write(StringPart value)
        {
            if (value.Length == 0)
                return;

            if (this.Buffer.Length < value.Length)
                this.Buffer = new char[value.Length];

            value.Source.CopyTo(value.StartIndex, this.Buffer, 0, value.Length);

            if (this._windowsNewLine)
            {
                var lastPos = value.StartIndex;
                var pos = lastPos;

                while (-1 != (pos = value.Source.IndexOf('\n', pos, value.Length - pos + value.StartIndex)))
                {
                    var lastC = pos == 0 ? this._last : value.Source[pos - 1];

                    if (lastC != '\r')
                    {
                        this._inner.Write(this.Buffer, lastPos - value.StartIndex, pos - lastPos);
                        this._inner.Write('\r');
                        lastPos = pos;
                    }

                    pos++;
                }

                this._inner.Write(this.Buffer, lastPos - value.StartIndex, value.Length - lastPos + value.StartIndex);
            }
            else
            {
                this._inner.Write(this.Buffer, 0, value.Length);
            }

            this._last = this.Buffer[value.Length - 1];
        }
Esempio n. 6
0
 private void WriteEncodedHtml(StringPart text)
 {
     HtmlFormatterSlim.EscapeHtml(text, _target);
 }
Esempio n. 7
0
 private void Write(StringPart text)
 {
     _target.Write(text);
 }
Esempio n. 8
0
        private static Inline HandleRightSquareBracket(Subject subj, CommonMarkSettings settings)
        {
            // move past ']'
            subj.Position++;

            bool canClose;
            var istack = InlineStack.FindMatchingOpener(subj.LastPendingInline, InlineStack.InlineStackPriority.Links, '[', out canClose);

            if (istack != null)
            {
                // if the opener is "inactive" then it means that there was a nested link
                if (istack.DelimeterCount == -1)
                {
                    InlineStack.RemoveStackEntry(istack, subj, istack, settings.InlineParserParameters);
                    return new Inline("]", subj.Position - 1, subj.Position);
                }

                var endpos = subj.Position;

                // try parsing details for '[foo](/url "title")' or '[foo][bar]'
                var details = ParseLinkDetails(subj, settings);

                // try lookup of the brackets themselves
                if (details == null || details == Reference.SelfReference)
                {
                    var startpos = istack.StartPosition;
                    var label = new StringPart(subj.Buffer, startpos, endpos - startpos - 1);

                    details = LookupReference(subj.ReferenceMap, label, settings);
                }

                if (details == Reference.InvalidReference)
                    details = null;

                MatchSquareBracketStack(istack, subj, details, settings.InlineParserParameters);
                return null;
            }

            var inlText = new Inline("]", subj.Position - 1, subj.Position);

            if (canClose)
            {
                // note that the current implementation will not work if there are other inlines with priority
                // higher than Links.
                // to fix this the parsed link details should be added to the closer element in the stack.

                throw new NotSupportedException("It is not supported to have inline stack priority higher than Links.");

                ////istack = new InlineStack();
                ////istack.Delimeter = '[';
                ////istack.StartingInline = inlText;
                ////istack.StartPosition = subj.Position;
                ////istack.Priority = InlineStack.InlineStackPriority.Links;
                ////istack.Flags = InlineStack.InlineStackFlags.Closer;

                ////InlineStack.AppendStackEntry(istack, subj);
            }

            return inlText;
        }
Esempio n. 9
0
        /// <summary>
        /// Parses the contents of [..] for a reference label. Only used for parsing 
        /// reference definition labels for use with the reference dictionary because 
        /// it does not properly parse nested inlines.
        /// 
        /// Assumes the source starts with '[' character or spaces before '['.
        /// Returns null and does not advance if no matching ] is found.
        /// Note the precedence:  code backticks have precedence over label bracket
        /// markers, which have precedence over *, _, and other inline formatting
        /// markers. So, 2 below contains a link while 1 does not:
        /// 1. [a link `with a ](/url)` character
        /// 2. [a link *with emphasized ](/url) text*        /// </summary>
        private static StringPart? ParseReferenceLabel(Subject subj)
        {
            var startPos = subj.Position;
            var source = subj.Buffer;
            var len = subj.Length;

            while (subj.Position < len)
            {
                var c = subj.Buffer[subj.Position];
                if (c == ' ' || c == '\n')
                {
                    subj.Position++;
                    continue;
                }
                else if (c == '[')
                {
                    subj.Position++;
                    break;
                }
                else
                {
                    subj.Position = startPos;
                    return null;
                }
            }

            var labelStartPos = subj.Position;

            len = subj.Position + Reference.MaximumReferenceLabelLength;
            if (len > source.Length)
                len = source.Length;

            subj.Position = source.IndexOfAny(BracketSpecialCharacters, subj.Position, len - subj.Position);
            while (subj.Position > -1)
            {
                var c = source[subj.Position];
                if (c == '\\')
                {
                    subj.Position += 2;
                    if (subj.Position >= len)
                        break;

                    subj.Position = source.IndexOfAny(BracketSpecialCharacters, subj.Position, len - subj.Position);
                }
                else if (c == '[')
                {
                    break;
                }
                else
                {
                    var label = new StringPart(source, labelStartPos, subj.Position - labelStartPos);
                    subj.Position++;
                    return label;
                }
            }

            subj.Position = startPos;
            return null;
        }
Esempio n. 10
0
        /// <summary>
        /// Collapses internal whitespace to single space, removes leading/trailing whitespace, folds case.
        /// </summary>
        private static string NormalizeReference(StringPart s, CommonMarkSettings settings)
        {
            if (s.Length == 0)
                return string.Empty;

            var result = NormalizeWhitespace(s.Source, s.StartIndex, s.Length);
            if (0 == (settings.AdditionalFeatures & CommonMarkAdditionalFeatures.RespectReferenceCase))
                result = result.ToUpperInvariant();
            return result;
        }
        /// <summary>
        /// Escapes special HTML characters.
        /// </summary>
        /// <remarks>Orig: escape_html(inp, preserve_entities)</remarks>
        internal static void EscapeHtml(StringPart input, HtmlTextWriter target)
        {
            if (input.Length == 0)
                return;

            int pos;
            int lastPos = input.StartIndex;
            char[] buffer;

            if (target.Buffer.Length < input.Length)
                buffer = target.Buffer = new char[input.Length];
            else
                buffer = target.Buffer;
                 
            input.Source.CopyTo(input.StartIndex, buffer, 0, input.Length);

            while ((pos = input.Source.IndexOfAny(EscapeHtmlCharacters, lastPos, input.Length - lastPos + input.StartIndex)) != -1)
            {
                target.Write(buffer, lastPos - input.StartIndex, pos - lastPos);
                lastPos = pos + 1;

                switch (input.Source[pos])
                {
                    case '<':
                        target.WriteConstant(EscapeHtmlLessThan);
                        break;
                    case '>':
                        target.WriteConstant(EscapeHtmlGreaterThan);
                        break;
                    case '&':
                        target.WriteConstant(EscapeHtmlAmpersand);
                        break;
                    case '"':
                        target.WriteConstant(EscapeHtmlQuote);
                        break;
                }
            }

            target.Write(buffer, lastPos - input.StartIndex, input.Length - lastPos + input.StartIndex);
        }