Skip to content

Commit c285b94

Browse files
committed
fix: add support for temlpate values in mod.toml
1 parent 2696507 commit c285b94

File tree

3 files changed

+69
-3
lines changed

3 files changed

+69
-3
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ curseforge_slug = "your-mod-slug"
4040
```
4141

4242
`loader` must be `forge`.
43+
Template placeholders like `${...}` are not allowed in `[mc-publish]` values.
4344

4445
Dependencies are read directly from `mods.toml` by mc-publish. No `dependencies.txt` is used.
4546
Only Forge is supported; `mods.toml` is required and is the single source of metadata.

scripts/mods_toml.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,39 @@ def find_mods_toml(root: Path) -> Path:
4040
return paths[0]
4141

4242

43+
def strip_inline_comment(line: str) -> str:
44+
return line.split("#", 1)[0].strip()
45+
46+
47+
def is_table_header(line: str) -> bool:
48+
stripped = strip_inline_comment(line)
49+
return stripped.startswith("[") and stripped.endswith("]")
50+
51+
52+
def is_mc_publish_header(line: str) -> bool:
53+
stripped = strip_inline_comment(line)
54+
return stripped.startswith("[mc-publish") or stripped.startswith("[[mc-publish")
55+
56+
57+
def extract_mc_publish_block(text: str) -> str:
58+
lines = text.splitlines()
59+
header_indices = [index for index, line in enumerate(lines) if strip_inline_comment(line) == "[mc-publish]"]
60+
if not header_indices:
61+
fail("Missing [mc-publish] table in mods.toml")
62+
if len(header_indices) > 1:
63+
fail("Multiple [mc-publish] tables found in mods.toml")
64+
65+
start_index = header_indices[0]
66+
end_index = len(lines)
67+
for index in range(start_index + 1, len(lines)):
68+
if is_table_header(lines[index]) and not is_mc_publish_header(lines[index]):
69+
end_index = index
70+
break
71+
72+
block_lines = lines[start_index:end_index]
73+
return "\n".join(block_lines) + "\n"
74+
75+
4376
def normalize_value(value: object | None) -> str | None:
4477
if value is None:
4578
return None
@@ -51,7 +84,8 @@ def normalize_value(value: object | None) -> str | None:
5184

5285
def read_metadata(mods_toml: Path) -> dict[str, str]:
5386
try:
54-
data = tomllib.loads(mods_toml.read_text())
87+
block_text = extract_mc_publish_block(mods_toml.read_text())
88+
data = tomllib.loads(block_text)
5589
except tomllib.TOMLDecodeError as exc:
5690
fail(f"Invalid TOML in {mods_toml}: {exc}")
5791

@@ -70,6 +104,8 @@ def read_metadata(mods_toml: Path) -> dict[str, str]:
70104
if value is None:
71105
missing.append(key)
72106
continue
107+
if "${" in value:
108+
fail(f"[mc-publish].{key} contains a template placeholder: {value}")
73109
values[key] = value
74110

75111
if missing:

setup.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,10 @@ def find_mods_toml() -> Path:
9393

9494
def read_mc_publish_table(mods_toml: Path) -> dict[str, str]:
9595
try:
96-
data = tomllib.loads(mods_toml.read_text())
96+
block_text = extract_mc_publish_block(mods_toml.read_text())
97+
if block_text is None:
98+
return {}
99+
data = tomllib.loads(block_text)
97100
except tomllib.TOMLDecodeError as exc:
98101
sys.exit(f"ERROR: Invalid TOML in {mods_toml}: {exc}")
99102
table = data.get("mc-publish")
@@ -107,6 +110,8 @@ def read_mc_publish_table(mods_toml: Path) -> dict[str, str]:
107110
def validate_file_value(name: str, value: str) -> tuple[bool, str]:
108111
if not value.strip():
109112
return False, "value cannot be empty"
113+
if "${" in value:
114+
return False, "value contains a template placeholder"
110115
if name == "loader" and value not in ALLOWED_LOADERS:
111116
allowed_list = ", ".join(sorted(ALLOWED_LOADERS))
112117
return False, f"loader must be one of: {allowed_list}"
@@ -129,6 +134,30 @@ def is_table_header(line: str) -> bool:
129134
return stripped.startswith("[") and stripped.endswith("]")
130135

131136

137+
def is_mc_publish_header(line: str) -> bool:
138+
stripped = strip_inline_comment(line)
139+
return stripped.startswith("[mc-publish") or stripped.startswith("[[mc-publish")
140+
141+
142+
def extract_mc_publish_block(text: str) -> str | None:
143+
lines = text.splitlines()
144+
header_indices = [index for index, line in enumerate(lines) if strip_inline_comment(line) == "[mc-publish]"]
145+
if not header_indices:
146+
return None
147+
if len(header_indices) > 1:
148+
sys.exit("ERROR: Multiple [mc-publish] tables found in mods.toml")
149+
150+
start_index = header_indices[0]
151+
end_index = len(lines)
152+
for index in range(start_index + 1, len(lines)):
153+
if is_table_header(lines[index]) and not is_mc_publish_header(lines[index]):
154+
end_index = index
155+
break
156+
157+
block_lines = lines[start_index:end_index]
158+
return "\n".join(block_lines) + "\n"
159+
160+
132161
def build_mc_publish_block(values: dict[str, str], ordered_keys: list[str]) -> list[str]:
133162
lines = ["[mc-publish]"]
134163
for key in ordered_keys:
@@ -148,7 +177,7 @@ def update_mc_publish_block(mods_toml: Path, values: dict[str, str], ordered_key
148177
if start_index is not None:
149178
end_index = len(lines)
150179
for index in range(start_index + 1, len(lines)):
151-
if is_table_header(lines[index]):
180+
if is_table_header(lines[index]) and not is_mc_publish_header(lines[index]):
152181
end_index = index
153182
break
154183
block_lines = lines[start_index + 1 : end_index]

0 commit comments

Comments
 (0)