public override void WriteEndElement()
        {
            WriteStartElementEnd();
            if (_nodes.Count <= 0)
            {
                return;
            }

            var start = _nodes.Pop();

            if (_ignoreDepth > _nodes.Count)
            {
                _ignoreDepth = int.MaxValue;
            }

            switch (start.Value)
            {
            case "a":
                _minify = MinifyState.Compressed;
                if (_buffer != null)
                {
                    var text = _buffer.ToPool();
                    if (!string.IsNullOrEmpty(start["href"]))
                    {
                        _links.Add(new PlainTextLink()
                        {
                            Href   = start["href"],
                            Offset = _pos - text.Length,
                            Tag    = start,
                            Text   = text
                        });
                    }
                }
                _buffer = null;
                break;

            case "blockquote":
            case "h1":
            case "h2":
            case "h3":
            case "h4":
            case "h5":
            case "h6":
            case "ol":
            case "p":
            case "ul":
                EndBlock();
                break;

            case "pre":
                EndBlock();
                _preserveWhitespace = PreserveState.None;
                break;

            case "title":
                _metadata.Add(new KeyValuePair <string, string>("title", _buffer.ToPool()));
                _buffer = null;
                break;
            }
        }
示例#2
0
        private void WriteStartElementEnd()
        {
            if (_nodes.Count > 0 && _state == InternalState.Element)
            {
                var    start = _nodes.Peek();
                string buffer;
                switch (start.Value)
                {
                case "a":
                    buffer = null;
                    StartInline();
                    if (start.Attributes.Count > 0 &&
                        (!start.TryGetValue("href", out buffer) ||
                         string.IsNullOrEmpty(buffer)))
                    {
                        _writer.Write("<a ");
                        foreach (var attr in start)
                        {
                            _writer.Write(attr.Key);
                            if (!string.IsNullOrEmpty(attr.Value))
                            {
                                _writer.Write('=');
                                _writer.Write('"');
                                WriteEscaped(attr.Value);
                                _writer.Write('"');
                            }
                        }
                        _writer.Write('>');
                        _preserveWhitespace = PreserveState.HtmlEncoding;
                    }
                    else if (!string.IsNullOrEmpty(buffer))
                    {
                        _writer.Write('[');
                    }
                    break;

                case "img":
                    StartInline();
                    _writer.Write('!');
                    _writer.Write('[');
                    _writer.Write(start["alt"]);
                    _writer.Write(']');
                    _writer.Write('(');
                    _writer.Write(start["src"]);
                    if (start.TryGetValue("title", out buffer))
                    {
                        _writer.Write(' ');
                        _writer.Write('"');
                        _writer.Write(buffer);
                        _writer.Write('"');
                    }
                    _writer.Write(')');
                    _minify = MinifyState.Compressed;
                    break;

                default:
                    if (_settings.ShouldSkipElement(start))
                    {
                        _ignoreDepth = _nodes.Count;
                    }
                    break;
                }
                _state = InternalState.Content;
            }
        }
示例#3
0
        private void WriteInternal(string value)
        {
            WriteStartElementEnd();

            if (_ignoreDepth <= _nodes.Count)
            {
                return;
            }

            if (_preserveWhitespace == PreserveState.HtmlEncoding)
            {
                WriteEscaped(value);
                _outputStarted = true;
                return;
            }

            if (this._buffer != null)
            {
                this._buffer.Append(value);
            }
            else
            {
                for (var i = 0; i < value.Length; i++)
                {
                    if (_preserveWhitespace == PreserveState.InternalLineFeed)
                    {
                        _writer.Write(_settings.NewLineChars);
                        WritePrefix();
                        _preserveWhitespace = PreserveState.Preserve;
                    }

                    if (char.IsWhiteSpace(value[i]) && value[i] != '\u00A0')
                    {
                        if (_preserveWhitespace == PreserveState.BeforeContent &&
                            value[i] == Symbols.LineFeed)
                        {
                            _preserveWhitespace = PreserveState.Preserve;
                        }
                        else if (_preserveWhitespace != PreserveState.None)
                        {
                            if (value[i] == Symbols.LineFeed)
                            {
                                _preserveWhitespace = PreserveState.InternalLineFeed;
                            }
                            else
                            {
                                _writer.Write(value[i]);
                            }
                        }
                        else
                        {
                            if (_minify != MinifyState.LastCharWasSpace &&
                                _minify != MinifyState.BlockEnd)
                            {
                                _minify = MinifyState.SpaceNeeded;
                            }
                        }
                    }
                    else
                    {
                        switch (_minify)
                        {
                        case MinifyState.BlockEnd:
                            _writer.Write(_settings.NewLineChars);
                            _writer.Write(_settings.NewLineChars);
                            _minify = MinifyState.Compressed;
                            break;

                        case MinifyState.SpaceNeeded:
                            _writer.Write(' ');
                            _minify = MinifyState.Compressed;
                            break;

                        case MinifyState.LastCharWasSpace:
                            _minify = MinifyState.Compressed;
                            break;
                        }

                        if (_preserveWhitespace == PreserveState.None)
                        {
                            switch (value[i])
                            {
                            case '\\':
                            case '*':
                            case '[':
                            case '`':
                                _writer.Write('\\');
                                break;
                            }
                        }
                        else if (_preserveWhitespace == PreserveState.BeforeContent)
                        {
                            _preserveWhitespace = PreserveState.Preserve;
                        }
                        _writer.Write(value[i]);
                    }
                }
                _outputStarted = true;
            }
        }
示例#4
0
        /// <summary>
        /// Writes the specified start tag and associates it with the given namespace and prefix.
        /// </summary>
        /// <param name="prefix">The namespace prefix of the element.</param>
        /// <param name="localName">The local name of the element.</param>
        /// <param name="ns">The namespace URI to associate with the element.</param>
        public override void WriteStartElement(string prefix, string localName, string ns)
        {
            WriteStartElementEnd();
            var start = new HtmlStartTag(localName.ToLowerInvariant());

            _nodes.Push(start);
            switch (start.Value)
            {
            case "b":
            case "strong":
                StartInline();
                if (_boldDepth > _nodes.Count)
                {
                    _boldDepth = _nodes.Count;
                    _writer.Write("**");
                }
                break;

            case "blockquote":
                StartBlock("> ");
                break;

            case "br":
                _minify = MinifyState.LastCharWasSpace;
                switch (_preserveWhitespace)
                {
                case PreserveState.BeforeContent:
                    _preserveWhitespace = PreserveState.Preserve;
                    break;

                case PreserveState.InternalLineFeed:
                    _writer.Write(_settings.NewLineChars);
                    WritePrefix();
                    _preserveWhitespace = PreserveState.InternalLineFeed;
                    break;

                case PreserveState.None:
                    _writer.Write('\\');
                    _writer.Write(_settings.NewLineChars);
                    WritePrefix();
                    break;

                default:
                    _preserveWhitespace = PreserveState.InternalLineFeed;
                    break;
                }
                break;

            case "code":
                if (_preserveWhitespace == PreserveState.None)
                {
                    StartInline();
                    _writer.Write('`');
                }
                break;

            case "em":
            case "i":
                StartInline();
                if (_italicDepth > _nodes.Count)
                {
                    _italicDepth = _nodes.Count;
                    _writer.Write("*");
                }
                break;

            case "h1":
                StartBlock("# ");
                break;

            case "h2":
                StartBlock("## ");
                break;

            case "h3":
                StartBlock("### ");
                break;

            case "h4":
                StartBlock("#### ");
                break;

            case "h5":
                StartBlock("##### ");
                break;

            case "h6":
                StartBlock("###### ");
                break;

            case "hr":
                StartBlock("* * *");
                EndBlock();
                _writer.Write(_settings.NewLineChars);
                _minify = MinifyState.LastCharWasSpace;
                break;

            case "li":
                if (_outputStarted)
                {
                    _writer.Write(_settings.NewLineChars);
                }
                if (_linePrefix.Count > 0 &&
                    char.IsDigit(_linePrefix[_linePrefix.Count - 1][0]))
                {
                    var value = _linePrefix[_linePrefix.Count - 1];
                    value = string.Format("{0}. ", int.Parse(value.Substring(0, value.Length - 2)) + 1);
                    _linePrefix[_linePrefix.Count - 1] = value;
                }
                WritePrefix();
                _minify = MinifyState.LastCharWasSpace;
                break;

            case "p":
                StartBlock("");
                break;

            case "pre":
                StartBlock("    ");
                _preserveWhitespace = PreserveState.BeforeContent;
                break;

            case "ol":
                StartList("0. ");
                break;

            case "ul":
                StartList("- ");
                break;
            }
            _state = InternalState.Element;
        }
示例#5
0
        /// <summary>
        /// Closes one element and pops the corresponding namespace scope.
        /// </summary>
        public override void WriteEndElement()
        {
            WriteStartElementEnd();
            var start = _nodes.Pop();

            if (_ignoreDepth > _nodes.Count)
            {
                _ignoreDepth = int.MaxValue;
            }

            string buffer;

            switch (start.Value)
            {
            case "a":
                if (start.TryGetValue("href", out buffer))
                {
                    _writer.Write(']');
                    _writer.Write('(');
                    _writer.Write(buffer);
                    if (start.TryGetValue("title", out buffer))
                    {
                        _writer.Write(' ');
                        _writer.Write('"');
                        _writer.Write(buffer);
                        _writer.Write('"');
                    }
                    _writer.Write(')');
                }
                else if (start.Attributes.Count > 0)
                {
                    _writer.Write("</a>");
                    _preserveWhitespace = PreserveState.None;
                }
                _minify = MinifyState.Compressed;
                break;

            case "b":
            case "strong":
                if (_boldDepth > _nodes.Count)
                {
                    _writer.Write("**");
                    _boldDepth = int.MaxValue;
                }
                break;

            case "code":
                if (_preserveWhitespace == PreserveState.None)
                {
                    _writer.Write('`');
                }
                break;

            case "em":
            case "i":
                if (_italicDepth > _nodes.Count)
                {
                    _writer.Write("*");
                    _italicDepth = int.MaxValue;
                }
                break;

            case "blockquote":
            case "h1":
            case "h2":
            case "h3":
            case "h4":
            case "h5":
            case "h6":
            case "ol":
            case "p":
            case "ul":
                EndBlock();
                break;

            case "pre":
                EndBlock();
                _preserveWhitespace = PreserveState.None;
                break;
            }
        }
示例#6
0
        private void WriteStartElementEnd(string nextTag = null)
        {
            if (_nodes.Count > 0 && _state == InternalState.Element)
            {
                var    start = _nodes.Peek();
                string buffer;
                switch (start.Value)
                {
                case "a":
                    buffer = null;
                    StartInline();
                    if (start.Attributes.Count > 0 &&
                        (!start.TryGetValue("href", out buffer) ||
                         string.IsNullOrEmpty(buffer)))
                    {
                        _writer.Write("<a ");
                        foreach (var attr in start)
                        {
                            _writer.Write(attr.Key);
                            if (!string.IsNullOrEmpty(attr.Value))
                            {
                                _writer.Write('=');
                                _writer.Write('"');
                                WriteEscaped(attr.Value);
                                _writer.Write('"');
                            }
                        }
                        _writer.Write('>');
                        _preserveWhitespace = PreserveState.HtmlEncoding;
                    }
                    else if (!string.IsNullOrEmpty(buffer))
                    {
                        _writer.Write('[');
                        _writer.Write('"');
                        WriteAttributes(start, _writer);
                    }
                    break;

                case "blockquote":
                    StartBlock("bq", start);
                    if (start.TryGetValue("cite", out buffer))
                    {
                        _writer.Write(':');
                        _writer.Write(buffer);
                    }
                    break;

                case "b":
                    StartInline();
                    if (_boldDepth > _nodes.Count)
                    {
                        _boldDepth = _nodes.Count;
                        _writer.Write('*');
                        _writer.Write('*');
                        WriteAttributes(start, _writer);
                    }
                    break;

                case "strong":
                    StartInline();
                    if (_boldDepth > _nodes.Count)
                    {
                        _boldDepth = _nodes.Count;
                        _writer.Write('*');
                        WriteAttributes(start, _writer);
                    }
                    break;

                case "br":
                    _minify = MinifyState.LastCharWasSpace;
                    switch (_preserveWhitespace)
                    {
                    case PreserveState.BeforeContent:
                        _preserveWhitespace = PreserveState.Preserve;
                        break;

                    case PreserveState.InternalLineFeed:
                        _writer.Write(_settings.NewLineChars);
                        WritePrefix();
                        _preserveWhitespace = PreserveState.InternalLineFeed;
                        break;

                    case PreserveState.None:
                        _writer.Write(_settings.NewLineChars);
                        WritePrefix();
                        break;

                    default:
                        _preserveWhitespace = PreserveState.InternalLineFeed;
                        break;
                    }
                    break;

                case "cite":
                    StartInline();
                    _writer.Write('?');
                    _writer.Write('?');
                    WriteAttributes(start, _writer);
                    break;

                case "code":
                    if (_preserveWhitespace == PreserveState.None)
                    {
                        StartInline();
                        _writer.Write('@');
                        WriteAttributes(start, _writer);
                    }
                    break;

                case "del":
                    StartInline();
                    _writer.Write('[');
                    _writer.Write('-');
                    break;

                case "div":
                    StartBlock("div", start);
                    break;

                case "em":
                    StartInline();
                    if (_italicDepth > _nodes.Count)
                    {
                        _italicDepth = _nodes.Count;
                        _writer.Write('_');
                        WriteAttributes(start, _writer);
                    }
                    break;

                case "i":
                    StartInline();
                    if (_italicDepth > _nodes.Count)
                    {
                        _italicDepth = _nodes.Count;
                        _writer.Write('_');
                        _writer.Write('_');
                        WriteAttributes(start, _writer);
                    }
                    break;

                case "h1":
                    StartBlock("h1", start);
                    break;

                case "h2":
                    StartBlock("h2", start);
                    break;

                case "h3":
                    StartBlock("h3", start);
                    break;

                case "h4":
                    StartBlock("h4", start);
                    break;

                case "h5":
                    StartBlock("h5", start);
                    break;

                case "h6":
                    StartBlock("h6", start);
                    break;

                case "img":
                    StartInline();
                    _writer.Write('!');
                    WriteAttributes(start, _writer);
                    _writer.Write(start["src"]);
                    if (start.TryGetValue("alt", out buffer))
                    {
                        _writer.Write('(');
                        _writer.Write(buffer);
                        _writer.Write(')');
                    }
                    _writer.Write('!');
                    _minify = MinifyState.Compressed;
                    break;

                case "ins":
                    StartInline();
                    _writer.Write('[');
                    _writer.Write('+');
                    break;

                case "hr":
                    StartBlock("---", start);
                    EndBlock();
                    _writer.Write(_settings.NewLineChars);
                    _minify = MinifyState.LastCharWasSpace;
                    break;

                case "li":
                    if (_outputStarted)
                    {
                        _writer.Write(_settings.NewLineChars);
                    }
                    WritePrefix();
                    break;

                case "p":
                    StartBlock("", start);
                    break;

                case "pre":
                    if (nextTag == "code")
                    {
                        StartBlock("bc", start, true);
                    }
                    else
                    {
                        StartBlock("pre", start, true);
                    }
                    _preserveWhitespace = PreserveState.BeforeContent;
                    break;

                case "span":
                    _writer.Write('?');
                    WriteAttributes(start, _writer);
                    break;

                case "sub":
                    StartInline();
                    _writer.Write('[');
                    _writer.Write('~');
                    break;

                case "sup":
                    StartInline();
                    _writer.Write('[');
                    _writer.Write('^');
                    break;

                case "ol":
                    StartList("#");
                    break;

                case "ul":
                    StartList("*");
                    break;

                default:
                    if (_settings.ShouldSkipElement(start))
                    {
                        _ignoreDepth = _nodes.Count;
                    }
                    break;
                }
                _state = InternalState.Content;
            }
        }
示例#7
0
        public override void WriteEndElement()
        {
            WriteStartElementEnd();
            var start = _nodes.Pop();

            if (_ignoreDepth > _nodes.Count)
            {
                _ignoreDepth = int.MaxValue;
            }

            string buffer;

            switch (start.Value)
            {
            case "a":
                if (start.TryGetValue("href", out buffer))
                {
                    var href = buffer;
                    if (start.TryGetValue("title", out buffer))
                    {
                        _writer.Write('(');
                        _writer.Write(buffer);
                        _writer.Write(')');
                    }
                    _writer.Write('"');
                    _writer.Write(':');
                    _writer.Write(href);
                    _writer.Write(']');
                }
                else if (start.Attributes.Count > 0)
                {
                    _writer.Write("</a>");
                    _preserveWhitespace = PreserveState.None;
                }
                _minify = MinifyState.Compressed;
                break;

            case "acronym":
                if (start.TryGetValue("title", out buffer))
                {
                    _writer.Write('(');
                    _writer.Write(buffer);
                    _writer.Write(')');
                }
                break;

            case "b":
                if (_boldDepth > _nodes.Count)
                {
                    _writer.Write('*');
                    _writer.Write('*');
                    _boldDepth = int.MaxValue;
                }
                break;

            case "strong":
                if (_boldDepth > _nodes.Count)
                {
                    _writer.Write('*');
                    _boldDepth = int.MaxValue;
                }
                break;

            case "cite":
                _writer.Write('?');
                _writer.Write('?');
                break;

            case "code":
                if (_preserveWhitespace == PreserveState.None)
                {
                    _writer.Write('@');
                }
                break;

            case "del":
                _writer.Write('-');
                _writer.Write(']');
                break;

            case "em":
                if (_italicDepth > _nodes.Count)
                {
                    _writer.Write('_');
                    _italicDepth = int.MaxValue;
                }
                break;

            case "i":
                if (_italicDepth > _nodes.Count)
                {
                    _writer.Write('_');
                    _writer.Write('_');
                    _italicDepth = int.MaxValue;
                }
                break;

            case "ins":
                _writer.Write('+');
                _writer.Write(']');
                break;

            case "blockquote":
            case "h1":
            case "h2":
            case "h3":
            case "h4":
            case "h5":
            case "h6":
            case "p":
                EndBlock();
                break;

            case "ol":
            case "ul":
                EndBlock();
                if (_linePrefix.Count > 0)
                {
                    _linePrefix.RemoveAt(_linePrefix.Count - 1);
                }
                break;

            case "pre":
                EndBlock();
                _preserveWhitespace = PreserveState.None;
                _lastWasMultiline   = true;
                break;

            case "sub":
                _writer.Write('~');
                _writer.Write(']');
                break;

            case "sup":
                _writer.Write('^');
                _writer.Write(']');
                break;
            }
        }