Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ For other examples, you can check out the example code.
## Css Compiler
The CssInCSharp is similar to less or sass. You can simply convert you style file into C# class, so that you can make full use of the C# language features to generate style content.

## Css Converter
For those projects that are already using css or ts styles, you can use the [converter](./generators/README.md) provided by CssInCSharp to convert css or ts code into C# code, which improves style control and code reuse.

For details about the style migration of antd-v5, see the [Antd v5 Style Migration Document](./docs/migration.md).

## Benchmark
```

Expand Down
342 changes: 342 additions & 0 deletions docs/migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,342 @@
## Antd v5 Style Migration

- Clone the source code of react-antd

```bash
git clone https://github.com/ant-design/ant-design.git
```

After cloning, the directory tree is as follows:
```
ant-design/
ant-design-blazor/
├── cssincs.json
```

`ant-design: ` is the source code of the React project.
`ant-design-blazor: ` is the source code of the Blazor project.

**For stable version, please use the git tag version**

- Install the generator

```bash
dotnet tool install -g CssInCSharp.CommandLine
```

- Create profile

Create a cssincs.json under the root path of the blazor project, as follows:

```json
{
"Converter": "Ts",
"CsOptions": {
"Usings": [
"System",
"AntDesign",
"CssInCSharp",
"CssInCSharp.Colors",
"static AntDesign.GlobalStyle",
"static AntDesign.Theme",
"static AntDesign.StyleUtil",
"static AntDesign.PresetColors",
"Keyframes = CssInCSharp.Keyframe"
],
"Namespace": "AntDesign.Styles",
"NamePrefix": "{dir:../../}",
"DefaultReturnType": "object",
"DefaultParameterType": "object",
"DefaultVariableType": "object",
"DefaultExportType": "object",
"DefaultExportClassName": "{dir:../../}Style",
"DefaultExportMethodName": "{file}Default",
"UsePascalCase": true,
"UsePartialClass": true,
"UseStaticMethod": true,
"Replacements": [
{
"Pattern": "class ComponentToken",
"Value": "class ComponentToken : TokenWithCommonCls"
},
{
"Pattern": "FullToken(\\<\\w*\\>)?",
"Value": "ComponentToken"
},
{
"Pattern": "(?<!var) gen(\\w+)",
"Value": " Gen$1"
},
{
"Pattern": "prepare(\\w+)",
"Value": "Prepare$1"
},
{
"Pattern": "(?<!token.)Calc\\(",
"Value": "calc("
},
{
"Pattern": "_skip_check_",
"Value": "SkipCheck"
},
{
"Pattern": "= textEllipsis",
"Value": "= TextEllipsis"
},
{
"Pattern": "= AvatarSizeStyle",
"Value": "= avatarSizeStyle"
},
{
"Pattern": "= GetCompactBorderStyle",
"Value": "= getCompactBorderStyle"
},
{
"Pattern": "CSSObject\\[\\]",
"Value": "CSSInterpolation[]"
},
{
"Pattern": "ButtonVariantType variant",
"Value": "string variant = null"
},
{
"Pattern": "variant &&",
"Value": "variant == null &&"
},
{
"Pattern": "var genDisabledButtonStyle",
"Value": "Func<ButtonToken, CSSObject> genDisabledButtonStyle"
},
{
"Pattern": "= GenDisabledButtonStyle",
"Value": "= genDisabledButtonStyle"
},
{
"Pattern": "PresetColorKey",
"Value": "string"
},
{
"Pattern": "token\\[(\\$@\"[^\"]+\")\\]",
"Value": "token[$1].ToString()"
},
{
"Pattern": "Unitless = new GenOptions",
"Value": "Unitless = new"
},
{
"Pattern": "getCompactBorderStyle\\(\\)",
"Value": "getCompactBorderStyle(false)"
},
{
"Pattern": "CSSObject hoverStyle, CSSObject activeStyle",
"Value": "CSSObject hoverStyle = null, CSSObject activeStyle = null"
},
{
"Pattern": "getColumnsStyle;",
"Value": "GetColumnsStyle;"
}
]
},
"Include": [
{
"Src": "../ant-design/components/**/style/*.ts",
"Dest": "./components"
}
],
"Exclude": [
"../ant-design/components/style/*.ts",
"../ant-design/components/qrcode/style/*.ts"
],
"TypeInferences": [
{
"RuleName": "ObjectTypeInfer_CSSObject",
"Expression": "Kind == \"ObjectType\" && ((HasIndexer && Properties == null) || HasAny(\"margin\", \"width\", \"display\", \"position\", \"color\", \"direction\", \"flex\", \"background\"))",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "\"CSSObject\""
}
}
}
},
{
"RuleName": "ObjectTypeInfer_PropertySkip",
"Expression": "Kind == \"ObjectType\" && HasKey(\"_skip_check_\")",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "\"PropertySkip\""
}
}
}
},
{
"RuleName": "ObjectTypeInfer_GenOptions",
"Expression": "Kind == \"ObjectType\" && HasAny(\"deprecatedTokens\", \"unitless\")",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "\"GenOptions\""
}
}
}
},
{
"RuleName": "ReturnTypeInfer_CSSInterpolation_Size",
"Expression": "Kind == \"ReturnType\" && FunctionName.StartsWith(\"genSize\")",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "\"CSSInterpolation\""
}
}
}
},
{
"RuleName": "ReturnTypeInfer_CSSObject",
"Expression": "Kind == \"ReturnType\" && FunctionName.EndsWith(\"Style\")",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "\"CSSObject\""
}
}
}
},
{
"RuleName": "ReturnTypeInfer_Token",
"Expression": "Kind == \"ReturnType\" && FunctionName.StartsWith(\"pre\") && FunctionName.EndsWith(\"Token\")",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "CsOptions.NamePrefix + \"Token\""
}
}
}
},
{
"RuleName": "ReturnTypeInfer_UseComponentStyleResult",
"Expression": "Kind == \"ReturnType\" && FunctionName.EndsWith(\"indexDefault\")",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "\"UseComponentStyleResult\""
}
}
}
},
{
"RuleName": "ReturnTypeInfer_CSSInterpolation",
"Expression": "Kind == \"ReturnType\" && (FunctionName == \"genStyleHooks\" || FunctionName == \"genSubStyleComponent\") && ValueType == \"array\"",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "\"CSSInterpolation\""
}
}
}
},
{
"RuleName": "ParameterTypeInfer_Token",
"Expression": "Kind == \"ParameterType\" && Name.EndsWith(\"token\")",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "FunctionName.EndsWith(\"ComponentToken\") ? \"GlobalToken\" : CsOptions.NamePrefix + \"Token\""
}
}
}
},
{
"RuleName": "ParameterTypeInfer_CalcColor",
"Expression": "Kind == \"ParameterType\" && FunctionName == \"genPresetColor\"",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "Name.Contains(\"binding\") ? \"CalcColor\" : \"string\""
}
}
}
},
{
"RuleName": "ParameterTypeInfer_StringColor",
"Expression": "Kind == \"ParameterType\" && Name.Contains(\"Color\")",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "\"string\""
}
}
}
},
{
"RuleName": "PropertyTypeInfer_String",
"Expression": "Kind == \"PropertyType\" && UnionType != null",
"Actions": {
"OnSuccess": {
"Name": "OutputExpression",
"Context": {
"Expression": "\"CSSProperties\""
}
}
}
}
]
}
```

Where `Include` and `Exclude` are relative to the path of the react project, if you clone with a different path, please modify this configuration.

- Execute Convert Command

Execute the following command at the root path of the blazor project.

```bash
cssincs convert -c cssincs.json
```

After the command is executed, all .ts files will be converted to .cs files. If `Dest` specifies a folder instead of a file, the final file will be generated according to the directory of the source file.

## Legacy ssues
- Since C# doesn't support UnionType, like multiple inheritance or `Pick<T>`, `Omit<T>`, etc., are not possible.

To solve this problem, we plan to use a source generator to achieve the effect of Pick and Omit.

- Antd-Style library is not implemented

Sample code:

```cs
var style = new
{
container = new CSSObject
{
MaxWidth = 400,
Width = '100%',
Height = 180,
Display = 'flex',
},
card = css(@"
margin-bottom: 8px;
cursor: pointer;
&:hover {
color: #DDD;
}
")
}

<div class="@style.card"></div>
<div class="@cx('a-simple-create-style-demo-classname', styles.container)"></div>
```
To solve the above problems, you only need to implement a css() and cx() method. CssInCSharp already supports the serialization of a `string` or a `CSSObject`.
13 changes: 13 additions & 0 deletions generators/CssInCSharp.Ast.Css/CssInCSharp.Ast.Css.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\CssInCSharp.Ast\CssInCSharp.Ast.csproj" />
</ItemGroup>

</Project>
Loading
Loading