/// <summary>
 /// Creates a <see cref="FlexiTabsBlockOptions"/>.
 /// </summary>
 /// <param name="blockName">
 /// <para>The <see cref="FlexiTabsBlock"/>'s <a href="https://en.bem.info/methodology/naming-convention/#block-name">BEM block name</a>.</para>
 /// <para>In compliance with <a href="https://en.bem.info">BEM methodology</a>, this value is the <see cref="FlexiTabsBlock"/>'s root element's class as well as the prefix for all other classes in the block.</para>
 /// <para>This value should contain only valid <a href="https://www.w3.org/TR/CSS21/syndata.html#characters">CSS class characters</a>.</para>
 /// <para>If this value is <c>null</c>, whitespace or an empty string, the <see cref="FlexiTabsBlock"/>'s block name is "flexi-tabs".</para>
 /// <para>Defaults to "flexi-tabs".</para>
 /// </param>
 /// <param name="defaultTabOptions">
 /// <para>The default <see cref="IFlexiTabBlockOptions"/> for contained <see cref="FlexiTabBlock"/>s.</para>
 /// <para>If this value is <c>null</c>, a <see cref="FlexiTabBlockOptions"/> with default values is used.</para>
 /// <para>Defaults to <c>null</c>.</para>
 /// </param>
 /// <param name="attributes">
 /// <para>The HTML attributes for the <see cref="FlexiTabsBlock"/>'s root element.</para>
 /// <para>Attribute names must be lowercase.</para>
 /// <para>If the class attribute is specified, its value is appended to default classes. This facilitates <a href="https://en.bem.info/methodology/quick-start/#mix">BEM mixes</a>.</para>
 /// <para>If this value is <c>null</c>, default classes are still assigned to the root element.</para>
 /// <para>Defaults to <c>null</c>.</para>
 /// </param>
 public FlexiTabsBlockOptions(
     string blockName = "flexi-tabs",
     IFlexiTabBlockOptions defaultTabOptions = default,
     IDictionary <string, string> attributes = default) : base(blockName, attributes)
 {
     DefaultTabOptions = defaultTabOptions ?? new FlexiTabBlockOptions();
 }
        public void Create_CreatesFlexiTabBlock()
        {
            // Arrange
            const int                     dummyColumn               = 2;
            var                           dummyLine                 = new StringSlice("dummyText", 3, 8);
            IFlexiTabBlockOptions         dummyDefaultTabOptions    = _mockRepository.Create <IFlexiTabBlockOptions>().Object;
            Mock <IFlexiTabsBlockOptions> mockFlexiTabsBlockOptions = _mockRepository.Create <IFlexiTabsBlockOptions>();

            mockFlexiTabsBlockOptions.Setup(f => f.DefaultTabOptions).Returns(dummyDefaultTabOptions);
            Mock <BlockParser>  dummyBlockParser         = _mockRepository.Create <BlockParser>();
            ProxyFlexiTabsBlock dummyProxyFlexiTabsBlock = CreateProxyFlexiTabsBlock(mockFlexiTabsBlockOptions.Object, blockParser: dummyBlockParser.Object);
            BlockProcessor      dummyBlockProcessor      = MarkdigTypesFactory.CreateBlockProcessor();

            // Following 3 lines set dummyBlockProcessor.CurrentContainer
            dummyBlockParser.Setup(b => b.TryContinue(dummyBlockProcessor, dummyProxyFlexiTabsBlock)).Returns(BlockState.ContinueDiscard);
            dummyBlockProcessor.Open(dummyProxyFlexiTabsBlock);
            dummyBlockProcessor.ProcessLine(new StringSlice(string.Empty));
            dummyBlockProcessor.Column = dummyColumn;
            dummyBlockProcessor.Line   = dummyLine;
            var dummyAttributes = new ReadOnlyDictionary <string, string>(new Dictionary <string, string>());
            Mock <IFlexiTabBlockOptions> mockFlexiTabBlockOptions = _mockRepository.Create <IFlexiTabBlockOptions>();

            mockFlexiTabBlockOptions.Setup(f => f.Attributes).Returns(dummyAttributes);
            Mock <IBlockOptionsFactory <IFlexiTabBlockOptions> > mockFlexiTabBlockOptionsFactory = _mockRepository.
                                                                                                   Create <IBlockOptionsFactory <IFlexiTabBlockOptions> >();

            mockFlexiTabBlockOptionsFactory.Setup(f => f.Create(dummyDefaultTabOptions, dummyBlockProcessor)).Returns(mockFlexiTabBlockOptions.Object);
            FlexiTabBlockFactory testSubject = CreateFlexiTabBlockFactory(mockFlexiTabBlockOptionsFactory.Object);

            // Act
            FlexiTabBlock result = testSubject.Create(dummyBlockProcessor, dummyBlockParser.Object);

            // Assert
            _mockRepository.VerifyAll();
            Assert.Same(dummyAttributes, result.Attributes);
            Assert.Same(dummyBlockParser.Object, result.Parser);
            Assert.Equal(dummyColumn, result.Column);
            Assert.Equal(dummyLine.Start, result.Span.Start);
            Assert.Equal(0, result.Span.End);
        }
        /// <summary>
        /// Creates a <see cref="FlexiTabBlock"/>.
        /// </summary>
        /// <param name="blockProcessor">The <see cref="BlockProcessor"/> processing the <see cref="FlexiTabBlock"/>.</param>
        /// <param name="blockParser">The <see cref="BlockParser"/> parsing the <see cref="FlexiTabBlock"/>.</param>
        /// <exception cref="BlockException">Thrown if <paramref name="blockProcessor"/>'s <see cref="BlockProcessor.CurrentContainer"/> is not
        /// a <see cref="ProxyFlexiTabsBlock"/>.</exception>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="blockProcessor"/> is <c>null</c>.</exception>
        public override FlexiTabBlock Create(BlockProcessor blockProcessor, BlockParser blockParser)
        {
            if (!(blockProcessor.CurrentContainer is ProxyFlexiTabsBlock proxyFlexiTabsBlock))
            {
                throw new BlockException(nameof(FlexiTabBlock),
                                         blockProcessor.LineIndex,
                                         blockProcessor.Column,
                                         string.Format(Strings.BlockException_Shared_BlockCanOnlyExistWithinASpecificTypeOfBlock,
                                                       nameof(FlexiTabBlock),
                                                       nameof(FlexiTabsBlock)));
            }

            IFlexiTabBlockOptions flexiTabBlockOptions = _flexiTabBlockOptionsFactory.
                                                         Create(proxyFlexiTabsBlock.FlexiTabsBlockOptions.DefaultTabOptions, blockProcessor);

            // Create block
            return(new FlexiTabBlock(flexiTabBlockOptions.Attributes, blockParser)
            {
                Column = blockProcessor.Column,
                Span = new SourceSpan(blockProcessor.Start, 0) // MultipartBlockParser will update end
                       // Line is assigned by BlockProcessor
            });
        }