コード例 #1
0
        public void Parse_NoCodesShouldBeUnchanged(
            ShortcodeParser sut
            )
        {
            const string content =
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus eu faucibus leo. Morbi ligula tellus, convallis non lorem vel, ultricies viverra diam. Pellentesque eget ligula eleifend, venenatis purus nec, tincidunt ante. Maecenas nec pellentesque lectus, vel bibendum sem. Sed eget vulputate lacus, mollis convallis massa. Quisque in ante ut turpis euismod elementum interdum in purus. Phasellus viverra nec est ut scelerisque.";

            var result = sut.Parse(null, content);

            result.ToString().Should().Be(content);
        }
コード例 #2
0
            public void ThrowsForExtraClosingContent()
            {
                // Given
                Stream stream = new MemoryStream(Encoding.UTF8.GetBytes("<?# foo ?>abc<?#/ foo bar ?>"));
                IShortcodeCollection shortcodeCollection = new TestShortcodeCollection();

                shortcodeCollection.Add("foo", typeof(TestShortcode));
                ShortcodeParser parser = new ShortcodeParser(
                    ShortcodeParser.DefaultStartDelimiter,
                    ShortcodeParser.DefaultEndDelimiter,
                    shortcodeCollection);

                // When, Then
                Should.Throw <ShortcodeParserException>(() => parser.Parse(stream));
            }
コード例 #3
0
            public void ThrowsForUnregisteredShortcodeName()
            {
                // Given
                Stream stream = new MemoryStream(Encoding.UTF8.GetBytes("<?# foo ?>abc<?#/ foo ?>"));
                IShortcodeCollection shortcodeCollection = new TestShortcodeCollection();

                shortcodeCollection.Add("bar", typeof(TestShortcode));
                ShortcodeParser parser = new ShortcodeParser(
                    ShortcodeParser.DefaultPostRenderStartDelimiter,
                    ShortcodeParser.DefaultPostRenderEndDelimiter,
                    shortcodeCollection);

                // When, Then
                Should.Throw <ShortcodeParserException>(() => parser.Parse(stream));
            }
コード例 #4
0
        public void Parse_MatchedContentIsReplaced(
            [Frozen] IRenderShortcode renderShortcode,
            ShortcodeParser sut,
            IHtmlHelper helper
            )
        {
            A.CallTo(() => renderShortcode.CanRender("test")).Returns(true);
            A.CallTo(() => renderShortcode.Render(helper, "test", A <Dictionary <string, string> > .Ignored))
            .Returns("Updated text");
            const string content = "[test]";

            var result = sut.Parse(helper, content);

            result.ToString().Should().Be("Updated text");
        }
コード例 #5
0
            public void ThrowsForExtraClosingContent()
            {
                // Given
                Stream          stream = new MemoryStream(Encoding.UTF8.GetBytes("<?# foo ?>abc<?#/ foo bar ?>"));
                ShortcodeParser parser = new ShortcodeParser(
                    ShortcodeParser.DefaultPostRenderStartDelimiter,
                    ShortcodeParser.DefaultPostRenderEndDelimiter,
                    new TestShortcodeCollection
                {
                    { "foo", (Type)null }
                });

                // When, Then
                Should.Throw <ShortcodeParserException>(() => parser.Parse(stream));
            }
コード例 #6
0
            public void ThrowsForUnterminatedShortcode(string input)
            {
                // Given
                Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
                IShortcodeCollection shortcodeCollection = new TestShortcodeCollection();

                shortcodeCollection.Add("foo", typeof(TestShortcode));
                shortcodeCollection.Add("bar", typeof(TestShortcode));
                ShortcodeParser parser = new ShortcodeParser(
                    ShortcodeParser.DefaultStartDelimiter,
                    ShortcodeParser.DefaultEndDelimiter,
                    shortcodeCollection);

                // When, Then
                Should.Throw <ShortcodeParserException>(() => parser.Parse(stream));
            }
コード例 #7
0
            public void ThrowsForUnterminatedShortcode(string input)
            {
                // Given
                Stream          stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
                ShortcodeParser parser = new ShortcodeParser(
                    ShortcodeParser.DefaultPostRenderStartDelimiter,
                    ShortcodeParser.DefaultPostRenderEndDelimiter,
                    new TestShortcodeCollection
                {
                    { "foo", (Type)null },
                    { "bar", (Type)null }
                });

                // When, Then
                Should.Throw <ShortcodeParserException>(() => parser.Parse(stream));
            }
コード例 #8
0
            public void TrimsWildcardProcessingInstructionFromContent(string input, string content)
            {
                // Given
                Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
                IShortcodeCollection shortcodeCollection = new TestShortcodeCollection();

                shortcodeCollection.Add("name", typeof(TestShortcode));
                ShortcodeParser parser = new ShortcodeParser(
                    ShortcodeParser.DefaultStartDelimiter,
                    ShortcodeParser.DefaultEndDelimiter,
                    shortcodeCollection);

                // When
                List <ShortcodeLocation> result = parser.Parse(stream);

                // Then
                result.Single().Content.ShouldBe(content);
            }
コード例 #9
0
        public void Parse_GetsAttributesFromShortcode(
            [Frozen] IRenderShortcode renderShortcode,
            ShortcodeParser sut,
            IHtmlHelper helper
            )
        {
            A.CallTo(() => renderShortcode.CanRender("test")).Returns(true);
            A.CallTo(() =>
                     renderShortcode.Render(helper, "test",
                                            A <Dictionary <string, string> > .That.Matches(
                                                dictionary => dictionary.ContainsKey("id") && dictionary["id"] == "123")))
            .Returns("Updated text");
            const string content = "[test id=\"123\"]";

            var result = sut.Parse(helper, content);

            result.ToString().Should().Be("Updated text");
        }
コード例 #10
0
            public void TrimsWildcardProcessingInstructionFromContent(string input, string content)
            {
                // Given
                Stream          stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
                ShortcodeParser parser = new ShortcodeParser(
                    ShortcodeParser.DefaultPostRenderStartDelimiter,
                    ShortcodeParser.DefaultPostRenderEndDelimiter,
                    new TestShortcodeCollection
                {
                    { "name", (Type)null }
                });

                // When
                List <ShortcodeLocation> result = parser.Parse(stream);

                // Then
                result.Single().Content.ShouldBe(content);
            }
コード例 #11
0
            public void FindsClosingShortcode(string input, int firstIndex, int lastIndex)
            {
                // Given
                Stream stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
                IShortcodeCollection shortcodeCollection = new TestShortcodeCollection();

                shortcodeCollection.Add("name", typeof(TestShortcode));
                ShortcodeParser parser = new ShortcodeParser(
                    ShortcodeParser.DefaultStartDelimiter,
                    ShortcodeParser.DefaultEndDelimiter,
                    shortcodeCollection);

                // When
                List <ShortcodeLocation> result = parser.Parse(stream);

                // Then
                result.Single().FirstIndex.ShouldBe(firstIndex);
                result.Single().LastIndex.ShouldBe(lastIndex);
            }
コード例 #12
0
            public void FindsClosingShortcode(string input, int firstIndex, int lastIndex)
            {
                // Given
                Stream          stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
                ShortcodeParser parser = new ShortcodeParser(
                    ShortcodeParser.DefaultPostRenderStartDelimiter,
                    ShortcodeParser.DefaultPostRenderEndDelimiter,
                    new TestShortcodeCollection
                {
                    { "name", (Type)null }
                });

                // When
                List <ShortcodeLocation> result = parser.Parse(stream);

                // Then
                result.Single().FirstIndex.ShouldBe(firstIndex);
                result.Single().LastIndex.ShouldBe(lastIndex);
            }
コード例 #13
0
        public void Parse_WithQuotes(
            [Frozen] IRenderShortcode renderShortcode,
            ShortcodeParser sut,
            IHtmlHelper helper
            )
        {
            var content = "[test id=\"123\"] sdfs adfsdf sdaf sadf asdfsdaf sdf sdf  more=(*&)(&knkjdhnf data]";


            A.CallTo(() => renderShortcode.CanRender("test")).Returns(true);
            A.CallTo(() =>
                     renderShortcode.Render(helper, "test ",
                                            A <Dictionary <string, string> > .That.Matches(
                                                dictionary =>
                                                dictionary.ContainsKey("id") && dictionary["id"] == "123"
                                                &&
                                                !dictionary.ContainsKey("more")
                                                )));

            var result = sut.Parse(helper, content);

            result.ToString().Should().Be(" sdfs adfsdf sdaf sadf asdfsdaf sdf sdf  more=(*&)(&knkjdhnf data]");
        }
コード例 #14
0
            public void SupportsAlternateDelimiters(
                string input,
                int firstIndex,
                int lastIndex,
                string startDelimiter,
                string endDelimiter)
            {
                // Given
                Stream          stream = new MemoryStream(Encoding.UTF8.GetBytes(input));
                ShortcodeParser parser = new ShortcodeParser(
                    startDelimiter,
                    endDelimiter,
                    new TestShortcodeCollection
                {
                    { "name", (Type)null }
                });

                // When
                List <ShortcodeLocation> result = parser.Parse(stream);

                // Then
                result.Single().FirstIndex.ShouldBe(firstIndex);
                result.Single().LastIndex.ShouldBe(lastIndex);
            }
コード例 #15
0
        // The inputStream will be disposed if this returns <c>true</c> but will not otherwise
        private bool ProcessShortcodes(Stream inputStream, IDocument input, IExecutionContext context, out IDocument result)
        {
            // Parse the input stream looking for shortcodes
            ShortcodeParser parser = new ShortcodeParser(_startDelimiter, _endDelimiter, context.Shortcodes);

            if (!inputStream.CanSeek)
            {
                inputStream = new SeekableStream(inputStream, true);
            }
            List <ShortcodeLocation> locations = parser.Parse(inputStream);

            // Reset the position because we're going to use the stream again when we do replacements
            inputStream.Position = 0;

            // Return the original document if we didn't find any
            if (locations.Count == 0)
            {
                result = null;
                return(false);
            }

            // Otherwise, create a shortcode instance for each named shortcode
            Dictionary <string, IShortcode> shortcodes =
                locations
                .Select(x => x.Name)
                .Distinct(StringComparer.OrdinalIgnoreCase)
                .ToDictionary(x => x, x => context.Shortcodes.CreateInstance(x), StringComparer.OrdinalIgnoreCase);

            // Execute each of the shortcodes in order
            List <InsertingStreamLocation> insertingLocations = locations
                                                                .Select(x =>
            {
                // Execute the shortcode
                IShortcodeResult shortcodeResult = shortcodes[x.Name].Execute(x.Arguments, x.Content, input, context);

                // Merge output metadata with the current input document
                // Creating a new document is the easiest way to ensure all the metadata from shortcodes gets accumulated correctly
                if (shortcodeResult?.Metadata != null)
                {
                    input = context.GetDocument(input, shortcodeResult.Metadata);
                }

                // Recursively parse shortcodes
                Stream shortcodeResultStream = shortcodeResult?.Stream;
                if (shortcodeResultStream != null)
                {
                    // Don't process nested shortcodes if it's the raw shortcode
                    if (!x.Name.Equals(nameof(Core.Shortcodes.Contents.Raw), StringComparison.OrdinalIgnoreCase))
                    {
                        if (!shortcodeResultStream.CanSeek)
                        {
                            shortcodeResultStream = new SeekableStream(shortcodeResultStream, true);
                        }
                        if (ProcessShortcodes(shortcodeResultStream, input, context, out IDocument nestedResult))
                        {
                            input = nestedResult;
                            shortcodeResultStream = nestedResult.GetStream();      // Will get disposed in the replacement operation below
                        }
                        else
                        {
                            shortcodeResultStream.Position = 0;
                        }
                    }
                    return(new InsertingStreamLocation(x.FirstIndex, x.LastIndex, shortcodeResultStream));
                }

                return(new InsertingStreamLocation(x.FirstIndex, x.LastIndex, null));
            })
                                                                .ToList();

            // Dispose any shortcodes that implement IDisposable
            foreach (IDisposable disposableShortcode
                     in shortcodes.Values.Select(x => x as IDisposable).Where(x => x != null))
            {
                disposableShortcode.Dispose();
            }

            // Construct a new stream with the shortcode results inserted
            // We have to use all TextWriter/TextReaders over the streams to ensure consistent encoding
            Stream resultStream = context.GetContentStream();

            char[] buffer = new char[4096];
            using (TextWriter writer = new StreamWriter(resultStream, Encoding.UTF8, 4096, true))
            {
                // The input stream will get disposed when the reader is
                using (TextReader reader = new StreamReader(inputStream))
                {
                    int position = 0;
                    int length   = 0;
                    foreach (InsertingStreamLocation insertingLocation in insertingLocations)
                    {
                        // Copy up to the start of this shortcode
                        length = insertingLocation.FirstIndex - position;
                        Read(reader, writer, length, ref buffer);
                        position += length;

                        // Copy the shortcode content to the result stream
                        if (insertingLocation.Stream != null)
                        {
                            // This will dispose the shortcode content stream when done
                            using (TextReader insertingReader = new StreamReader(insertingLocation.Stream))
                            {
                                Read(insertingReader, writer, null, ref buffer);
                            }
                        }

                        // Skip the shortcode text
                        length = insertingLocation.LastIndex - insertingLocation.FirstIndex + 1;
                        Read(reader, null, length, ref buffer);
                        position += length;
                    }

                    // Copy remaining
                    Read(reader, writer, null, ref buffer);
                }
            }
            result = context.GetDocument(input, resultStream);
            return(true);
        }
コード例 #16
0
 public void Parse_NullContentReturnsEmptyString(
     ShortcodeParser sut
     )
 {
     sut.Parse(null, null).Should().Be(MvcHtmlString.Empty);
 }