mcpField
C
conformetry-configure

conformetry-configure

github.com/organizzolini开发0587 次安装2 天前更新
代码仓库

关于 conformetry-configure

用于配置 conformetry 生成器并编写模板的技能,说明输入、钩子、实例匹配、占位符和一致性阈值在命令行宿主与 Nx 插件中的行为。

主要功能

  1. 01生成器配置与校验
  2. 02实例组与路径匹配
  3. 03JSON Schema 输入设置
  4. 04生成钩子与文件系统规则
  5. 05Mustache 占位符与推断
  6. 06一致性阈值指南

适用场景

  1. 01为工作区模板定义生成器
  2. 02将实例限定到 Nx 项目或 glob
  3. 03在模板生成前后添加钩子
  4. 04排查占位符与一致性问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/organizzolini/codebase --skill conformetry-configure

安装后在 Claude Code 中输入/conformetry-configure确认已加载。

附带文件references/languages.md

详细介绍

配置 conformetry 并编写模板

生成器将一个名称与一个模板配对——一个普通文件夹,里面是普通文件——以及渲染模板所需的输入。配置声明生成器;模板文件夹则完整定义了要生成的内容。后续也会以同一个模板为基准来衡量实例,因此模板既是起点,也是标准。

配置

配置文件默认导出一个数组,每个生成器对应一个条目。只有两个必填字段:

字段必填含义
name是调用生成器时使用的名称
templatePath是相对于工作区根目录的模板文件夹
inputs否模板渲染时使用的值,以 JSON Schema 片段表示
instances否此生成器的输出已有的存放位置
description否列出生成器时显示
hooks否在生成前后运行的函数;参见 Hooks
threshold否此生成器的实例允许达到的最低符合度评分,范围为 0 到 1

不接受未知键,因此拼错字段,或使用已被彻底移除的 aliases,都会导致加载失败,而不是悄无声息地不起作用。可通过列出生成器来确认条目是否生效。每条 conformetry 命令都必须使用 --config <path>——没有默认配置文件:

conformetry templates --config configuration/conformetry.config.ts

未指定路径时,命令会失败,并抛出 ConfigurationPathRequiredError,指出未设置的标志或选项。在 Nx 中,这指的是 nx.json 里 @conformetry/nx 插件的 configurationPath 选项,或执行器和 sync 生成器的 configuration 选项。

没有 inputs 和 instances 的生成器也是合法的:它会渲染固定模板,后续不会对任何内容进行验证。

配置拒绝加载的四种冲突
  1. 两个生成器不得共用同一个 name。 宿主会解析第一个匹配项,使另一个生成器无法访问。
  2. 两个生成器不得指定同一个 templatePath。 验证时将无法判断匹配的实例属于哪个生成器。
  3. 名称不得为空,也不得包含路径分隔符。 名称会成为生成的 Nx 插件中的文件名。
  4. 名称不得为 all。 validate --templates all 已表示所有模板;若某个生成器也使用这个名称,同一个命令行参数就会有两种含义。
实例组:已有输出的存放位置

instances 是一个组列表,每组可选包含 patterns、exclude、tags、substitutions 和 threshold。设置分组是为了让不同路径集合使用不同的替换规则和符合度门槛。

exclude 用于列出相对于工作区的 glob,匹配的路径永远不会被视为实例。如果 exclude glob 匹配到由匹配模式找到的目录或文件,就会将其排除,无论是否设置了 tags。可用它排除与真实实例混在一起的第三方或生成代码,例如 shadcn 的组件输出: exclude: ["projects/lexico/lexico-web/src/components/ui/**"]。

在 Nx 插件中,tags 会改变组的含义:

  • 带有标签的组是项目选择器。 它适用于带有其中任一标签的所有项目,并会在每个选定项目内部读取其 patterns——因此 src/modules/* 在每个项目中都表示相同内容。
  • 不带标签的组是普通工作区 glob,按原样使用。
  • 带标签但不含模式的组只进行选择,不定位文件。 这样生成器就可以限定其可作用的项目,同时不验证任何内容。

目录模式和文件模式的行为不同,而这种差异决定了匹配项会由哪个模板胜出。各语言具体会如何比较,请参阅 references/languages.md。

输入

每个输入都是一个 JSON Schema 片段。以下键会生效;其他键均会被忽略:

键作用
description提示词文本
enum将提示词变为列表,并限制可选值
minLength / maxLength长度验证
pattern按 Unicode 正则表达式进行匹配

两个宿主对于输入是否必填意见不一,而且无法通过配置更改。 Nx 插件会将所有已声明的输入标记为必填。命令行宿主则将所有输入标记为非必填。编写模板时,应确保缺少值会在输出中一目了然,而不要假定任一宿主的行为。

在 Nx 插件下,有四个输入名称具有额外含义,值得有意使用,而非不经意间使用:project、module、type 和 directory 都会影响输出位置。如果生成器所属的组带有标签,声明名为 project 的输入还会将其变成项目选择器。

config、help、instancePath 和 template 是保留名称,永远不会被视为输入——--template 是命令行宿主用于选择要渲染的模板的参数。name 则特意不设为保留名称。

钩子

生成器可以声明带有 preGenerate 和 postGenerate 的 hooks:宿主在生成前后运行的普通函数。你可以用它在写入任何内容之前拒绝无效输入,或编辑模板无法管理的文件,例如索引文件或 helm values 文件。

  • preGenerate 在写入任何内容之前运行,此时 generatedFilePaths 为空。抛出异常即可拒绝本次运行。
  • postGenerate 在模板渲染完成后、格式化之前运行,此时 generatedFilePaths 已排序。

JSON 配置无法声明钩子,因为 JSON 无法包含函数;任何 JavaScript 或 TypeScript 配置都可以声明钩子。使用 @conformetry/configuration 中的 GeneratorHookContext 为钩子添加类型。以下三条规则可确保钩子在两个宿主下都能正常工作:

  • 通过 context.filesystem 写入,绝不要使用 node:fs。 在 Nx 下,适配器会写入虚拟树,因此 --dry-run 和运行失败都不会留下改动。
  • 为 context.filesystem 提供工作区内的绝对路径,并基于 context.configurationDirectoryPath 构建。在 Nx 下,工作区外的路径会被重新定位到工作区内。
  • 将写入的路径推入 context.generatedFilePaths,以便宿主对其进行格式化并报告。

在命令行宿主下,如果 postGenerate 抛出异常,已渲染的文件仍会留在磁盘上。生成 README 列出了完整的上下文表以及各宿主的错误行为,hooks 示例则会运行这两个钩子。

编写模板

文件夹本身就是定义。无需注册模板文件。

需要生成文件夹的模板必须包含该文件夹。 此时,其实例路径应设为该文件夹的_父级_。生成独立文件的模板则应将这些文件放在根目录下。如果弄错了,输出位置就会偏移一级。

占位符

渲染使用 Mustache,并关闭了 HTML 转义,因此请写 {{field}}, 不要写 {{{field}}}。路径使用与内容相同的花括号:名为 {{nameKebabCase}}.service.ts 的文件会渲染为 orders.service.ts。

始终提供从名称派生的四种命名格式:

占位符search bar 的结果
{{nameCamelCase}}searchBar
{{nameKebabCase}}search-bar
{{namePascalCase}}SearchBar
{{nameSnakeCase}}search_bar

显式输入和配置的替换项最后应用,因此始终优先于同名的派生格式。

如果某个占位符没有对应的输入,生成会拒绝执行。 它会引发 MissingSubstitutionError,并指出占位符和模板文件,以便拼写错误能明确报错,而不是留下无声的空缺或空路径段。

如果某个占位符没有对应的输入,验证会从实例中读取该占位符。 它会为占位符渲染一个随机替代值,并照常进行比较。如果包含该替代值的模板节点与某个实例节点对齐,就会捕获实例中对应位置的文本。按文件顺序、再按文档顺序,首次捕获的值会被采用。随后会使用该值重新渲染模板并再次比较,因此后续使用该占位符的位置若包含不同文本,就会被视为普通差异。如果没有任何节点对齐,验证会报告 Could not infer {{path}}: no instance node aligned with the template text that uses it 并且无论阈值如何,实例都会验证失败。

  • name 及其格式变体永远不会被推断;它们来自实例路径。
  • 配置的 substitutions 值始终优先于推断值。
  • 捕获方式遵循各语言自身的匹配规则:TypeScript 节点键(字符串字面量、声明名称,例如 class {{commandName}}Command、调用的第一个参数)、JSON 值、Markdown 节点文本(例如标题)以及纯文本行。占位符周围的字面文本必须完全匹配。Python、Jupyter、注释和文件路径不会捕获任何内容,因此只在这些位置使用的占位符必须显式提供。

以下两种情况仍然允许缺省,也是模板请求可选内容的方式:

  • 区段标签。 {{#owner}}Owner: {{owner}}{{/owner}} 和 {{^owner}}Unowned.{{/owner}} 是条件语句,因此缺少 owner 时不会报错,而是渲染为空。请在区段内插入变量,不要在区段外插入。
  • 提供空值。 substitutions: { owner: "" } 就是一个有效答案。只有缺少键才算空缺。

因此,只有当每个实例都在比较对齐的位置显示该值时,向模板添加占位符才对验证来说是安全的。否则,请在同一项更改中添加替换项。

没有条件文件机制

没有针对单个文件的谓词、扩展名过滤或跳过列表。树中的每个文件都会被渲染并写入。Mustache 区段可在内容内部使用,但由空占位符渲染出的路径会包含空段,而不是跳过文件。不要尝试寻找让文件变为可选的方法;这种机制不存在。

将值标记为可自由变化

包含 TODO 的注释是占位符:实例中的任意注释都能满足它。可将其用于在不同实例间确实会变化的说明性文字。

字符串字面量没有等效机制。 模板中的字符串必须逐字匹配,因此占位符说明或消息会成为每个实例的永久要求。最好将此类值留在模板之外,而不是固定成没人想要的措辞。

阈值

一致性按分数评定,而不只是通过或未通过;阈值是实例允许达到的最低分数。解析顺序由最具体到最宽泛:实例组的 threshold,然后是生成器的,再然后是运行级别的 --threshold,最后是 1。

除非正在迁移,否则不要设置。 默认值 1 表示完全匹配,这正是模板能成为标准而非建议的原因。将现有实例逐步迁移到新模板时,可以有意调低阈值,并在实例跟上后调高——永久调低的阈值意味着模板已无法描述其实例。

降低阈值不会抑制报告:通过了自身门槛的实例仍会显示差异。

更改配置后

Nx 生成器命名空间由配置生成,而且所有 conformetry 命令在命名空间过期时都会拒绝运行,而不是使用过时的定义:

nx sync

此部分涉及两种错误,它们都会指出各自的修复方法:

  • 文件与配置不同步——运行 nx sync。
  • 生成器指定的模板文件夹不存在——修正 templatePath,或创建该文件夹。

如果生成失败,依赖项安装只会发出警告,而不会失败,因此编辑到一半的配置不会导致所有人的安装中断。这也意味着此处的警告确实值得阅读。

检查你的工作

生成一个实例,然后检查它是否符合要求。新生成的实例按构造必然符合要求,因此任何差异都意味着模板与配置不一致——如何解读结果,请参阅 conformetry-validate 技能;生成步骤本身,请参阅 conformetry-generate。

与其阅读,不如亲自查看

conformetry-examples 包含 12 个自成一体的示例,每个示例都是一份完整配置,小到可以一口气读完。以下示例可以解答配置方面的问题:

  • hello-template — 必需的最少字段,以及模板的放置位置。
  • case-variants — 派生变体,以及如何覆盖其中一个。
  • scoring-thresholds — 两个实例组使用两个阈值,以及三个级别中哪一个优先。
  • ambiguous-attribution — 两个模板声明同一路径时会报告什么,以及为什么重复声明同一个 glob 是个错误。
  • nx-host — 按标签限定的实例组,以及没有项目图的宿主如何处理这些实例组。
  • hooks — 拒绝不合规名称的 preGenerate,以及写入回执的 postGenerate。
  • failure-modes — 未提供的占位符,且没有实例文本能揭示它;生成时会拒绝,验证时会报告。

完整索引请参阅其 AGENTS.md。

评论

支持 Markdown