diff --git a/.codespell_ignore b/.codespell_ignore index 074d29fcbc5f2..850ff0d54881d 100644 --- a/.codespell_ignore +++ b/.codespell_ignore @@ -16,4 +16,5 @@ inout parameteras pullrequest rightt +rouge statics diff --git a/.github/workflows/gh_pages_ci.yaml b/.github/workflows/gh_pages_ci.yaml new file mode 100644 index 0000000000000..0a4650cfb2cbe --- /dev/null +++ b/.github/workflows/gh_pages_ci.yaml @@ -0,0 +1,41 @@ +# 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 + +name: GitHub Pages CI + +on: + pull_request: + +# Cancel previous workflows on the PR when there are multiple fast commits. +# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Prebuild actions + run: ./website/prebuild.py + - name: Setup Ruby + uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0 + with: + # Runs 'bundle install' and caches installed gems automatically. + bundler-cache: true + # Increment this number if you need to re-download cached gems. + cache-version: 0 + - name: Build with Jekyll + run: bundle exec jekyll build diff --git a/.github/workflows/gh_pages_deploy.yaml b/.github/workflows/gh_pages_deploy.yaml new file mode 100644 index 0000000000000..e95fc986fb7f9 --- /dev/null +++ b/.github/workflows/gh_pages_deploy.yaml @@ -0,0 +1,76 @@ +# 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 + +name: GitHub Pages deploy + +on: + # Runs on pushes targeting the default branch. + push: + branches: ['trunk'] + + # Allows you to run this workflow manually from the Actions tab. + workflow_dispatch: + +# Cancel previous workflows on the PR when there are multiple fast commits. +# https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages. +permissions: + contents: read + pages: write + id-token: write + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Checkout + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + - name: Prebuild actions + run: ./website/prebuild.py + - name: Setup Pages + uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0 + - name: Setup Ruby + uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0 + with: + # Runs 'bundle install' and caches installed gems automatically. + bundler-cache: true + # Increment this number if you need to re-download cached gems. + cache-version: 0 + - name: Build with Jekyll + env: + JEKYLL_ENV: production + run: | + bundle exec jekyll build --verbose \ + --source ./ \ + --destination ./_site \ + --baseurl "${{ steps.pages.outputs.base_path }}" + - name: Upload artifact + # Automatically uploads an artifact from the './_site' directory by + # default. + uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 + + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Harden Runner + uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1 + with: + egress-policy: audit + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2a4024df40865..49e38661e95d2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -180,7 +180,7 @@ repos: Exceptions. See /LICENSE for license information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - --custom_format - - '\.(carbon|c|json|proto|ypp)(\.tmpl)?$' + - '\.(carbon|c|json|proto|scss|ypp)(\.tmpl)?$' - '' - '// ' - '' @@ -216,6 +216,8 @@ repos: compile_flags.txt| github_tools/requirements.txt| third_party/.*| + website/.ruby-version| + website/Gemfile.lock| .*\.def| .*\.svg| .*/fuzzer_corpus/.*| diff --git a/SECURITY.md b/SECURITY.md index 6b3e81c84d8ae..c3c8f5694bb3c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,11 +1,11 @@ +# Security policy + -# Security policy - It's important to us that the Carbon Language provides a secure implementation. Thank you for taking the time to report vulnerabilities. @@ -13,7 +13,7 @@ The Carbon Language is still an [experimental project](/README.md#project-status), so please be careful if using it in security-sensitive environments. -# Reporting a vulnerability +## Reporting a vulnerability Please use to diff --git a/docs/images/snippets.md b/docs/images/snippets.md index 2bfffeb00af27..eb6067c9edf3c 100644 --- a/docs/images/snippets.md +++ b/docs/images/snippets.md @@ -6,6 +6,11 @@ Exceptions. See /LICENSE for license information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --> + + ## Images Images are managed in @@ -138,3 +143,7 @@ auto main() -> int { return 0; } ``` + + diff --git a/explorer/README.md b/explorer/README.md index b711433a3fe0d..7e93519eccd64 100644 --- a/explorer/README.md +++ b/explorer/README.md @@ -6,6 +6,11 @@ Exceptions. See /LICENSE for license information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --> + + `explorer` is an implementation of Carbon whose primary purpose is to act as a clear specification of the language. As an extension of that goal, it can also be used as a platform for prototyping and validating changes to the language. @@ -334,3 +339,7 @@ information and provide visual separation for different sections. - - - - - Sub Heading - - - - - -------------------------------- ``` + + diff --git a/explorer/ast/README.md b/explorer/ast/README.md index 6089a9dd3a03b..d58233e4ccadf 100644 --- a/explorer/ast/README.md +++ b/explorer/ast/README.md @@ -1,3 +1,5 @@ +# Explorer AST + + +Testing-specific libraries. diff --git a/testing/file_test/README.md b/testing/file_test/README.md index 30e1393a545b5..8f5f208d922ab 100644 --- a/testing/file_test/README.md +++ b/testing/file_test/README.md @@ -6,6 +6,11 @@ Exceptions. See /LICENSE for license information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --> + + ## BUILD A typical BUILD target will look like: @@ -156,3 +161,7 @@ Supported comment markers are: Tips like this are added by autoupdate, for example providing commands to run the test directly. Tips have no impact on validation; the marker informs autoupdate that it can update or remove them as needed. + + diff --git a/website/.ruby-version b/website/.ruby-version new file mode 100644 index 0000000000000..eb39e5382f4f0 --- /dev/null +++ b/website/.ruby-version @@ -0,0 +1 @@ +3.3 diff --git a/website/404.md b/website/404.md new file mode 100644 index 0000000000000..007476d03d5ac --- /dev/null +++ b/website/404.md @@ -0,0 +1,12 @@ +--- +title: 404 +nav_exclude: true +--- + +# 404: File not found + + diff --git a/website/Gemfile b/website/Gemfile new file mode 100644 index 0000000000000..5acc1635f8a0d --- /dev/null +++ b/website/Gemfile @@ -0,0 +1,14 @@ +# 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 + +source 'https://rubygems.org' + +gem "jekyll", "4.3.3" +gem "just-the-docs", "0.8.2" + +group :jekyll_plugins do + gem "jekyll-default-layout", "0.1.5" + gem "jekyll-readme-index", "0.3.0" + gem "jekyll-relative-links", "0.7.0" +end diff --git a/website/Gemfile.lock b/website/Gemfile.lock new file mode 100644 index 0000000000000..ffdbdbdb5eaa6 --- /dev/null +++ b/website/Gemfile.lock @@ -0,0 +1,100 @@ +GEM + remote: https://rubygems.org/ + specs: + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + bigdecimal (3.1.8) + colorator (1.1.0) + concurrent-ruby (1.3.4) + em-websocket (0.5.3) + eventmachine (>= 0.12.9) + http_parser.rb (~> 0) + eventmachine (1.2.7) + ffi (1.17.0) + forwardable-extended (2.6.0) + google-protobuf (4.27.3-arm64-darwin) + bigdecimal + rake (>= 13) + google-protobuf (4.27.3-x86_64-linux) + bigdecimal + rake (>= 13) + http_parser.rb (0.8.0) + i18n (1.14.5) + concurrent-ruby (~> 1.0) + jekyll (4.3.3) + addressable (~> 2.4) + colorator (~> 1.0) + em-websocket (~> 0.5) + i18n (~> 1.0) + jekyll-sass-converter (>= 2.0, < 4.0) + jekyll-watch (~> 2.0) + kramdown (~> 2.3, >= 2.3.1) + kramdown-parser-gfm (~> 1.0) + liquid (~> 4.0) + mercenary (>= 0.3.6, < 0.5) + pathutil (~> 0.9) + rouge (>= 3.0, < 5.0) + safe_yaml (~> 1.0) + terminal-table (>= 1.8, < 4.0) + webrick (~> 1.7) + jekyll-default-layout (0.1.5) + jekyll (>= 3.0, < 5.0) + jekyll-include-cache (0.2.1) + jekyll (>= 3.7, < 5.0) + jekyll-readme-index (0.3.0) + jekyll (>= 3.0, < 5.0) + jekyll-relative-links (0.7.0) + jekyll (>= 3.3, < 5.0) + jekyll-sass-converter (3.0.0) + sass-embedded (~> 1.54) + jekyll-seo-tag (2.8.0) + jekyll (>= 3.8, < 5.0) + jekyll-watch (2.2.1) + listen (~> 3.0) + just-the-docs (0.8.2) + jekyll (>= 3.8.5) + jekyll-include-cache + jekyll-seo-tag (>= 2.0) + rake (>= 12.3.1) + kramdown (2.4.0) + rexml + kramdown-parser-gfm (1.1.0) + kramdown (~> 2.0) + liquid (4.0.4) + listen (3.9.0) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + mercenary (0.4.0) + pathutil (0.16.2) + forwardable-extended (~> 2.6) + public_suffix (6.0.1) + rake (13.2.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) + ffi (~> 1.0) + rexml (3.3.5) + strscan + rouge (4.3.0) + safe_yaml (1.0.5) + sass-embedded (1.77.8) + google-protobuf (~> 4.26) + rake (>= 13) + strscan (3.1.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + unicode-display_width (2.5.0) + webrick (1.8.1) + +PLATFORMS + arm64-darwin + x86_64-linux + +DEPENDENCIES + jekyll (= 4.3.3) + jekyll-default-layout (= 0.1.5) + jekyll-readme-index (= 0.3.0) + jekyll-relative-links (= 0.7.0) + just-the-docs (= 0.8.2) + +BUNDLED WITH + 2.5.17 diff --git a/website/README.md b/website/README.md new file mode 100644 index 0000000000000..a926be7471c29 --- /dev/null +++ b/website/README.md @@ -0,0 +1,59 @@ +# Documentation website + + + + + +## Table of contents + +- [Overview](#overview) +- [Build process](#build-process) +- [Development tips](#development-tips) +- [Domain configuration](#domain-configuration) + + + +## Overview + +Carbon's main website is the GitHub project page. Carbon remains too early and +experimental to have a full-fledged website. + +This directories contains infrastructure for building the convenience +documentation website, which should be at . + +## Build process + +Website generation is done by +[gh_pages_deploy.yaml](/.github/workflows/gh_pages_deploy.yaml). It runs +`prebuild.py`, which prepares files for website generation, then builds the +website using Jekyll, configured through `_config.yml`. + +## Development tips + +[rbenv](https://github.com/rbenv/rbenv) can be used to set up Ruby and `bundle`. + +To run a server, run `bundle exec jekyll serve`. See +[Jekyll docs](https://jekyllrb.com/docs/usage/) for more commands. + +To update the `Gemfile.lock` after `Gemfile` changes, run `bundle update`. + +## Domain configuration + +The +[custom domain](https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site) +is configured in three places: + +- GitHub organization + [verified domains](https://github.com/organizations/carbon-language/settings/pages) +- GitHub repository + [custom domain](https://github.com/carbon-language/carbon-lang/settings/pages) +- Google Cloud DNS + - This is visible with `dig docs.carbon-lang.dev` + +Note all of these require admin permissions to modify. For sharing test pages, a +GitHub user and repository can be used, pushing to `.github.io` (or +getting a custom DNS setup). diff --git a/website/_config.yml b/website/_config.yml new file mode 100644 index 0000000000000..5bdd916bc478a --- /dev/null +++ b/website/_config.yml @@ -0,0 +1,25 @@ +# 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 + +title: Carbon Language documentation +description: An experimental successor to C++ + +# https://just-the-docs.github.io/just-the-docs/ +theme: just-the-docs + +favicon_ico: '/favicon.png' + +aux_links: + Discord: https://discord.gg/ZjVdShJDAs + GitHub: https://github.com/carbon-language/carbon-lang + +mermaid: + # Version of mermaid library + # Pick an available version from https://cdn.jsdelivr.net/npm/mermaid/ + version: '10.9.1' + +# We add frontmatter to files, but still want README.md -> index.md. +readme_index: + remove_originals: true + with_frontmatter: true diff --git a/website/_includes/footer_custom.html b/website/_includes/footer_custom.html new file mode 100644 index 0000000000000..28c7cff04b56a --- /dev/null +++ b/website/_includes/footer_custom.html @@ -0,0 +1,33 @@ + + + + diff --git a/website/_includes/nav_footer_custom.html b/website/_includes/nav_footer_custom.html new file mode 100644 index 0000000000000..d5f55ab6e7f65 --- /dev/null +++ b/website/_includes/nav_footer_custom.html @@ -0,0 +1,12 @@ + + + diff --git a/website/_sass/custom/custom.scss b/website/_sass/custom/custom.scss new file mode 100644 index 0000000000000..6c4a6c3ee4256 --- /dev/null +++ b/website/_sass/custom/custom.scss @@ -0,0 +1,47 @@ +// 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 + +// This is modifying the builtin scss, particularly: +// https://github.com/just-the-docs/just-the-docs/blob/main/_sass/layout.scss + +.site-nav { + // The navbar will typically overflow, so keep a scrollbar so that the zippies + // don't move on open/close. + overflow-y: scroll; +} + +.side-bar { + @include mq(lg) { + // Allow left alignment instead of centering. + width: #{$nav-width}; + } + + & + .main { + @include mq(lg) { + // Allow left alignment instead of centering. + margin-left: #{$nav-width}; + } + } +} + +.site-footer { + color: #57606a; +} + +// Comments in code. +.highlight .c { + color: #57606a; +} + +// Misc syntax in code. +.highlight .nb, +.highlight .nt, +.highlight .nv { + color: #a36000; +} + +// Strings in code. +.highlight .s2 { + color: #3f7f3f; +} diff --git a/website/_sass/custom/setup.scss b/website/_sass/custom/setup.scss new file mode 100644 index 0000000000000..e829fcf2ab74e --- /dev/null +++ b/website/_sass/custom/setup.scss @@ -0,0 +1,14 @@ +// 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 + +// This is modifying the builtin scss, particularly: +// https://github.com/just-the-docs/just-the-docs/blob/main/_sass/color_schemes/light.scss +// https://github.com/just-the-docs/just-the-docs/blob/main/_sass/support/_variables.scss + +// Prefer wider content. +$nav-width: 20rem; +$content-width: 60rem; + +$code-background-color: #f6f8fa; +$body-text-color: #1f2328; diff --git a/website/favicon.png b/website/favicon.png new file mode 100644 index 0000000000000..6eb787ba056cf Binary files /dev/null and b/website/favicon.png differ diff --git a/website/implementation.md b/website/implementation.md new file mode 100644 index 0000000000000..edee1ab3c3221 --- /dev/null +++ b/website/implementation.md @@ -0,0 +1,9 @@ +# Implementation + + + +These documents cover components of Carbon's reference implementation. diff --git a/website/prebuild.py b/website/prebuild.py new file mode 100755 index 0000000000000..5e9c97aac0536 --- /dev/null +++ b/website/prebuild.py @@ -0,0 +1,198 @@ +#!/usr/bin/env python3 + +"""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 +from pathlib import Path +import re +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"\1", 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() + + 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 x != readme] + 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__).parent.parent) + + # bazel-execroot interferes with jekyll because it's a broken symlink. + Path("bazel-execroot").unlink() + + # 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)) + 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", next(nav_order), parent_title="Implementation") + label_subdir("explorer", next(nav_order), parent_title="Implementation") + label_subdir("testing", next(nav_order), parent_title="Implementation") + + +if __name__ == "__main__": + main()