Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ hide:
- toc
- feedback
template: home.html
title: C/C++ Linting
title: C/C++ Linter with clang-format and clang-tidy
description: clang-format and clang-tidy for C and C++ pull requests, pre-commit hooks and CI, with the LLVM version you pin.
---

Expand Down
15 changes: 15 additions & 0 deletions docs/overrides/404.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{% extends "main.html" %}

{#-
Gives the 404 page a title of its own. With Material's default it was titled
"cpp-linter" like a real page, so missing pages were hard to tell apart in
Google Analytics.
-#}

{% block htmltitle %}
<title>Page not found - {{ config.site_name }}</title>
{% endblock %}

{% block content %}
<h1>404 - Not found</h1>
{% endblock %}
96 changes: 96 additions & 0 deletions docs/overrides/main.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,112 @@
{% extends "base.html" %}

{#-
Visits from the maintainers are tagged so that the Internal Traffic data
filter in Google Analytics can drop them. Opening any page with ?internal=1
stores a flag in localStorage, ?internal=0 removes it, and while the flag is
there every event carries traffic_type=internal. The docs under
/cpp-linter-action/, /clang-tools-pip/, /cpp-linter-rs/ and /cpp-linter/ are
on the same origin and read the same flag. It runs before Material's own
snippet, so the setting is queued ahead of the first page_view.
-#}

{% block analytics %}
{% if config.extra.analytics %}
<script>
try {
var param = new URLSearchParams(location.search).get("internal");
if (param === "1") localStorage.setItem("cpp-linter-internal", "1");
if (param === "0") localStorage.removeItem("cpp-linter-internal");
if (localStorage.getItem("cpp-linter-internal") === "1") {
window.dataLayer = window.dataLayer || [];
(function () { dataLayer.push(arguments); })("set", { traffic_type: "internal" });
}
} catch (e) {
// localStorage is unavailable when storage is blocked; the visit is then not tagged.
}
</script>
{% endif %}
{{ super() }}
{% endblock %}

{#-
The site's fonts are self-hosted in docs/fonts and declared in shared.css:
Instrument Sans for text, JetBrains Mono for code and Bricolage Grotesque for
headings. theme.font is false in mkdocs.yml, so Material loads nothing itself.
Preloading the latin files for text and headings lets the browser fetch them
while it is still reading the stylesheets. The URLs must match the ones in
shared.css, and crossorigin is required for fonts even on the same origin.

The Open Graph and Twitter tags give links shared in chats and on social
sites a title, a description and the card in static/og-image.png. Pages with
no URL of their own, like the 404 page, leave og:url out.
-#}

{% block extrahead %}
{{ super() }}
<link rel="preload" href="{{ 'fonts/instrument-sans-latin.woff2' | url }}" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="{{ 'fonts/bricolage-grotesque-latin.woff2' | url }}" as="font" type="font/woff2" crossorigin>
{%- if page and page.meta and page.meta.title %}
{%- set og_title = page.meta.title %}
{%- elif page and page.title and not page.is_homepage %}
{%- set og_title = page.title | striptags %}
{%- else %}
{%- set og_title = config.site_name %}
{%- endif %}
{%- set og_description = (page.meta.description if page and page.meta and page.meta.description) or config.site_description %}
{%- set og_image = config.site_url ~ "static/og-image.png" %}
<meta property="og:type" content="website">
<meta property="og:site_name" content="{{ config.site_name }}">
<meta property="og:title" content="{{ og_title }}">
<meta property="og:description" content="{{ og_description }}">
{%- if page and page.canonical_url %}
<meta property="og:url" content="{{ page.canonical_url }}">
{%- endif %}
<meta property="og:image" content="{{ og_image }}">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="cpp-linter: clang-format and clang-tidy for C/C++ pull requests, pre-commit hooks and CI">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="{{ og_title }}">
<meta name="twitter:description" content="{{ og_description }}">
<meta name="twitter:image" content="{{ og_image }}">
{% endblock %}

{#-
Copying a code block is how a reader takes cpp-linter into a project, so each
copy is sent to Google Analytics as a copy_code event. snippet names the
section the block is in (the id of the nearest heading above it, or the
block's own id on the home page), and code_title is the file name shown above
the block, when it has one.
-#}

{% block scripts %}
{{ super() }}
{% if config.extra.analytics %}
<script>
document.addEventListener("click", function (event) {
var button = event.target.closest &&
event.target.closest('.md-code__button[data-md-type="copy"], .md-clipboard, .cl-copy');
if (!button) return;
var block = button.closest(".highlight, .cl-window");
var snippet = "";
if (button.classList.contains("cl-copy")) {
snippet = (button.getAttribute("data-clipboard-target") || "").replace(/^#/, "");
} else if (block) {
var headings = document.querySelectorAll("article h2[id], article h3[id]");
for (var i = 0; i < headings.length; i++) {
if (headings[i].compareDocumentPosition(block) & Node.DOCUMENT_POSITION_FOLLOWING) {
snippet = headings[i].id;
}
}
}
var title = block && block.querySelector(".filename, .cl-window__file");
window.dataLayer = window.dataLayer || [];
(function () { dataLayer.push(arguments); })("event", "copy_code", {
snippet: snippet || "(none)",
code_title: title ? title.textContent.trim() : "(none)"
});
});
</script>
{% endif %}
{% endblock %}
10 changes: 10 additions & 0 deletions docs/robots.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# The cpp-linter docs share this host: the organization site at the root and
# each project's docs under its own path. This file covers all of them.
User-agent: *
Allow: /

Sitemap: https://cpp-linter.github.io/sitemap.xml
Sitemap: https://cpp-linter.github.io/cpp-linter-action/sitemap.xml
Sitemap: https://cpp-linter.github.io/clang-tools-pip/sitemap.xml
Sitemap: https://cpp-linter.github.io/cpp-linter-rs/sitemap.xml
Sitemap: https://cpp-linter.github.io/cpp-linter/sitemap.xml
Binary file added docs/static/og-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 61 additions & 0 deletions hooks/redirects.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
"""Write redirect pages for old URLs that still get visits.
GitHub Pages cannot send real redirects, so each old path gets a small page
that forwards the browser with a meta refresh and tells search engines where
the content lives now. The paths are the ones Google Analytics recorded as
404s on this site: pages that moved into the sponsor page, short names for the
getting started guide, and doc pages of cpp-linter-action, cpp-linter and
cpp-linter-rs requested without their project prefix.
A key ending in .html is written as that file; any other key is a directory
and gets an index.html. Targets are relative to site_url.
"""

from __future__ import annotations

import html
from pathlib import Path

REDIRECTS = {
"docs/": "getting-started/",
"merch/": "sponsor/#t-shirt-perk",
"inputs-outputs/": "cpp-linter-action/inputs-outputs/",
"examples/": "cpp-linter-action/examples/",
"permissions/": "cpp-linter-action/permissions/",
"pr-review-caveats/": "cpp-linter-action/pr-review-caveats/",
"cli_args/": "cpp-linter/cli_args.html",
"cpp_linter_rs/": "cpp-linter-rs/",
"cpp_linter_rs/cli.html": "cpp-linter-rs/cli/",
}

PAGE = """<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Redirecting to {url}</title>
<meta name="robots" content="noindex">
<link rel="canonical" href="{url}">
<meta http-equiv="refresh" content="0; url={url}">
<script>location.replace({url_js})</script>
</head>
<body>
<p>This page has moved to <a href="{url}">{url}</a>.</p>
</body>
</html>
"""


def on_post_build(config, **kwargs) -> None:
site_dir = Path(config["site_dir"])
site_url = config["site_url"]
for source, target in REDIRECTS.items():
path = site_dir / source
if not source.endswith(".html"):
path = path / "index.html"
if path.exists():
raise ValueError(f"redirect from {source} would replace a built page")
url = site_url + target
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(
PAGE.format(url=html.escape(url), url_js=repr(url)), encoding="utf-8"
)
3 changes: 3 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ markdown_extensions:
- toc:
permalink: true

hooks:
- hooks/redirects.py

plugins:
- search
- tags
Expand Down
Loading