Example #1
0
        /// <summary>
        /// Writes the specified Markdown object.
        /// </summary>
        /// <typeparam name="T">A MarkdownObject type</typeparam>
        /// <param name="obj">The Markdown object to write to this renderer.</param>
        public void Write <T>(T obj) where T : MarkdownObject
        {
            if (obj == null)
            {
                return;
            }

            var objectType = obj.GetType();

            // Calls before writing an object
            var writeBefore = ObjectWriteBefore;

            writeBefore?.Invoke(this, obj);

            // Handle regular renderers
            IMarkdownObjectRenderer renderer = previousObjectType == objectType ? previousRenderer : null;

            if (renderer == null && !renderersPerType.TryGetValue(objectType, out renderer))
            {
                for (int i = 0; i < ObjectRenderers.Count; i++)
                {
                    var testRenderer = ObjectRenderers[i];
                    if (testRenderer.Accept(this, obj))
                    {
                        renderersPerType[objectType] = renderer = testRenderer;
                        break;
                    }
                }
            }
            if (renderer != null)
            {
                renderer.Write(this, obj);
            }
            else
            {
                var containerBlock = obj as ContainerBlock;
                if (containerBlock != null)
                {
                    WriteChildren(containerBlock);
                }
                else
                {
                    var containerInline = obj as ContainerInline;
                    if (containerInline != null)
                    {
                        WriteChildren(containerInline);
                    }
                }
            }

            previousObjectType = objectType;
            previousRenderer   = renderer;

            // Calls after writing an object
            var writeAfter = ObjectWriteAfter;

            writeAfter?.Invoke(this, obj);
        }
Example #2
0
        /// <summary>
        /// Writes the specified Markdown object.
        /// </summary>
        /// <typeparam name="T">A MarkdownObject type</typeparam>
        /// <param name="obj">The Markdown object to write to this renderer.</param>
        /// <remarks>
        /// Write{T}(T obj) cannot be overridden. Therefore, copy 'n paste the complete impl
        /// of Render and modify it slightly so that errors are rendered.
        /// </remarks>
        public void WriteInternal <T>(T obj, bool isSummary = false) where T : MarkdownObject
        {
            if (obj == null)
            {
                return;
            }
            bool isError = false;

            if (obj is IExtensionBlock block && _blockErrors.ContainsKey(block))
            {
                if (!isSummary)
                {
                    var errors = _blockErrors[block];
                    var sb     = new StringBuilder();
                    sb.AppendLine("<ul class='error-list'>");
                    foreach (var error in errors.Errors)
                    {
                        sb.AppendLine("<li class='error'>");
                        IExtension extension     = _extensionByBlock[block];
                        string     extensionName = extension.GetType().Name;
                        var        parseError    = error as IParseError;
                        if (parseError != null)
                        {
                            sb.Append($@"<span class='Range'>{parseError.Range}</span> ");
                        }
                        sb.Append($@"<span class='extension-name'>{extensionName}:</span>");
                        sb.Append($@"<span class='message'>{error.Message}</span>");
                        sb.AppendLine("</li>");
                    }
                    sb.AppendLine("</ul>");
                    WriteLine(sb.ToString());
                }
                isError = true;
            }
            if (obj is IExtensionInline inline && _inlineErrors.ContainsKey(inline))
            {
                // TODO: implement and design a nice inline error visual
                isError = true;
            }

            if (!isError)
            {
                // Calls before writing an object
                //var writeBefore = ObjectWriteBefore;
                //ObjectWriteBefore?.Invoke(this, obj);

                // Handle regular renderers
                var  objectType         = obj.GetType();
                var  extensionBlock     = obj as IExtensionBlock;
                bool isSummaryExtension = extensionBlock != null &&
                                          _extensionByBlock.ContainsKey(extensionBlock) &&
                                          _extensionByBlock[extensionBlock].IsSummary;
                bool shouldRender = obj is MarkdownDocument ||
                                    (isSummary && isSummaryExtension) ||
                                    (!isSummary && !isSummaryExtension);

                IMarkdownObjectRenderer renderer = _previousObjectType == objectType ? _previousRenderer : null;
                if (renderer == null && !_renderersPerType.TryGetValue(objectType, out renderer))
                {
                    for (int i = 0; i < ObjectRenderers.Count; i++)
                    {
                        var testRenderer = ObjectRenderers[i];
                        if (testRenderer.Accept(this, obj))
                        {
                            _renderersPerType[objectType] = renderer = testRenderer;
                            break;
                        }
                    }
                }
                if (renderer != null && shouldRender)
                {
                    renderer.Write(this, obj);
                }
                else
                {
                    var containerBlock = obj as ContainerBlock;
                    if (containerBlock != null && shouldRender)
                    {
                        WriteChildrenInternal(containerBlock, isSummary);
                    }
                    else
                    {
                        var containerInline = obj as ContainerInline;
                        if (containerInline != null && shouldRender)
                        {
                            WriteChildrenInternal(containerInline);
                        }
                    }
                }

                _previousObjectType = objectType;
                _previousRenderer   = renderer;
            }

            // Calls after writing an object
            //var writeAfter = ObjectWriteAfter;
            //writeAfter?.Invoke(this, obj);
        }