Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

scripts/set-page-title.py: add script #12732

Merged
merged 10 commits into from
May 9, 2024
2 changes: 2 additions & 0 deletions scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ This section contains a summary of the scripts available in this directory. For
- [send-to-bot.py](send-to-bot.py) is a Python script that send the build or tests output to tldr-bot.
- [set-alias-page.py](set-alias-page.py) is a Python script to generate or update alias pages.
- [set-more-info-link.py](set-more-info-link.py) is a Python script to generate or update more information links across pages.
- [set-page-title.py](set-page-title.py) is a Python script to update the title across pages.
- [test.sh](test.sh) script runs some basic tests on every PR/commit to make sure that the pages are valid and that the code is formatted correctly.
- [wrong-filename.sh](wrong-filename.sh) script checks the consistency between the filenames and the page title.
- [update-command.py](update-command.py) is a Python script to update the common contents of a command example across all languages.
Expand All @@ -29,5 +30,6 @@ The below table shows the compatibility of user-executable scripts with differen
| [build.sh](build.sh) | ✅ | ✅ | ❌ |
| [set-alias-pages.py](set-alias-pages.py) | ✅ | ✅ | ✅ |
| [set-more-info-link.py](set-more-info-link.py) | ✅ | ✅ | ✅ |
| [set-page-title.py](set-page-title.py) | ✅ | ✅ | ✅ |
| [wrong-filename.sh](wrong-filename.sh) | ✅ | ❌ | ❌ |
| [update-command.py](update-command.py) | ✅ | ✅ | ✅ |
194 changes: 194 additions & 0 deletions scripts/set-page-title.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: MIT

"""
This script sets the title for all translations of a page.
It can be used to update the titles in translations.

Note: Before running this script, ensure that TLDR_ROOT is set to the location
of a clone of https://github.com/tldr-pages/tldr, and 'git' is available.
If there is a symlink error when using the stage flag remove the `pages.en`
directory temporarily and try executing it again.
sebastiaanspeck marked this conversation as resolved.
Show resolved Hide resolved

Usage: python3 scripts/set-page-title.py [-p PAGE] [-s] [-S] [-n] [TITLE]

Supported Arguments:
-p, --page Specify the page name in the format "platform/command.md".
This option allows setting the title for a specific page.
-s, --stage Stage modified pages for commit. This option requires 'git'
to be on the $PATH and TLDR_ROOT to be a Git repository.
-S, --sync Synchronize each translation's title (if
exists) with that of the English page. This is useful to
ensure consistency across translations.
-n, --dry-run Show what changes would be made without actually modifying the page.

Positional Argument:
TITLE The title to be set as the title.

Examples:
1. Set the title for a specific page:
python3 scripts/set-page-title.py -p common/tar.md https://example.com
sebastiaanspeck marked this conversation as resolved.
Show resolved Hide resolved

2. Synchronize titles across translations:
python3 scripts/set-page-title.py -S

3. Synchronize titles across translations and stage modified pages for commit:
python3 scripts/set-page-title.py -Ss
python3 scripts/set-page-title.py --sync --stage

4. Show what changes would be made across translations:
python3 scripts/set-page-title.py -Sn
python3 scripts/set-page-title.py --sync --dry-run
"""

import argparse
import os
import subprocess
from pathlib import Path

IGNORE_FILES = (".DS_Store",)


def get_tldr_root() -> Path:
f = Path(__file__).resolve()
return next(path for path in f.parents if path.name == "tldr")

if "TLDR_ROOT" in os.environ:
return Path(os.environ["TLDR_ROOT"])
raise SystemError(
"\x1b[31mPlease set TLDR_ROOT to the location of a clone of https://github.com/tldr-pages/tldr."
)
sebastiaanspeck marked this conversation as resolved.
Show resolved Hide resolved


def set_title(path: Path, title: str, dry_run=False) -> str:
new_line = f"# {title}\n"

# Read the content of the Markdown file
with path.open(encoding="utf-8") as f:
lines = f.readlines()

if lines[0] == new_line:
# return empty status to indicate that no changes were made
return ""

if dry_run:
status = "title will be updated"
sebastiaanspeck marked this conversation as resolved.
Show resolved Hide resolved
sebastiaanspeck marked this conversation as resolved.
Show resolved Hide resolved
sebastiaanspeck marked this conversation as resolved.
Show resolved Hide resolved
else:
status = "title updated"

status = f"\x1b[34m{status}\x1b[0m"

if not dry_run:
lines[0] = new_line
with path.open("w", encoding="utf-8") as f:
f.writelines(lines)

return status


def get_title(path: Path) -> str:
with path.open(encoding="utf-8") as f:
first_line = f.readline().strip()

return first_line.split("#", 1)[-1].strip()


def sync(
root: Path, pages_dirs: list[str], command: str, title: str, dry_run=False
) -> list[str]:
paths = []
for page_dir in pages_dirs:
path = root / page_dir / command
if path.exists():
rel_path = "/".join(path.parts[-3:])
status = set_title(path, title, dry_run)
if status != "":
paths.append(path)
print(f"\x1b[32m{rel_path} {status}\x1b[0m")
return paths


def main():
parser = argparse.ArgumentParser(
description="Sets the title for all translations of a page"
)
parser.add_argument(
"-p",
"--page",
type=str,
required=False,
default="",
help='page name in the format "platform/command.md"',
)
parser.add_argument(
"-s",
"--stage",
action="store_true",
default=False,
help="stage modified pages (requires `git` to be on $PATH and TLDR_ROOT to be a Git repository)",
)
parser.add_argument(
"-S",
"--sync",
action="store_true",
default=False,
help="synchronize each translation's title (if exists) with that of English page",
)
parser.add_argument(
"-n",
"--dry-run",
action="store_true",
default=False,
help="show what changes would be made without actually modifying the pages",
)
parser.add_argument("title", type=str, nargs="?", default="")
args = parser.parse_args()

root = get_tldr_root()
pages_dirs = [d for d in root.iterdir() if d.name.startswith("pages")]

target_paths = []

# Use '--page' option
if args.page != "":
if not args.page.lower().endswith(".md"):
args.page = f"{args.page}.md"
arg_platform, arg_page = args.page.split("/")

for pages_dir in pages_dirs:
page_path = pages_dir / arg_platform / arg_page
if not page_path.exists():
continue
target_paths.append(page_path)

target_paths.sort()

for path in target_paths:
rel_path = "/".join(path.parts[-3:])
status = set_title(path, args.title)
if status != "":
print(f"\x1b[32m{rel_path} {status}\x1b[0m")

# Use '--sync' option
elif args.sync:
sebastiaanspeck marked this conversation as resolved.
Show resolved Hide resolved
pages_dirs.remove(root / "pages")
en_path = root / "pages"
platforms = [i.name for i in en_path.iterdir() if i.name not in IGNORE_FILES]
for platform in platforms:
platform_path = en_path / platform
commands = [
f"{platform}/{page.name}"
for page in platform_path.iterdir()
if page not in IGNORE_FILES
]
for command in commands:
title = get_title(root / "pages" / command)
if title != "":
target_paths += sync(root, pages_dirs, command, title, args.dry_run)

if args.stage and not args.dry_run and len(target_paths) > 0:
subprocess.call(["git", "add", *target_paths], cwd=root)


if __name__ == "__main__":
main()