diff --git a/.gitignore b/.gitignore
index f400df3..b15f811 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,4 +3,5 @@ obj/
/packages/
riderModule.iml
/_ReSharper.Caches/
-.idea/
\ No newline at end of file
+.idea/
+.vs/
\ No newline at end of file
diff --git a/BemIt.Tests/BlockTests.cs b/BemIt.Tests/BlockTests.cs
index b6ba818..8c5bbfc 100644
--- a/BemIt.Tests/BlockTests.cs
+++ b/BemIt.Tests/BlockTests.cs
@@ -16,6 +16,18 @@ public void Extend()
Assert.Equal("m-list-item-title", _block.Extend("title").Build());
}
+ [Fact]
+ public void Extend_element()
+ {
+ Assert.Equal("m-list-item-title__intro", _block.Extend("title").Element("intro").Build());
+ }
+
+ [Fact]
+ public void Extend_element_modifier()
+ {
+ Assert.Equal("m-list-item-title__intro m-list-item-title__intro--hoverable", _block.Extend("title").Element("intro").Modifier("hoverable").Build());
+ }
+
[Fact]
public void Block_modifier_empty_ctor()
{
diff --git a/BemIt.sln b/BemIt.sln
index 1d0adf1..088b8cb 100644
--- a/BemIt.sln
+++ b/BemIt.sln
@@ -1,8 +1,11 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BemIt", "BemIt\BemIt.csproj", "{DD0FDF41-698B-464E-829E-13F0AD00809E}"
+# Visual Studio Version 17
+VisualStudioVersion = 17.9.34310.174
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BemIt", "BemIt\BemIt.csproj", "{DD0FDF41-698B-464E-829E-13F0AD00809E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BemIt.Tests", "BemIt.Tests\BemIt.Tests.csproj", "{F686E4F1-1AA0-4473-B7FB-F3654B7377E1}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BemIt.Tests", "BemIt.Tests\BemIt.Tests.csproj", "{F686E4F1-1AA0-4473-B7FB-F3654B7377E1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -19,4 +22,10 @@ Global
{F686E4F1-1AA0-4473-B7FB-F3654B7377E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F686E4F1-1AA0-4473-B7FB-F3654B7377E1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {0D42B177-36B3-4337-856C-0C54B0B452E0}
+ EndGlobalSection
EndGlobal
diff --git a/BemIt.sln.DotSettings.user b/BemIt.sln.DotSettings.user
index 97909df..e45f201 100644
--- a/BemIt.sln.DotSettings.user
+++ b/BemIt.sln.DotSettings.user
@@ -1,38 +1,42 @@
<SessionState ContinuousTestingMode="0" Name="Block" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
<TestAncestor>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.UnitTest1.Block</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.UnitTest1.Block</TestId>
</TestAncestor>
</SessionState>
<SessionState ContinuousTestingMode="0" Name="All tests from <BemIt.Tests> #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
<Project Location="F:\code\BemIt\BemIt.Tests" Presentation="<BemIt.Tests>" />
</SessionState>
- <SessionState ContinuousTestingMode="0" IsActive="True" Name="Block_modifier_with_true_condition #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
+ <SessionState ContinuousTestingMode="0" Name="Block_modifier_with_true_condition #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
<Or>
<TestAncestor>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.BlockTests.Block_modifier_with_true_condition</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.ElementTests.Element_modifier</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.BlockTests.ChildBlock</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.ElementTests</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.ModifierTests.Modifier_with_true_condition</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.ModifierTests.Modifier_with_two_mods</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.ModifierTests.Modifier_three_withs</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.ModifierTests.Modifier_with_enum_with_one_mod</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.ModifierTests.Modifier_with_enum_with_multi</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.ModifierTests.Modifier_with_args_with_enum</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.BlockTests.Block_modifier_with_true_condition</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.ElementTests.Element_modifier</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.BlockTests.ChildBlock</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.ElementTests</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.ModifierTests.Modifier_with_true_condition</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.ModifierTests.Modifier_with_two_mods</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.ModifierTests.Modifier_three_withs</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.ModifierTests.Modifier_with_enum_with_one_mod</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.ModifierTests.Modifier_with_enum_with_multi</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.ModifierTests.Modifier_with_args_with_enum</TestId>
</TestAncestor>
<ProjectFile>F686E4F1-1AA0-4473-B7FB-F3654B7377E1/f:BlockTests.cs</ProjectFile>
</Or>
</SessionState>
<SessionState ContinuousTestingMode="0" Name="Block_modifier_with_true_condition" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
<TestAncestor>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.BlockTests.Block_modifier_with_true_condition</TestId>
- <TestId>xUnit::F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::BemIt.Tests.BlockTests.Block_modifier</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.BlockTests.Block_modifier_with_true_condition</TestId>
+ <TestId>F686E4F1-1AA0-4473-B7FB-F3654B7377E1::net6.0::xUnit::BemIt.Tests.BlockTests.Block_modifier</TestId>
</TestAncestor>
</SessionState>
<SessionState ContinuousTestingMode="0" Name="All tests from <BemIt.Tests>" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
<Project Location="F:\code\BemIt\BemIt.Tests" Presentation="<BemIt.Tests>" />
</SessionState>
- <SessionState ContinuousTestingMode="0" Name="All tests from UnitTest1.cs" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
- <ProjectFile>F686E4F1-1AA0-4473-B7FB-F3654B7377E1/f:UnitTest1.cs</ProjectFile>
+ <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from UnitTest1.cs" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
+ <Or>
+ <ProjectFile>F686E4F1-1AA0-4473-B7FB-F3654B7377E1/f:BlockTests.cs</ProjectFile>
+ <ProjectFile>F686E4F1-1AA0-4473-B7FB-F3654B7377E1/f:ElementTests.cs</ProjectFile>
+ <ProjectFile>F686E4F1-1AA0-4473-B7FB-F3654B7377E1/f:ModifierTests.cs</ProjectFile>
+ </Or>
</SessionState>
\ No newline at end of file
diff --git a/BemIt/Abstract/IBem.cs b/BemIt/Abstract/IBem.cs
index 85a4c4e..623ef11 100644
--- a/BemIt/Abstract/IBem.cs
+++ b/BemIt/Abstract/IBem.cs
@@ -1,7 +1,14 @@
-namespace BemIt;
+using System.Collections.Generic;
+
+namespace BemIt;
public interface IBem
{
+ ///
+ /// The name of the block or element
+ ///
+ string Name { get; }
+
///
/// Adds original class names
///
@@ -9,9 +16,23 @@ public interface IBem
///
IBem AddClass(params string?[] classNames);
+ ///
+ /// Adds original class name if condition is true
+ ///
+ /// a single or a list of class names
+ ///
+ ///
+ IBem AddClass(string className, bool condition);
+
+ ///
+ /// Generates a list of css classes
+ ///
+ ///
+ IEnumerable GenerateCssClasses();
+
///
/// Builds the css class
///
///
string Build();
-}
+}
\ No newline at end of file
diff --git a/BemIt/Abstract/IBlockOrElement.cs b/BemIt/Abstract/IBlockOrElement.cs
index b6ee007..7a3e87a 100644
--- a/BemIt/Abstract/IBlockOrElement.cs
+++ b/BemIt/Abstract/IBlockOrElement.cs
@@ -1,6 +1,6 @@
namespace BemIt;
-public interface IBlockOrElement: IBem
+public interface IBlockOrElement
{
string Name { get; }
-}
+}
\ No newline at end of file
diff --git a/BemIt/BemBase.cs b/BemIt/BemBase.cs
index 603ebcd..8f66a29 100644
--- a/BemIt/BemBase.cs
+++ b/BemIt/BemBase.cs
@@ -1,9 +1,17 @@
using System.Collections.Generic;
+using System.Linq;
namespace BemIt;
-public class BemBase : IBem
+public abstract class BemBase : IBem
{
+ public string Name { get; }
+
+ protected BemBase(string blockOrElement)
+ {
+ Name = blockOrElement;
+ }
+
protected List ClassNames { get; } = new();
// inherits
@@ -13,9 +21,37 @@ public IBem AddClass(params string?[] classNames)
return this;
}
+ // inherits
+ public IBem AddClass(string? className, bool condition)
+ {
+ if (condition)
+ {
+ ClassNames.Add(className);
+ }
+
+ return this;
+ }
+
+ // inherits
+ public virtual IEnumerable GenerateCssClasses()
+ {
+ yield return Name;
+
+ foreach (var className in ClassNames.Where(className => !string.IsNullOrWhiteSpace(className)))
+ {
+ yield return className!;
+ }
+ }
+
// inherits
public virtual string Build()
{
- return string.Join(" ", ClassNames).Trim();
+ return string.Join(" ", GenerateCssClasses());
+ }
+
+ // inherits
+ public override string ToString()
+ {
+ return Build();
}
-}
+}
\ No newline at end of file
diff --git a/BemIt/BemIt.csproj b/BemIt/BemIt.csproj
index 201b0ca..dd947cc 100644
--- a/BemIt/BemIt.csproj
+++ b/BemIt/BemIt.csproj
@@ -7,7 +7,7 @@
BemIt
https://github.com/capdiem/BemIt
capdiem
- 1.1.2
+ 1.2.0
https://github.com/capdiem/BemIt
blazor;css;bem;block;element;modifier;
True
diff --git a/BemIt/Block.cs b/BemIt/Block.cs
index bc052af..2dbae6e 100644
--- a/BemIt/Block.cs
+++ b/BemIt/Block.cs
@@ -13,16 +13,10 @@ public class Block : BemBase, IBlockOrElement
/// Creates a block
///
/// The name of the block
- public Block(string name)
+ public Block(string name) : base(name)
{
- Name = name;
}
- ///
- /// The name of the block
- ///
- public string Name { get; }
-
///
/// Creates a block extends from current block
///
@@ -51,19 +45,4 @@ public Element Element(string element)
{
return new Element(Name, element);
}
-
- ///
- /// Builds the css class from a block
- ///
- ///
- public override string Build()
- {
- return (Name + " " + string.Join(" ", ClassNames)).Trim();
- }
-
- // inherit
- public override string ToString()
- {
- return Build();
- }
-}
+}
\ No newline at end of file
diff --git a/BemIt/Element.cs b/BemIt/Element.cs
index a093042..b67edf1 100644
--- a/BemIt/Element.cs
+++ b/BemIt/Element.cs
@@ -10,31 +10,7 @@ public class Element : BemBase, IBlockOrElement
///
/// From which block
/// The name of the element, appended to the block name with double underscore
- public Element(string block, string element)
+ public Element(string block, string element) : base($"{block}__{element}")
{
- Name = $"{block}__{element}";
}
-
- ///
- /// The name of the element
- ///
- ///
- /// {block}__{element}
- ///
- public string Name { get; }
-
- ///
- /// Builds the css class from a element
- ///
- ///
- public override string Build()
- {
- return (Name + " " + string.Join(" ", ClassNames)).Trim();
- }
-
- // inherit
- public override string ToString()
- {
- return Build();
- }
-}
+}
\ No newline at end of file
diff --git a/BemIt/Extensions/BlockOrElementExtensions.cs b/BemIt/Extensions/BlockOrElementExtensions.cs
index 2b3d5c2..43a74e6 100644
--- a/BemIt/Extensions/BlockOrElementExtensions.cs
+++ b/BemIt/Extensions/BlockOrElementExtensions.cs
@@ -10,7 +10,7 @@ public static Modifier Modifier(this IBlockOrElement blockOrElement)
{
return new Modifier(blockOrElement.Name);
}
-
+
public static Modifier Modifier(this IBlockOrElement blockOrElement, string modifier)
{
return new Modifier(blockOrElement.Name, modifier);
@@ -33,7 +33,8 @@ public static Modifier Modifier(this IBlockOrElement blockOrElement, Enum value,
return new Modifier(blockOrElement.Name, modifier);
}
- public static Modifier Modifier(this IBlockOrElement blockOrElement, bool modifier, [CallerArgumentExpression("modifier")] string name = "")
+ public static Modifier Modifier(this IBlockOrElement blockOrElement, bool modifier,
+ [CallerArgumentExpression("modifier")] string name = "")
{
return new Modifier(blockOrElement.Name, name, modifier);
}
@@ -66,4 +67,4 @@ public static Modifier Modifier(this IBlockOrElement blockOrElement, bool modifi
{ name3, modifier3 },
});
}
-}
+}
\ No newline at end of file
diff --git a/BemIt/Extensions/StringExtensions.cs b/BemIt/Extensions/StringExtensions.cs
index 2bd8f0a..eac3bfa 100644
--- a/BemIt/Extensions/StringExtensions.cs
+++ b/BemIt/Extensions/StringExtensions.cs
@@ -12,11 +12,12 @@ public static string ToKebab(this string name)
#else
var split = Regex.Split(name, "(? s.Trim('-'));
#endif
- return string.Join("-", split).ToLowerInvariant();
+ return string.Join("-", split).ToLowerInvariant()
+ .TrimStart('_'); // for private fields like _myField
}
#if NET7_0_OR_GREATER
[GeneratedRegex("(?
public class Modifier : BemBase
{
- private readonly string _blockOrElement;
private readonly IDictionary _modifiers = new Dictionary();
///
/// Creates a modifier instance with a block or element
///
///
- public Modifier(string blockOrElement)
+ public Modifier(string blockOrElement) : base(blockOrElement)
{
- _blockOrElement = blockOrElement;
}
///
@@ -27,10 +25,8 @@ public Modifier(string blockOrElement)
///
///
///
- public Modifier(string blockOrElement, string m)
+ public Modifier(string blockOrElement, string m) : this(blockOrElement)
{
- _blockOrElement = blockOrElement;
-
_modifiers.Add(m, true);
}
@@ -40,10 +36,8 @@ public Modifier(string blockOrElement, string m)
///
///
///
- public Modifier(string blockOrElement, string m, bool condition)
+ public Modifier(string blockOrElement, string m, bool condition) : this(blockOrElement)
{
- _blockOrElement = blockOrElement;
-
_modifiers.Add(m, condition);
}
@@ -52,10 +46,8 @@ public Modifier(string blockOrElement, string m, bool condition)
///
///
///
- public Modifier(string blockOrElement, IDictionary modifiers)
+ public Modifier(string blockOrElement, IDictionary modifiers) : this(blockOrElement)
{
- _blockOrElement = blockOrElement;
-
_modifiers = modifiers;
}
@@ -85,12 +77,14 @@ public Modifier Add(string modifier)
///
/// Adds a modifier of type enum
///
- ///
+ /// The value of enum
+ /// Applies the modifier if
///
- public Modifier Add(Enum value)
+ public Modifier Add(Enum value, bool apply = true)
{
- var modifier = FormatEnum(value);
+ if (!apply) return this;
+ var modifier = FormatEnum(value);
return Add(modifier);
}
@@ -99,11 +93,13 @@ public Modifier Add(Enum value)
///
///
///
+ /// Applies the modifier if
///
- public Modifier Add(Enum value, string name)
+ public Modifier Add(Enum value, string name, bool apply = true)
{
- var modifier = FormatEnum(value, name);
+ if (!apply) return this;
+ var modifier = FormatEnum(value, name);
return Add(modifier);
}
@@ -180,6 +176,69 @@ public Modifier Add(bool modifier1, bool modifier2, bool modifier3,
});
}
+ ///
+ /// Adds a modifier based on the specified parameters.
+ /// Only one of the parameters that's value is true will be added.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Modifier AddOneOf(bool modifier1, bool modifier2,
+ [CallerArgumentExpression("modifier1")]
+ string name1 = "",
+ [CallerArgumentExpression("modifier2")]
+ string name2 = "")
+ {
+ if (modifier1)
+ {
+ Add(name1);
+ }
+ else if (modifier2)
+ {
+ Add(name2);
+ }
+
+ return this;
+ }
+
+ ///
+ /// Adds a modifier based on the specified parameters.
+ /// Only one of the parameters that's value is true will be added.
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Modifier AddOneOf(bool modifier1, bool modifier2, bool modifier3,
+ [CallerArgumentExpression("modifier1")]
+ string name1 = "",
+ [CallerArgumentExpression("modifier2")]
+ string name2 = "",
+ [CallerArgumentExpression("modifier2")]
+ string name3 = ""
+ )
+ {
+ if (modifier1)
+ {
+ Add(name1);
+ }
+ else if (modifier2)
+ {
+ Add(name2);
+ }
+ else if (modifier3)
+ {
+ Add(name3);
+ }
+
+ return this;
+ }
+
///
/// Formats an enum to a BEM modifier
///
@@ -194,16 +253,35 @@ public static string FormatEnum(Enum @enum, string? inputName = null)
return $"{name}-{value}";
}
+ // inherits
+ public override IEnumerable GenerateCssClasses()
+ {
+ yield return Name;
+
+ foreach (var item in _modifiers)
+ {
+ var className = Combine(Name, item.Key.ToKebab(), item.Value);
+ if (string.IsNullOrWhiteSpace(className))
+ {
+ continue;
+ }
+
+ yield return className;
+ }
+
+ foreach (var className in ClassNames.Where(c => !string.IsNullOrWhiteSpace(c)))
+ {
+ yield return className!;
+ }
+ }
+
///
/// Builds the css class from a modifier
///
///
public override string Build()
{
- var bemCss = _modifiers.Aggregate(_blockOrElement,
- (current, modifier) => current + Combine(_blockOrElement, modifier.Key.ToKebab(), modifier.Value));
-
- return (bemCss + " " + string.Join(" ", ClassNames)).Trim();
+ return string.Join(" ", GenerateCssClasses()).Trim();
}
// inherit
@@ -214,6 +292,6 @@ public override string ToString()
private static string Combine(string be, string modifier, bool condition)
{
- return condition ? $" {be}--{modifier}" : string.Empty;
+ return condition ? $"{be}--{modifier}" : string.Empty;
}
}
\ No newline at end of file