mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 13:40:11 +01:00
Not sure how these got missed when moving other things to `uv`, but this should clean them up. The bump to Python 3.12 is so that we can use `@override` with the simple import from `typing`. This is needed by the newest versions of `ty` to do type checking. Added the relevant `@override` annotations. Assisted-by: Antigravity with Gemini
213 lines
6.5 KiB
Python
Executable File
213 lines
6.5 KiB
Python
Executable File
#!/usr/bin/env -S uv run --script
|
|
|
|
# /// script
|
|
# requires-python = ">=3.12"
|
|
# ///
|
|
|
|
"""Updates files in preparation for a jekyll build.
|
|
|
|
Used from .github/workflows/gh_pages.yaml. This updates the file and directory
|
|
structure prior to the jekyll build.
|
|
"""
|
|
|
|
import dataclasses
|
|
import os
|
|
import re
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
__copyright__ = """
|
|
Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
Exceptions. See /LICENSE for license information.
|
|
SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
"""
|
|
|
|
|
|
@dataclasses.dataclass
|
|
class ChildDir:
|
|
"""Tracks whether a child directory has grandchildren."""
|
|
|
|
title: str
|
|
has_grandchildren: bool = False
|
|
|
|
|
|
def get_title(f: Path, content: str) -> str:
|
|
"""Returns a file's title according to markdown.
|
|
|
|
Replacements are for YAML compatibility in `add_frontmatter`.
|
|
"""
|
|
m = re.search("^# (.*)$", content, re.MULTILINE)
|
|
assert m, f
|
|
title = m[1]
|
|
title = title.replace("\\", "\\\\")
|
|
title = title.replace('"', '\\"')
|
|
title = re.sub("`([^`]+)`", r"<code>\1</code>", title)
|
|
return title
|
|
|
|
|
|
def add_frontmatter(
|
|
f: Path,
|
|
orig_content: str,
|
|
titles: list[str],
|
|
nav_order: Optional[int],
|
|
has_children: bool,
|
|
) -> None:
|
|
"""Adds frontmatter to a file."""
|
|
content = "---\n"
|
|
|
|
assert len(titles) <= 3
|
|
content += f'title: "{titles[-1]}"\n'
|
|
if len(titles) >= 2:
|
|
content += f'parent: "{titles[-2]}"\n'
|
|
if len(titles) == 3:
|
|
content += f'grand_parent: "{titles[-3]}"\n'
|
|
|
|
if nav_order is not None:
|
|
content += f"nav_order: {nav_order}\n"
|
|
if has_children:
|
|
# has_toc is disabling the list of child files in a separate table of
|
|
# contents.
|
|
content += "has_children: true\nhas_toc: false\n"
|
|
content += "---\n\n" + orig_content
|
|
f.write_text(content)
|
|
|
|
|
|
def label_subdir(
|
|
subdir_str: str,
|
|
top_nav_order: int,
|
|
parent_title: Optional[str] = None,
|
|
grandchild_dirs: bool = False,
|
|
) -> None:
|
|
"""Automatically adds child information to a subdirectory's markdown files.
|
|
|
|
This is in support of navigation.
|
|
"""
|
|
assert not (parent_title and grandchild_dirs)
|
|
|
|
subdir = Path(subdir_str)
|
|
readme = subdir / "README.md"
|
|
readme_content = readme.read_text()
|
|
|
|
def include_child(md_file: Path) -> bool:
|
|
"""Returns whether md_file is a child of this label."""
|
|
# The top-level README.md isn't a child.
|
|
if md_file == readme:
|
|
return False
|
|
# Skip directories that aren't part of the repository.
|
|
if "/node_modules/" in str(md_file):
|
|
return False
|
|
if "/dist/" in str(md_file):
|
|
return False
|
|
return True
|
|
|
|
readme_title = get_title(readme, readme_content)
|
|
readme_titles = [readme_title]
|
|
if parent_title:
|
|
readme_titles.insert(0, parent_title)
|
|
children = [x for x in subdir.glob("**/*.md") if include_child(x)]
|
|
add_frontmatter(
|
|
readme, readme_content, readme_titles, top_nav_order, bool(children)
|
|
)
|
|
|
|
if grandchild_dirs:
|
|
# When adding grandchildren, we cluster files by child directory.
|
|
child_dirs = {}
|
|
for child in children:
|
|
if child.name == "README.md":
|
|
title = get_title(child, child.read_text())
|
|
child_dirs[child.parent] = ChildDir(title)
|
|
for child in children:
|
|
if child.name != "README.md" and child.parent in child_dirs:
|
|
child_dirs[child.parent].has_grandchildren = True
|
|
|
|
for child in children:
|
|
child_content = child.read_text()
|
|
child_title = get_title(child, child_content)
|
|
child_nav_order = None
|
|
|
|
if subdir_str == "proposals":
|
|
# Use proposal numbers as part of the title and ordering.
|
|
m = re.match(r"p(\d+)(?:-.*)?\.md", child.name)
|
|
# Skip files that aren't proposals.
|
|
if not m:
|
|
continue
|
|
child_title = f"#{m[1]}: {child_title}"
|
|
child_nav_order = int(m[1])
|
|
|
|
titles = [readme_title, child_title]
|
|
has_children = False
|
|
if parent_title:
|
|
titles.insert(0, parent_title)
|
|
elif grandchild_dirs and child.parent in child_dirs:
|
|
if child.name == "README.md":
|
|
has_children = child_dirs[child.parent].has_grandchildren
|
|
else:
|
|
dir_title = child_dirs[child.parent].title
|
|
titles.insert(1, dir_title)
|
|
|
|
add_frontmatter(
|
|
child, child_content, titles, child_nav_order, has_children
|
|
)
|
|
|
|
|
|
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))
|
|
label_root_file("SECURITY.md", "Security policy", next(nav_order))
|
|
|
|
# Reset the order for the implementation children.
|
|
nav_order[0] = 0
|
|
label_subdir(
|
|
"toolchain/docs", next(nav_order), parent_title="Implementation"
|
|
)
|
|
label_subdir("testing", next(nav_order), parent_title="Implementation")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|