Skip to content

Commit 4528b41

Browse files
knowletcursoragent
andcommitted
feat: improve Unicode/exported structure support
- Add comprehensive pytest test suite with 26 test cases - Fix Unicode path handling using pathlib.Path - Support exported/flat RPG Maker structure (no www folder) - Auto-create plugins directory if missing - Add Python pytest CI job to GitHub Actions Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent a856d22 commit 4528b41

6 files changed

Lines changed: 615 additions & 35 deletions

File tree

.github/workflows/test.yml

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Node.js CI
1+
name: CI
22

33
on:
44
push:
@@ -7,20 +7,31 @@ on:
77
branches: [ "main", "master" ]
88

99
jobs:
10-
build:
11-
10+
node:
11+
name: Node.js
1212
runs-on: ubuntu-latest
13-
1413
strategy:
1514
matrix:
1615
node-version: [18.x, 20.x]
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Use Node.js ${{ matrix.node-version }}
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version: ${{ matrix.node-version }}
22+
cache: 'npm'
23+
- run: npm ci
24+
- run: npm test
1725

26+
python:
27+
name: Python (pytest)
28+
runs-on: ubuntu-latest
1829
steps:
19-
- uses: actions/checkout@v4
20-
- name: Use Node.js ${{ matrix.node-version }}
21-
uses: actions/setup-node@v4
22-
with:
23-
node-version: ${{ matrix.node-version }}
24-
cache: 'npm'
25-
- run: npm ci
26-
- run: npm test
30+
- uses: actions/checkout@v4
31+
- uses: actions/setup-python@v5
32+
with:
33+
python-version: "3.11"
34+
- name: Install dependencies
35+
run: pip install pytest -q
36+
- name: Run pytest
37+
run: pytest tests/test_install_plugin.py -v

install_plugin.py

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import os
33
import shutil
44
import json
5+
from pathlib import Path
56

67
PLUGIN_CONFIG = {
78
"name": "DynamicTranslation",
@@ -16,35 +17,64 @@
1617

1718

1819
def get_paths():
19-
arg_dir = sys.argv[1] if len(sys.argv) > 1 else os.getcwd()
20-
target_dir = os.path.abspath(arg_dir)
21-
if not os.path.isdir(target_dir):
22-
raise SystemExit(f"Invalid target directory: {target_dir}")
23-
24-
# Check if is in RPG Maker project www directory
25-
www_dir = os.path.join(target_dir, "www")
26-
if not os.path.isdir(www_dir):
27-
raise SystemExit(f"Invalid target directory: {target_dir}")
20+
# Use pathlib.Path for better unicode path handling
21+
if len(sys.argv) > 1:
22+
arg_dir = sys.argv[1]
23+
# Ensure proper unicode handling - pathlib handles this better than os.path
24+
target_path = Path(arg_dir).resolve()
25+
else:
26+
target_path = Path.cwd().resolve()
27+
28+
if not target_path.is_dir():
29+
raise SystemExit(f"Invalid target directory: {target_path}")
30+
31+
# Check for RPG Maker project structure
32+
# Support both traditional (project/www/js/) and exported/flat (project/js/) structures
33+
www_path = target_path / "www"
34+
js_path_in_www = www_path / "js"
35+
js_path_direct = target_path / "js"
36+
plugins_path_in_www = js_path_in_www / "plugins"
37+
plugins_path_direct = js_path_direct / "plugins"
38+
39+
if www_path.is_dir() and js_path_in_www.is_dir():
40+
# Traditional structure: project/www/js/
41+
www_dir = www_path
42+
js_path = js_path_in_www
43+
elif js_path_direct.is_dir():
44+
# Exported/flat structure: project/js/ (no www subdirectory)
45+
# Even without www, if js/plugins exists, we can install
46+
# Treat the project root as the "www" equivalent
47+
www_dir = target_path
48+
js_path = js_path_direct
49+
if plugins_path_direct.is_dir():
50+
print("Note: Detected exported/flat RPG Maker project structure (no www subdirectory)")
51+
else:
52+
print("Note: Detected exported/flat RPG Maker project structure (no www subdirectory)")
53+
print(f"Warning: plugins directory not found at {plugins_path_direct}")
54+
else:
55+
# Neither structure found
56+
raise SystemExit(
57+
f"Invalid target directory: {target_path}\n"
58+
"Expected RPG Maker project with either:\n"
59+
" - Traditional structure: project/www/js/\n"
60+
" - Exported structure: project/js/ (with or without plugins subdirectory)"
61+
)
2862

29-
# Basic sanity: must contain js directory
30-
js_dir = os.path.join(www_dir, "js")
31-
if not os.path.isdir(js_dir):
32-
print(f"Warning: {js_dir} not found; continuing but some steps may be skipped.")
33-
script_dir = os.path.dirname(os.path.abspath(__file__))
34-
return target_dir, www_dir, script_dir
63+
script_path = Path(__file__).resolve().parent
64+
65+
# Return as strings for backward compatibility with rest of code
66+
return str(target_path), str(www_dir), str(script_path)
3567

3668

3769
def copy_plugin_file(script_dir, target_dir):
3870
plugin_source = os.path.join(script_dir, "DynamicTranslation.js")
3971
plugin_dest_dir = os.path.join(target_dir, "js", "plugins")
4072
plugin_dest = os.path.join(plugin_dest_dir, "DynamicTranslation.js")
4173

74+
# Create plugins directory if it doesn't exist
4275
if not os.path.exists(plugin_dest_dir):
43-
print(f"Error: plugins directory not found at {plugin_dest_dir}")
44-
print(
45-
"Make sure you are running this script in the root of an RPG Maker project."
46-
)
47-
sys.exit(1)
76+
print(f"Creating plugins directory at {plugin_dest_dir}...")
77+
os.makedirs(plugin_dest_dir, exist_ok=True)
4878

4979
print("Copying DynamicTranslation.js...")
5080
shutil.copy2(plugin_source, plugin_dest)
@@ -88,8 +118,11 @@ def update_plugins_js(target_dir):
88118
print("plugins.js updated successfully.")
89119

90120

91-
def install_translation(target_dir):
92-
translations_dir = os.path.join(target_dir, "www", "translations")
121+
def install_translation(target_dir, www_dir):
122+
# translations folder should be relative to where HTML file is located
123+
# For traditional structure: www/translations/ (HTML is in www/)
124+
# For exported structure: translations/ (HTML is in project root, www_dir == target_dir)
125+
translations_dir = os.path.join(www_dir, "translations")
93126
print("Searching for translation files...")
94127

95128
if not os.path.exists(translations_dir):
@@ -133,7 +166,7 @@ def main():
133166

134167
copy_plugin_file(script_dir, www_dir)
135168
update_plugins_js(www_dir)
136-
install_translation(target_dir)
169+
install_translation(target_dir, www_dir)
137170

138171
print("Installation complete!")
139172

pyproject.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[project]
2+
name = "rpg-dynamic-translation"
3+
version = "1.0.0"
4+
description = "Dynamic translation system for RPG Maker MV/MZ"
5+
readme = "README.md"
6+
requires-python = ">=3.10"
7+
dependencies = []
8+
9+
[project.optional-dependencies]
10+
dev = [
11+
"pytest>=7.0.0",
12+
]
13+
14+
[tool.pytest.ini_options]
15+
testpaths = ["tests"]
16+
pythonpath = ["."]

requirements-dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest>=7.0.0

0 commit comments

Comments
 (0)