Repository: carbon-language/carbon-lang
File: website/prebuild.py (Python)

Code before:
    # TODO: Use path.walk once we require Python 3.12.
    for root, dirs, files in os.walk(path, topdown=False):
        root_path = Path(root)
        for name in files:
            (root_path / name).unlink()
        for name in dirs:
            (root_path / name).rmdir()


def main() -> None:
    # Ensure this runs from the repo root.
    os.chdir(Path(__file__).parents[1])

    # bazel-generated symlinks interfere with jekyll because they may contain
    # broken symlinks.
    Path("bazel-out").unlink(missing_ok=True)
    Path("bazel-bin").unlink(missing_ok=True)
    Path("bazel-genfiles").unlink(missing_ok=True)
    # bazel-execroot interferes with jekyll because it's a broken symlink.
    Path("bazel-execroot").unlink()
    # This is a symlink to website/favicon.png, which is moved below.
    # TODO: Consider moving the icon to a location which won't break.
    Path("utils/vscode/images/icon.png").unlink()
    # This may contain a README.md file that jekyll can't parse and that
    # shouldn't appear in the navigation tree.
    unlink_dir(Path("utils/vscode/node_modules"))
    # This can cause a failure if jekyll has already been run prior to
    # prebuild.
    unlink_dir(Path("website/.jekyll-cache"))

    # The external symlink is created by scripts/create_compdb.py, and can
    # interfere with local execution.
    external = Path("external")
    if external.exists():
        external.unlink()

    # Move files to the repo root.
    for f in Path("website").iterdir():
        if f.name == "README.md":
            continue
        f.rename(f.name)

    # Use an object for a reference.
    nav_order = [0]

    # Returns an incrementing value for ordering.
    def next(nav_order: list[int]) -> int:
        nav_order[0] += 1
        return nav_order[0]

    label_root_file("README.md", "Home", next(nav_order))

Review comment (bug):
I think we may accrue other node_modules. I think broken symlinks were a particular issue due to how jekyll works, it'd error too early. For this, had you considered in `_config.yml`:

```
exclude:
- **/node_modules
```

https://jekyllrb.com/docs/configuration/options/
https://ruby-doc.org/3.3.5/File.html#method-c-fnmatch

Note, I'm not sure whether this would also work for the .jekyll-cache dir, might make sense for both?

Code after:
        )


def label_root_file(
    name: str, title: str, top_nav_order: int, has_children: bool = False
) -> None:
    """Adds frontmatter to a root file, like CONTRIBUTING.md."""
    f = Path(name)
    add_frontmatter(f, f.read_text(), [title], top_nav_order, has_children)


def main() -> None:
    # Ensure this runs from the repo root.
    os.chdir(Path(__file__).parents[1])

    # The external symlink is created by scripts/create_compdb.py, and can
    # interfere with local execution.
    external = Path("external")
    if external.exists():
        external.unlink()

    # Move files to the repo root.
    for f in Path("website").iterdir():
        if f.name in ["README.md", ".jekyll-cache", "_site"]:
            continue
        f.rename(f.name)

    # Use an object for a reference.
    nav_order = [0]

    # Returns an incrementing value for ordering.
    def next(nav_order: list[int]) -> int:
        nav_order[0] += 1
        return nav_order[0]

    label_root_file("README.md", "Home", next(nav_order))
    label_root_file("CONTRIBUTING.md", "Contributing", next(nav_order))
    label_subdir("docs/design", next(nav_order), grandchild_dirs=True)
    label_subdir("docs/guides", next(nav_order))
    label_subdir("docs/project", next(nav_order), grandchild_dirs=True)
    label_subdir("docs/spec", next(nav_order))
    # Provide a small file to cluster implementation-related directories.
    label_root_file(
        "implementation.md",
        "Implementation",
        next(nav_order),
        has_children=True,
    )
    label_subdir("utils", next(nav_order))
    label_subdir("proposals", next(nav_order))
    label_root_file("CODE_OF_CONDUCT.md", "Code of conduct", next(nav_order))