示例#1
0
        /// <summary>
        /// Creates a <see cref="FlexiCardsBlock"/> from a <see cref="ProxyFlexiCardsBlock"/>.
        /// </summary>
        /// <param name="proxyFencedBlock">The <see cref="ProxyFlexiCardsBlock"/> containing data for the <see cref="FlexiCardsBlock"/>.</param>
        /// <param name="blockProcessor">The <see cref="BlockProcessor"/> processing the <see cref="FlexiCardsBlock"/>.</param>
        /// <exception cref="ArgumentNullException">Thrown if <paramref name="proxyFencedBlock"/> is <c>null</c>.</exception>
        /// <exception cref="OptionsException">Thrown if an option is invalid.</exception>
        public override FlexiCardsBlock Create(ProxyFlexiCardsBlock proxyFencedBlock, BlockProcessor blockProcessor)
        {
            if (proxyFencedBlock == null)
            {
                throw new ArgumentNullException(nameof(proxyFencedBlock));
            }

            IFlexiCardsBlockOptions flexiCardsBlockOptions = proxyFencedBlock.FlexiCardsBlockOptions;

            // Block name
            string blockName = ResolveBlockName(flexiCardsBlockOptions.BlockName);

            // Card size
            FlexiCardBlockSize cardSize = flexiCardsBlockOptions.CardSize;

            ValidateCardSize(cardSize);

            // Create block
            var flexiCardsBlock = new FlexiCardsBlock(blockName, cardSize, flexiCardsBlockOptions.Attributes, proxyFencedBlock.Parser)
            {
                Line   = proxyFencedBlock.Line,
                Column = proxyFencedBlock.Column,
                Span   = proxyFencedBlock.Span
            };

            MoveChildren(proxyFencedBlock, flexiCardsBlock);

            return(flexiCardsBlock);
        }
示例#2
0
 /// <summary>
 /// Creates a <see cref="FlexiCardBlockOptions"/>.
 /// </summary>
 /// <param name="blockName">
 /// <para>The <see cref="FlexiCardsBlock"/>'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="FlexiCardsBlock"/>'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="FlexiCardsBlock"/>'s block name is "flexi-cards".</para>
 /// <para>Defaults to "flexi-cards".</para>
 /// </param>
 /// <param name="cardSize">
 /// <para>The display size of contained <see cref="FlexiCardBlock"/>s.</para>
 /// <para>A class attribute with value "&lt;<paramref name="blockName"/>&gt;_size_&lt;<paramref name="cardSize"/>&gt;" is added to the <see cref="FlexiCardsBlock"/>'s root element.</para>
 /// <para>Defaults to <see cref="FlexiCardBlockSize.Small"/>.</para>
 /// </param>
 /// <param name="defaultCardOptions">
 /// <para>The default <see cref="IFlexiCardBlockOptions"/> for contained <see cref="FlexiCardBlock"/>s.</para>
 /// <para>If this value is <c>null</c>, a <see cref="FlexiCardBlockOptions"/> 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="FlexiCardsBlock"/>'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 FlexiCardsBlockOptions(
     string blockName            = "flexi-cards",
     FlexiCardBlockSize cardSize = FlexiCardBlockSize.Small,
     IFlexiCardBlockOptions defaultCardOptions = default,
     IDictionary <string, string> attributes   = default) : base(blockName, attributes)
 {
     CardSize           = cardSize;
     DefaultCardOptions = defaultCardOptions ?? new FlexiCardBlockOptions();
 }
示例#3
0
 /// <summary>
 /// Creates a <see cref="FlexiCardsBlock"/>.
 /// </summary>
 /// <param name="blockName">The <see cref="FlexiCardsBlock"/>'s BEM block name.</param>
 /// <param name="cardSize">The display size of contained <see cref="FlexiCardBlock"/>s.</param>
 /// <param name="attributes">HTML attributes for the <see cref="FlexiCardsBlock"/>'s root element.</param>
 /// <param name="blockParser">The <see cref="BlockParser"/> parsing the <see cref="FlexiCardsBlock"/>.</param>
 public FlexiCardsBlock(string blockName,
                        FlexiCardBlockSize cardSize,
                        ReadOnlyDictionary <string, string> attributes,
                        BlockParser blockParser) : base(blockParser)
 {
     BlockName  = blockName;
     CardSize   = cardSize;
     Attributes = attributes;
 }
示例#4
0
 internal virtual void ValidateCardSize(FlexiCardBlockSize cardSize)
 {
     if (!Enum.IsDefined(typeof(FlexiCardBlockSize), cardSize))
     {
         throw new OptionsException(nameof(IFlexiCardsBlockOptions.CardSize),
                                    string.Format(Strings.OptionsException_Shared_ValueMustBeAValidEnumValue,
                                                  cardSize,
                                                  nameof(FlexiCardBlockSize)));
     }
 }
        public void ValidateCardSize_ThrowsOptionsExceptionIfCardSizeIsInvalid()
        {
            // Arrange
            FlexiCardsBlockFactory   testSubject   = CreateFlexiCardsBlockFactory();
            const FlexiCardBlockSize dummyCardSize = (FlexiCardBlockSize)9;

            // Act and assert
            OptionsException result = Assert.Throws <OptionsException>(() => testSubject.ValidateCardSize(dummyCardSize));

            Assert.Equal(string.Format(Strings.OptionsException_OptionsException_InvalidOption,
                                       nameof(IFlexiCardsBlockOptions.CardSize),
                                       string.Format(Strings.OptionsException_Shared_ValueMustBeAValidEnumValue, dummyCardSize,
                                                     nameof(FlexiCardBlockSize))),
                         result.Message);
        }
示例#6
0
        private static FlexiCardsBlock CreateFlexiCardsBlock(string blockName            = default,
                                                             FlexiCardBlockSize cardSize = default,
                                                             ReadOnlyDictionary <string, string> attributes = default,
                                                             BlockParser blockParser        = default,
                                                             List <FlexiCardBlock> children = default)
        {
            var result = new FlexiCardsBlock(blockName, cardSize, attributes, blockParser);

            if (children != null)
            {
                foreach (FlexiCardBlock child in children)
                {
                    result.Add(child);
                }
            }
            return(result);
        }
        public void Create_CreatesFlexiCardsBlock()
        {
            // Arrange
            var                            dummySpan                  = new SourceSpan(6, 19);
            const int                      dummyLine                  = 5;
            const int                      dummyColumn                = 2;
            BlockParser                    dummyBlockParser           = _mockRepository.Create <BlockParser>().Object;
            const string                   dummyBlockName             = "dummyBlockName";
            const string                   dummyResolvedBlockName     = "dummyResolvedBlockName";
            const FlexiCardBlockSize       dummyCardSize              = FlexiCardBlockSize.Medium;
            var                            dummyAttributes            = new ReadOnlyDictionary <string, string>(new Dictionary <string, string>());
            Mock <IFlexiCardsBlockOptions> mockFlexiCardsBlockOptions = _mockRepository.Create <IFlexiCardsBlockOptions>();

            mockFlexiCardsBlockOptions.Setup(f => f.BlockName).Returns(dummyBlockName);
            mockFlexiCardsBlockOptions.Setup(f => f.CardSize).Returns(dummyCardSize);
            mockFlexiCardsBlockOptions.Setup(f => f.Attributes).Returns(dummyAttributes);
            ProxyFlexiCardsBlock dummyProxyFlexiCardsBlock = CreateProxyFlexiCardsBlock(mockFlexiCardsBlockOptions.Object, blockParser: dummyBlockParser);

            dummyProxyFlexiCardsBlock.Line   = dummyLine;
            dummyProxyFlexiCardsBlock.Column = dummyColumn;
            dummyProxyFlexiCardsBlock.Span   = dummySpan;
            Mock <FlexiCardsBlockFactory> mockTestSubject = CreateMockFlexiCardsBlockFactory();

            mockTestSubject.CallBase = true;
            mockTestSubject.Setup(t => t.ResolveBlockName(dummyBlockName)).Returns(dummyResolvedBlockName);
            mockTestSubject.Setup(t => t.ValidateCardSize(dummyCardSize));
            mockTestSubject.Protected().Setup("MoveChildren", dummyProxyFlexiCardsBlock, ItExpr.IsAny <FlexiCardsBlock>());

            // Act
            FlexiCardsBlock result = mockTestSubject.Object.Create(dummyProxyFlexiCardsBlock, null);

            // Assert
            _mockRepository.VerifyAll();
            Assert.Equal(dummyResolvedBlockName, result.BlockName);
            Assert.Equal(dummyCardSize, result.CardSize);
            Assert.Same(dummyAttributes, result.Attributes);
            Assert.Same(dummyBlockParser, result.Parser);
            Assert.Equal(dummyColumn, result.Column);
            Assert.Equal(dummyLine, result.Line);
            Assert.Equal(dummySpan, result.Span);
        }
示例#8
0
        public static IEnumerable <object[]> WriteBlock_WritesBlock_Data()
        {
            const string             dummyBlockName       = "dummyBlockName";
            const FlexiCardBlockSize dummyCardSize        = FlexiCardBlockSize.Medium;
            const string             dummyAttributeKey1   = "dummyAttributeKey1";
            const string             dummyAttributeValue1 = "dummyAttributeValue1";
            const string             dummyAttributeKey2   = "dummyAttributeKey2";
            const string             dummyAttributeValue2 = "dummyAttributeValue2";
            const string             dummyClass           = "dummyClass";

            // Dummy title part
            const string dummyTitle = "dummyTitle";
            var          dummyTitleContainerInline = new ContainerInline();

            dummyTitleContainerInline.AppendChild(new LiteralInline(dummyTitle));
            var dummyTitlePartBlock = new PlainLeafBlock(null);

            dummyTitlePartBlock.Inline = dummyTitleContainerInline;

            // Dummy content part
            const string dummyContent = "dummyContent";
            var          dummyContentContainerInline = new ContainerInline();

            dummyContentContainerInline.AppendChild(new LiteralInline(dummyContent));
            var dummyContentParagraphBlock = new ParagraphBlock()
            {
                Inline = dummyContentContainerInline
            };
            var dummyContentPartBlock = new PlainContainerBlock(null);

            dummyContentPartBlock.Add(dummyContentParagraphBlock);

            // Dummy footnote part
            const string dummyFootnote = "dummyFootnote";
            var          dummyFootnoteContainerInline = new ContainerInline();

            dummyFootnoteContainerInline.AppendChild(new LiteralInline(dummyFootnote));
            var dummyFootnotePartBlock = new PlainLeafBlock(null);

            dummyFootnotePartBlock.Inline = dummyFootnoteContainerInline;

            return(new object[][]
            {
                // BlockName is assigned as a class of the root element and all default classes are prepended with it
                new object[] {
                    CreateFlexiCardsBlock(dummyBlockName),
                    $@"<div class=""{dummyBlockName} {dummyBlockName}_size_small"">
</div>
"
                },
                // CardSize is rendered in a modifier class of the root element
                new object[] {
                    CreateFlexiCardsBlock(cardSize: dummyCardSize),
                    $@"<div class="" _size_{dummyCardSize.ToString().ToLower()}"">
</div>
"
                },
                // If attributes are specified, they're written
                new object[] {
                    CreateFlexiCardsBlock(attributes: new ReadOnlyDictionary <string, string>(new Dictionary <string, string> {
                        { dummyAttributeKey1, dummyAttributeValue1 }, { dummyAttributeKey2, dummyAttributeValue2 }
                    })),
                    $@"<div class="" _size_small"" {dummyAttributeKey1}=""{dummyAttributeValue1}"" {dummyAttributeKey2}=""{dummyAttributeValue2}"">
</div>
"
                },
                // If classes are specified, they're appended to default classes
                new object[] {
                    CreateFlexiCardsBlock(attributes: new ReadOnlyDictionary <string, string>(new Dictionary <string, string> {
                        { "class", dummyClass }
                    })),
                    $@"<div class="" _size_small {dummyClass}"">
</div>
"
                },
                // Child FlexiCardBlocks are rendered
                new object[] {
                    CreateFlexiCardsBlock(children: new List <FlexiCardBlock> {
                        CreateFlexiCardBlock(titlePart: dummyTitlePartBlock, contentPart: dummyContentPartBlock, footnotePart: dummyFootnotePartBlock)
                    }),
                    $@"<div class="" _size_small"">
<div class=""__card __card_not-link __card_no-background-icon"">
<p class=""__card-title"">{dummyTitle}</p>
<div class=""__card-content"">
<p>{dummyContent}</p>
</div>
<p class=""__card-footnote"">{dummyFootnote}</p>
</div>
</div>
"
                }
            });
        }
示例#9
0
        public static IEnumerable <object[]> FlexiCardsBlockOptions_CanBePopulated_Data()
        {
            const string             dummyBlockName       = "dummyBlockName";
            const FlexiCardBlockSize dummyCardSize        = FlexiCardBlockSize.Medium;
            const string             dummyUrl             = "dummyUrl";
            const string             dummyBackgroundIcon  = "dummyBackgroundIcon";
            const string             dummyAttribute1      = "dummyAttribute1";
            const string             dummyAttributeValue1 = "dummyAttributeValue1";
            var dummyCardsAttributes1 = new Dictionary <string, string> {
                { dummyAttribute1, dummyAttributeValue1 }
            };
            var dummyCardAttributes1 = new Dictionary <string, string> {
                { dummyAttribute1, dummyAttributeValue1 }
            };
            const string dummyAttribute2       = "dummyAttribute2";
            const string dummyAttributeValue2  = "dummyAttributeValue2";
            var          dummyCardsAttributes2 = new Dictionary <string, string> {
                { dummyAttribute2, dummyAttributeValue2 }
            };

            return(new object[][]
            {
                // Each new value should overwrite its corresponding existing value
                new object[]
                {
                    new FlexiCardsBlockOptions(),
                    new FlexiCardsBlockOptions(dummyBlockName,
                                               dummyCardSize,
                                               new FlexiCardBlockOptions(dummyUrl, dummyBackgroundIcon, dummyCardAttributes1),
                                               dummyCardsAttributes1),
                    $@"{{
    ""{nameof(FlexiCardsBlockOptions.BlockName)}"": ""{dummyBlockName}"",
    ""{nameof(FlexiCardsBlockOptions.CardSize)}"": ""{dummyCardSize}"",
    ""{nameof(FlexiCardsBlockOptions.DefaultCardOptions)}"": {{
        ""{nameof(FlexiCardBlockOptions.Url)}"": ""{dummyUrl}"",
        ""{nameof(FlexiCardBlockOptions.BackgroundIcon)}"": ""{dummyBackgroundIcon}"",
        ""{nameof(FlexiCardBlockOptions.Attributes)}"": {{
            ""{dummyAttribute1}"": ""{dummyAttributeValue1}""
        }}
    }},
    ""{nameof(FlexiCardsBlockOptions.Attributes)}"": {{
        ""{dummyAttribute1}"": ""{dummyAttributeValue1}""
    }}
}}"
                },

                // Existing values should not be overwritten if no corresponding new value
                new object[]
                {
                    new FlexiCardsBlockOptions(dummyBlockName),
                    new FlexiCardsBlockOptions(dummyBlockName, dummyCardSize), // Block name should stay the same
                    $@"{{ ""{nameof(FlexiCardsBlockOptions.CardSize)}"": ""{dummyCardSize}"" }}"
                },

                // Populating FlexiCardsBlockOptions with an existing attributes collection should replace the entire collection
                new object[]
                {
                    new FlexiCardsBlockOptions(attributes: dummyCardsAttributes1),
                    new FlexiCardsBlockOptions(attributes: dummyCardsAttributes2),
                    $@"{{
    ""{nameof(FlexiCardsBlockOptions.Attributes)}"": {{
        ""{dummyAttribute2}"": ""{dummyAttributeValue2}""
    }}
}}"
                }
            });
        }