✨ feat(tsl-codegen): streamline generation workflow
Add explicit project-root output routing and require named input options with structured examples. Remove the unused HTML metadata enrichment command and its dedicated tests.
This commit is contained in:
@@ -21,7 +21,7 @@ Function declaration fields:
|
||||
tags optional list of Chinese keywords -> `<!-- tags: ... -->`
|
||||
params required when the signature takes args; omit for nullary
|
||||
returns required return type
|
||||
example optional fenced tsl block, pasted verbatim
|
||||
examples optional list of structured examples with desc/code/output fields
|
||||
Each param: name/type/desc required; optional (bool) -> `可选。` prefix;
|
||||
values (list of {value, desc}) -> a `name 取值` enum section.
|
||||
|
||||
@@ -29,6 +29,7 @@ Usage (run from repo root):
|
||||
python tools/tsl-codegen/scripts/generate.py --file entry.yml
|
||||
python tools/tsl-codegen/scripts/generate.py --file entry.json \
|
||||
--scope my-project
|
||||
python scripts/generate.py --file entry.json --root ../..
|
||||
python tools/tsl-codegen/scripts/generate.py --dir recordings
|
||||
"""
|
||||
|
||||
@@ -279,7 +280,6 @@ def validate_function(fn, where, *, returns_required, extra_fields=()):
|
||||
"tags",
|
||||
"params",
|
||||
"returns",
|
||||
"example",
|
||||
"examples",
|
||||
*extra_fields,
|
||||
}
|
||||
@@ -292,12 +292,6 @@ def validate_function(fn, where, *, returns_required, extra_fields=()):
|
||||
non_empty_string(fn.get("returns"), f"{where}:缺少 returns")
|
||||
elif "returns" in fn:
|
||||
optional_draft_string(fn["returns"], f"{where}: returns")
|
||||
require(
|
||||
not ("example" in fn and "examples" in fn),
|
||||
f"{where}:example 和 examples 不能同时存在",
|
||||
)
|
||||
if "example" in fn:
|
||||
non_empty_string(fn["example"], f"{where}: example")
|
||||
if "examples" in fn:
|
||||
validate_examples(fn["examples"], where)
|
||||
return name
|
||||
@@ -333,7 +327,6 @@ def validate_class_member(member, where):
|
||||
"params",
|
||||
"returns",
|
||||
"modifiers",
|
||||
"example",
|
||||
"examples",
|
||||
},
|
||||
where,
|
||||
@@ -600,14 +593,6 @@ def render_examples(fn, heading_level):
|
||||
while lines and not lines[-1]:
|
||||
lines.pop()
|
||||
return lines
|
||||
if fn.get("example"):
|
||||
return [
|
||||
f"{'#' * heading_level} 示例",
|
||||
"",
|
||||
"```tsl",
|
||||
*fn["example"].rstrip("\n").split("\n"),
|
||||
"```",
|
||||
]
|
||||
return []
|
||||
|
||||
|
||||
@@ -822,7 +807,7 @@ def format_markdown(text):
|
||||
return result.stdout
|
||||
|
||||
|
||||
def output_path(data, scope):
|
||||
def output_path(data, scope, root=None):
|
||||
"""Build the leaf-page destination from the recording file's relative path."""
|
||||
relative = data.get("path")
|
||||
require(relative, "录入数据缺少 path")
|
||||
@@ -854,7 +839,8 @@ def output_path(data, scope):
|
||||
)
|
||||
relative_path = Path(*recorded_path.parts)
|
||||
return (
|
||||
Path("skills/tsl-api-reference/references/codegen")
|
||||
(Path(root) if root is not None else Path())
|
||||
/ "skills/tsl-api-reference/references/codegen"
|
||||
/ scope
|
||||
/ relative_path.with_suffix(".md")
|
||||
)
|
||||
@@ -902,14 +888,14 @@ def gather_directory_inputs(directory, fmt):
|
||||
return inputs
|
||||
|
||||
|
||||
def prepare_input(in_path, input_format, scope):
|
||||
def prepare_input(in_path, input_format, scope, root=None):
|
||||
data = load_entries(in_path, input_format)
|
||||
try:
|
||||
rendered = render_page(data)
|
||||
except GenerationError as exc:
|
||||
raise GenerationError(f"录入数据校验失败:{exc}") from exc
|
||||
try:
|
||||
out_path = output_path(data, scope)
|
||||
out_path = output_path(data, scope, root)
|
||||
except GenerationError as exc:
|
||||
raise GenerationError(f"输出路径无效:{exc}") from exc
|
||||
try:
|
||||
@@ -941,11 +927,14 @@ def find_output_collisions(prepared):
|
||||
def main(argv=None):
|
||||
if hasattr(sys.stdout, "reconfigure"):
|
||||
sys.stdout.reconfigure(encoding="utf-8")
|
||||
if hasattr(sys.stderr, "reconfigure"):
|
||||
sys.stderr.reconfigure(encoding="utf-8")
|
||||
parser = ChineseArgumentParser(
|
||||
description="从 YAML/JSON 录入文件生成 TSL API 文档",
|
||||
usage=(
|
||||
"%(prog)s [--help] [--scope SCOPE] [--format {json,yaml}] "
|
||||
"(--file INPUT_FILE | --dir INPUT_DIR | INPUT_FILE)"
|
||||
"%(prog)s [--help] [--root ROOT_DIR] [--scope SCOPE] "
|
||||
"[--format {json,yaml}] "
|
||||
"(--file INPUT_FILE | --dir INPUT_DIR)"
|
||||
),
|
||||
add_help=False,
|
||||
allow_abbrev=False,
|
||||
@@ -955,12 +944,6 @@ def main(argv=None):
|
||||
action="help",
|
||||
help="显示本帮助并退出(不提供 -h 短选项)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"legacy_input",
|
||||
nargs="?",
|
||||
metavar="INPUT_FILE",
|
||||
help="已废弃,请使用 --file;暂时兼容 YAML/JSON 录入文件路径",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--file",
|
||||
dest="input_file",
|
||||
@@ -973,6 +956,11 @@ def main(argv=None):
|
||||
metavar="INPUT_DIR",
|
||||
help="批量生成目录中的直属 YAML/JSON 录入文件",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--root",
|
||||
metavar="ROOT_DIR",
|
||||
help="包含 skills 目录的项目根目录(默认:当前工作目录)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--scope",
|
||||
type=scope_name,
|
||||
@@ -986,16 +974,16 @@ def main(argv=None):
|
||||
)
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
input_modes = (args.legacy_input, args.input_file, args.input_dir)
|
||||
input_modes = (args.input_file, args.input_dir)
|
||||
if sum(value is not None for value in input_modes) != 1:
|
||||
parser.error("必须且只能指定一种输入方式:INPUT_FILE、--file 或 --dir")
|
||||
parser.error("必须且只能指定一种输入方式:--file 或 --dir")
|
||||
is_batch = args.input_dir is not None
|
||||
try:
|
||||
if is_batch:
|
||||
input_paths = gather_directory_inputs(Path(args.input_dir), args.format)
|
||||
input_format = None
|
||||
else:
|
||||
in_path = Path(args.input_file or args.legacy_input)
|
||||
in_path = Path(args.input_file)
|
||||
if not in_path.is_file():
|
||||
die(f"输入文件不存在或不是普通文件:{in_path}")
|
||||
input_paths = [in_path]
|
||||
@@ -1008,7 +996,9 @@ def main(argv=None):
|
||||
input_errors = []
|
||||
for in_path in input_paths:
|
||||
try:
|
||||
prepared.append(prepare_input(in_path, input_format, args.scope))
|
||||
prepared.append(
|
||||
prepare_input(in_path, input_format, args.scope, args.root)
|
||||
)
|
||||
except GenerationError as exc:
|
||||
input_errors.append((in_path, exc))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user