Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add code generator for typescript to csharp #31

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,3 +83,11 @@ AMD Ryzen 7 5700G with Radeon Graphics, 1 CPU, 16 logical and 8 physical cores
| CreateCss | .NET 7.0 | .NET 7.0 | 50.61 μs | 0.999 μs | 2.062 μs | 0.87 | 0.05 | 17.6392 | 1.0376 | 144.42 KB | 0.96 |
| CreateCss | .NET 8.0 | .NET 8.0 | 37.73 μs | 0.748 μs | 1.642 μs | 0.65 | 0.03 | 17.6392 | 0.9155 | 144.3 KB | 0.96 |


## Special Thanks

[cssinjs](https://github.com/ant-design/cssinjs): Component level cssinjs solution used in ant.design.
[stylis](https://github.com/thysultan/stylis): A Light–weight CSS Preprocessor.
[csstype](https://github.com/frenic/csstype): TypeScript and Flow definitions for CSS.
[tinycolor](https://github.com/scttcper/tinycolor): A small library for color manipulation and conversion.
[TypeScriptAST](https://github.com/ToCSharp/TypeScriptAST): .NET port of TypeScript parser.
129 changes: 129 additions & 0 deletions generators/CssInCSharp.Ast.TypeScript/Change/ChangeAST.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Zu.TypeScript.TsTypes;

namespace Zu.TypeScript.Change
{
public class ChangeAST
{
private readonly ICollection<NodeChangeItem> _nodeChangeItems;

public ChangeAST(ICollection<NodeChangeItem> changeItems = null)
{
_nodeChangeItems = changeItems ?? new List<NodeChangeItem>();
}

public static string Change(string source, IEnumerable<NodeChangeItem> changeItems)
{
var changes = changeItems.OrderBy(v => v.Node.Pos).ThenBy(v2 => v2.ChangeType);
var sb = new StringBuilder();
var pos = 0;
foreach (var ch in changes)
{
if (ch.Node.Pos == null) throw new NullReferenceException("Node.Pos");
switch (ch.ChangeType)
{
case NodeChangeType.InsertBefore:
if (ch.Node.Pos > pos) sb.Append(source.Substring(pos, (int) ch.Node.Pos - pos));
sb.Append(ch.NewValue);
pos = (int) ch.Node.Pos;
break;
case NodeChangeType.Change:
if (ch.Node.Pos > pos) sb.Append(source.Substring(pos, (int) ch.Node.Pos - pos));
sb.Append(ch.NewValue);
if (ch.Node.End != null) pos = (int) ch.Node.End;
else throw new NullReferenceException("Node.End");
break;
case NodeChangeType.Delete:
if (ch.Node.Pos > pos) sb.Append(source.Substring(pos, (int) ch.Node.Pos - pos));
if (ch.Node.End != null) pos = (int) ch.Node.End + 1;
break;
case NodeChangeType.InsertAfter:
if (ch.Node.End > pos) sb.Append(source.Substring(pos, (int) ch.Node.End - pos));
sb.Append(ch.NewValue);
if (ch.Node.End != null) pos = (int) ch.Node.End;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
if (pos < source.Length) sb.Append(source.Substring(pos));
var newSource = sb.ToString();

return newSource;
}

public string GetChangedSource(string baseSource)
{
return Change(baseSource, _nodeChangeItems);
}

public void ChangeNode(INode node, string newValue)
{
if (_nodeChangeItems.Any(v => v.Node == node &&
(v.ChangeType == NodeChangeType.Change ||
v.ChangeType == NodeChangeType.Delete)))
throw new Exception("ChangeItems already have this node. Delete first");
if (_nodeChangeItems.Any(v => v.Node.Pos < node.Pos && v.Node.End > node.Pos))
throw new Exception("ChangeItems already have node that contains this node. Delete first");

if (newValue != node.GetTextWithComments())
{
var nodeCh = new NodeChangeItem {ChangeType = NodeChangeType.Change, Node = node, NewValue = newValue};
_nodeChangeItems.Add(nodeCh);
}
else
{
throw new Exception("Same value");
}
}

public void InsertBefore(INode node, string newValue)
{
if (node != null)
{
//if (_nodeChangeItems.Any(v => v.Node.Pos < node.Pos && v.Node.End > node.Pos))
// throw new Exception("ChangeItems already have node that contains this node. Delete first");

var nodeCh = new NodeChangeItem
{
ChangeType = NodeChangeType.InsertBefore,
Node = node,
NewValue = newValue
};
_nodeChangeItems.Add(nodeCh);
}
}

public void InsertAfter(INode node, string newValue)
{
if (node != null)
{
//if (_nodeChangeItems.Any(v => v.Node.Pos < node.Pos && v.Node.End > node.Pos))
// throw new Exception("ChangeItems already have node that contains this node. Delete first");

var nodeCh = new NodeChangeItem
{
ChangeType = NodeChangeType.InsertAfter,
Node = node,
NewValue = newValue
};
_nodeChangeItems.Add(nodeCh);
}
}

public void Delete(INode node)
{
if (node != null)
{
if (_nodeChangeItems.Any(v => v.Node.Pos < node.Pos && v.Node.End > node.Pos))
throw new Exception("ChangeItems already have node that contains this node. Delete first");

var nodeCh = new NodeChangeItem {ChangeType = NodeChangeType.Delete, Node = node};
_nodeChangeItems.Add(nodeCh);
}
}
}
}
27 changes: 27 additions & 0 deletions generators/CssInCSharp.Ast.TypeScript/Change/NodeChangeItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Zu.TypeScript.TsTypes;

namespace Zu.TypeScript.Change
{
public class NodeChangeItem
{
public NodeChangeType ChangeType { get; set; }

public INode Node { get; set; }
//public int Pos { get; set; }

//public int End { get; set; }
public string NewValue { get; set; }

private string NewValueSmall => NewValue == null
? ""
: NewValue.Length > 20
? NewValue.Substring(0, 18) + $"..({NewValue.Length})"
: NewValue;

public override string ToString()
{
if (ChangeType == NodeChangeType.Delete) return $"{ChangeType} {Node}.";
return $"{ChangeType} {Node}. NewValue = \"{NewValueSmall}\"";
}
}
}
10 changes: 10 additions & 0 deletions generators/CssInCSharp.Ast.TypeScript/Change/NodeChangeType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Zu.TypeScript.Change
{
public enum NodeChangeType
{
InsertBefore,
Change,
Delete,
InsertAfter
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

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

</Project>
1 change: 1 addition & 0 deletions generators/CssInCSharp.Ast.TypeScript/NOTICE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
CssInCSharp.Ast.TypeScript is based TypeScriptAST project hosted on https://github.com/ToCSharp/TypeScriptAST distributed with Apache 2.0 license.
Loading
Loading