在 Manus 中运行任何 Skill
一键导入
一键导入
一键在 Manus 中运行任何 Skill
开始使用rsdn-dev
星标6
分支5
更新时间2026年4月25日 19:41
Правила разработки RsdnFormatter
安装
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
SKILL.md
readonly菜单
Правила разработки RsdnFormatter
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | rsdn-dev |
| description | Правила разработки RsdnFormatter |
// ✅ Правильно
namespace Rsdn.Framework.Formatting.BBCode.Nodes;
public class TextNode : Node { }
// ❌ Неправильно (для новых файлов)
namespace Rsdn.Framework.Formatting.BBCode.Nodes
{
public class TextNode : Node { }
}
Использовать для классов с обязательной инициализацией:
public class TagNode(string tagName, string? attribute = null) : Node
{
public string TagName { get; } = tagName.ToLowerInvariant();
public string? Attribute { get; } = attribute;
public List<Node> Children { get; } = [];
}
// ✅ Правильно
public List<Node> Children { get; } = [];
// ❌ Неправильно
public List<Node> Children { get; } = new List<Node>();
// ✅ Правильно
var document = new DocumentNode();
// Когда тип очевиден из контекста
Dictionary<string, string> map = new() { ["key"] = "value" };
// Switch expression
public override string ToString() => Type switch
{
TokenType.Text => $"Text: [{TextRange.Start}..{TextRange.End}]",
TokenType.OpenTag => $"OpenTag: [{TagNameRange.Start}..{TagNameRange.End}]",
_ => $"Unknown: {Type}"
};
// Pattern matching с is
if (child is TextNode textNode)
{
var text = textNode.Text;
}
namespace Rsdn.Framework.Formatting.CodeFormat;
public class CodeFormatter
{
//...
}
Использовать для работы с ReadOnlySpan<T> без аллокаций:
public ref struct Tokenizer(ReadOnlySpan<char> text)
{
private readonly ReadOnlySpan<char> _text = text;
public int Position { get; private set; } = 0;
}
Использовать для immutable структур данных:
public readonly struct Token
{
public TokenType Type { get; }
public int Position { get; }
}
Проект использует NRT — явно указывать ? для nullable типов:
public string? Attribute { get; } // Может быть null
public string TagName { get; } // Не может быть null
Использовать для обработки AST:
public interface INodeVisitor<TContext>
{
void Visit(DocumentNode node, TContext ctx);
void Visit(TagNode node, TContext ctx);
void Visit(TextNode node, TContext ctx);
}
public abstract class Node
{
public abstract void Accept<TContext>(INodeVisitor<TContext> visitor, TContext ctx);
}
Разделять лексический и синтаксический анализ:
Текст → Tokenizer → Токены → Parser → AST → Renderer → HTML
Использовать диапазоны в токенах для избежания аллокаций:
public readonly struct TextRange
{
public int Start { get; }
public int End { get; }
public int Length => End - Start;
}
// Преобразование в строку только при необходимости
public string? GetTextString(ReadOnlySpan<char> source)
{
var span = source.Slice(TextRange.Start, TextRange.Length);
return span.IsEmpty ? null : span.ToString();
}
MethodName_Scenario_ExpectedResult#region категориям (Tokenizer Tests, Parser Tests, Integration Tests)[Test]
public void Parser_BoldTag_ReturnsTagNode()
{
var parser = new Parser("[b]text[/b]");
var doc = parser.Parse();
Assert.AreEqual(1, doc.Children.Count);
Assert.IsInstanceOf<TagNode>(doc.Children[0]);
}