diff --git a/confluence-mdx/bin/convert_all.py b/confluence-mdx/bin/convert_all.py index 5e8b3872d..6abccf626 100755 --- a/confluence-mdx/bin/convert_all.py +++ b/confluence-mdx/bin/convert_all.py @@ -22,10 +22,21 @@ import yaml +# Resolve project root (confluence-mdx/) from this script's location +_SCRIPT_DIR = Path(__file__).resolve().parent # confluence-mdx/bin/ +_PROJECT_DIR = _SCRIPT_DIR.parent # confluence-mdx/ + # Ensure bin/ is on sys.path -_bin_dir = str(Path(__file__).resolve().parent) -if _bin_dir not in sys.path: - sys.path.insert(0, _bin_dir) +if str(_SCRIPT_DIR) not in sys.path: + sys.path.insert(0, str(_SCRIPT_DIR)) + + +def _resolve(rel: str) -> str: + """Resolve a relative path against _PROJECT_DIR (confluence-mdx/).""" + p = Path(rel) + if p.is_absolute(): + return rel + return str(_PROJECT_DIR / rel) def load_pages_yaml(pages_yaml_path: str) -> List[Dict]: @@ -131,7 +142,7 @@ def convert_all(pages: List[Dict], var_dir: str, output_base_dir: str, public_di os.makedirs(output_dir, exist_ok=True) cmd = [ - sys.executable, os.path.join(_bin_dir, 'converter', 'cli.py'), + sys.executable, str(_SCRIPT_DIR / 'converter' / 'cli.py'), input_file, output_file, f'--public-dir={public_dir}', f'--attachment-dir={attachment_dir}', @@ -170,6 +181,13 @@ def main(): help='Log level for converter/cli.py (default: warning)') args = parser.parse_args() + # Resolve relative paths against project root (confluence-mdx/) + args.pages_yaml = _resolve(args.pages_yaml) + args.var_dir = _resolve(args.var_dir) + args.output_dir = _resolve(args.output_dir) + args.public_dir = _resolve(args.public_dir) + args.translations = _resolve(args.translations) + # Load data pages = load_pages_yaml(args.pages_yaml) translations = load_translations(args.translations) diff --git a/confluence-mdx/bin/converter/cli.py b/confluence-mdx/bin/converter/cli.py index 8b7c269a8..6440f4797 100755 --- a/confluence-mdx/bin/converter/cli.py +++ b/confluence-mdx/bin/converter/cli.py @@ -16,10 +16,14 @@ import yaml +# Resolve project root (confluence-mdx/) from this script's location +# bin/converter/cli.py -> .parent=converter/ -> .parent=bin/ -> .parent=confluence-mdx/ +_SCRIPT_DIR = Path(__file__).resolve().parent.parent # confluence-mdx/bin/ +_PROJECT_DIR = _SCRIPT_DIR.parent # confluence-mdx/ + # Ensure bin/ is on sys.path when run as a script (e.g. bin/converter/cli.py) -_bin_dir = str(Path(__file__).resolve().parent.parent) -if _bin_dir not in sys.path: - sys.path.insert(0, _bin_dir) +if str(_SCRIPT_DIR) not in sys.path: + sys.path.insert(0, str(_SCRIPT_DIR)) import converter.context as ctx from converter.context import ( @@ -111,7 +115,7 @@ def main(): parser.add_argument('input_file', help='Input XHTML file path') parser.add_argument('output_file', help='Output Markdown file path') parser.add_argument('--public-dir', - default='./public', + default=str(_PROJECT_DIR / 'public'), help='/public directory path') parser.add_argument('--attachment-dir', help='Directory to save attachments (default: output file directory)') diff --git a/confluence-mdx/bin/fetch/config.py b/confluence-mdx/bin/fetch/config.py index 03fa8fe93..c402f0508 100644 --- a/confluence-mdx/bin/fetch/config.py +++ b/confluence-mdx/bin/fetch/config.py @@ -2,8 +2,13 @@ import os from dataclasses import dataclass +from pathlib import Path from typing import Optional +# Resolve project root (confluence-mdx/) from this module's location +# bin/fetch/config.py -> .parent=fetch/ -> .parent=bin/ -> .parent=confluence-mdx/ +_PROJECT_DIR = Path(__file__).resolve().parent.parent.parent # confluence-mdx/ + @dataclass class Config: @@ -26,3 +31,9 @@ def __post_init__(self): self.email = os.environ.get('ATLASSIAN_USERNAME', 'your-email@example.com') if self.api_token is None: self.api_token = os.environ.get('ATLASSIAN_TOKEN', 'your-api-token') + + # Resolve relative paths against project root (confluence-mdx/) + for field in ('default_output_dir', 'cache_dir', 'translations_file'): + value = getattr(self, field) + if not os.path.isabs(value): + setattr(self, field, str(_PROJECT_DIR / value)) diff --git a/confluence-mdx/bin/restore_alt_from_diff.py b/confluence-mdx/bin/restore_alt_from_diff.py index 8b5626fb1..742b98290 100755 --- a/confluence-mdx/bin/restore_alt_from_diff.py +++ b/confluence-mdx/bin/restore_alt_from_diff.py @@ -13,12 +13,19 @@ from pathlib import Path from typing import Dict, List, Tuple +# Resolve repo root from this script's location +# Script is at confluence-mdx/bin/restore_alt_from_diff.py +_SCRIPT_DIR = Path(__file__).resolve().parent # confluence-mdx/bin/ +_PROJECT_DIR = _SCRIPT_DIR.parent # confluence-mdx/ +_REPO_ROOT = _PROJECT_DIR.parent # repo root + def get_diff_for_lang(lang: str) -> str: """특정 언어의 git diff 가져오기""" result = subprocess.run( ['git', 'diff', f'src/content/{lang}/'], - capture_output=True, text=True + capture_output=True, text=True, + cwd=str(_REPO_ROOT), ) return result.stdout @@ -120,7 +127,7 @@ def main(): total_changes = 0 for file_path_str, alt_mapping in file_mappings.items(): - file_path = Path(file_path_str) + file_path = _REPO_ROOT / file_path_str if not file_path.exists(): continue diff --git a/confluence-mdx/bin/skeleton/cli.py b/confluence-mdx/bin/skeleton/cli.py index c12ea9510..6cddea8c3 100755 --- a/confluence-mdx/bin/skeleton/cli.py +++ b/confluence-mdx/bin/skeleton/cli.py @@ -91,6 +91,10 @@ from pathlib import Path from typing import List, Tuple, Optional +# Resolve project root (confluence-mdx/) from this script's location +_SCRIPT_DIR = Path(__file__).resolve().parent.parent # confluence-mdx/bin/ +_PROJECT_DIR = _SCRIPT_DIR.parent # confluence-mdx/ + # Import modules for recursive processing and comparison from skeleton.compare import compare_files from skeleton.diff import ( @@ -1119,9 +1123,9 @@ def delete_skeleton_files(directories: List[Path]) -> int: if len(directories) == 0: # No directories specified, use defaults (Korean, Japanese, English order) default_dirs = [ - Path('target/ko'), - Path('target/ja'), - Path('target/en') + _PROJECT_DIR / 'target/ko', + _PROJECT_DIR / 'target/ja', + _PROJECT_DIR / 'target/en', ] directories = default_dirs diff --git a/confluence-mdx/bin/skeleton/common.py b/confluence-mdx/bin/skeleton/common.py index 2b25f2056..2bf1f6855 100644 --- a/confluence-mdx/bin/skeleton/common.py +++ b/confluence-mdx/bin/skeleton/common.py @@ -21,10 +21,10 @@ def extract_language_code(file_path: Path) -> Optional[str]: path_str = str(file_path) path_lower = path_str.lower() - # Check for language codes in the target/{lang}/ pattern at the start + # Check for language codes in the target/{lang}/ pattern (anywhere in path) for lang in ['ko', 'en', 'ja']: - pattern = r'^target[/\\]' + lang + r'[/\\]' - if re.match(pattern, path_lower): + pattern = r'target[/\\]' + lang + r'[/\\]' + if re.search(pattern, path_lower): return lang.lower() return None @@ -75,10 +75,10 @@ def get_path_without_lang_dir(file_path: Path) -> Optional[str]: path_str = str(file_path) path_lower = path_str.lower() - # Check for the target/{lang}/ pattern at the start (relative path only) + # Check for the target/{lang}/ pattern (anywhere in path) for lang in ['ko', 'en', 'ja']: - pattern = r'^target[/\\]' + lang + r'[/\\]' - match = re.match(pattern, path_lower) + pattern = r'target[/\\]' + lang + r'[/\\]' + match = re.search(pattern, path_lower) if match: end = match.end() relative_path = path_str[end:] diff --git a/confluence-mdx/bin/skeleton/compare.py b/confluence-mdx/bin/skeleton/compare.py index 1cea5b2ea..994c60e31 100644 --- a/confluence-mdx/bin/skeleton/compare.py +++ b/confluence-mdx/bin/skeleton/compare.py @@ -8,6 +8,10 @@ from pathlib import Path +# Resolve project root (confluence-mdx/) from this module's location +_SCRIPT_DIR = Path(__file__).resolve().parent.parent # confluence-mdx/bin/ +_PROJECT_DIR = _SCRIPT_DIR.parent # confluence-mdx/ + def get_mdx_files(directory: Path) -> set[str]: """ @@ -43,7 +47,7 @@ def compare_files(verbose: bool = False): verbose: If False, skip files that exist in all three languages. If True, output all files. """ - base_dir = Path('target') + base_dir = _PROJECT_DIR / 'target' dirs = { 'ko': base_dir / 'ko', 'en': base_dir / 'en', diff --git a/confluence-mdx/bin/skeleton/diff.py b/confluence-mdx/bin/skeleton/diff.py index cf81f8168..9a748f3c0 100644 --- a/confluence-mdx/bin/skeleton/diff.py +++ b/confluence-mdx/bin/skeleton/diff.py @@ -13,6 +13,10 @@ from pathlib import Path from typing import List, Tuple, Optional, Dict, Set +# Resolve project root (confluence-mdx/) from this module's location +_SCRIPT_DIR = Path(__file__).resolve().parent.parent # confluence-mdx/bin/ +_PROJECT_DIR = _SCRIPT_DIR.parent # confluence-mdx/ + try: import yaml except ImportError: @@ -184,11 +188,14 @@ def filter_diff_output( Returns: Filtered diff output with ignored lines removed. Returns empty string if all differences are ignored. """ - # Normalize file path (use forward slashes, remove leading slash if present) + # Normalize file path (use forward slashes, extract target/{lang}/... portion) file_path = file_path.replace('\\', '/') - if file_path.startswith('/'): + target_match = re.search(r'target/(?:ko|en|ja)/', file_path) + if target_match: + file_path = file_path[target_match.start():] + elif file_path.startswith('/'): file_path = file_path[1:] - + # Get ignore line numbers for this file ignore_lines = ignore_rules.get(file_path, set()) @@ -527,9 +534,9 @@ def process_directories_recursive(directories: List[Path], convert_func) -> Tupl if len(directories) == 0: # No directories specified, use defaults (Korean, Japanese, English order) default_dirs = [ - Path('target/ko'), - Path('target/ja'), - Path('target/en') + _PROJECT_DIR / 'target/ko', + _PROJECT_DIR / 'target/ja', + _PROJECT_DIR / 'target/en', ] directories = default_dirs diff --git a/confluence-mdx/bin/sync_confluence_url.py b/confluence-mdx/bin/sync_confluence_url.py index ae96ffac1..a2be73f08 100755 --- a/confluence-mdx/bin/sync_confluence_url.py +++ b/confluence-mdx/bin/sync_confluence_url.py @@ -26,6 +26,12 @@ from pathlib import Path from typing import List, Optional, Tuple +# Resolve repo root from this script's location +# Script is at confluence-mdx/bin/sync_confluence_url.py +_SCRIPT_DIR = Path(__file__).resolve().parent # confluence-mdx/bin/ +_PROJECT_DIR = _SCRIPT_DIR.parent # confluence-mdx/ +_REPO_ROOT = _PROJECT_DIR.parent # repo root + # --------------------------------------------------------------------------- # Path helpers @@ -221,8 +227,8 @@ def main() -> int: targets: List[Path] = [] if args.recursive is not None: dirs = args.recursive if args.recursive else [ - Path('src/content/en'), - Path('src/content/ja'), + _REPO_ROOT / 'src/content/en', + _REPO_ROOT / 'src/content/ja', ] targets = collect_mdx_files(dirs) elif args.files: