diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 07d0b0a..63e8619 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to SNode.C projects -Choose the owning repository from the [organization profile](https://github.com/SNodeC). Use that project's **Contribute** menu for its issue tracker, build instructions and engineering guidelines. Report the revision, platform, steps to reproduce and expected/actual behavior; remove credentials, private configuration and private conversation data from reports. +Choose the owning repository from the [organization profile](https://github.com/SNodeC#banner). Use that project's **Contribute** menu for its issue tracker, build instructions and engineering guidelines. Report the revision, platform, steps to reproduce and expected/actual behavior; remove credentials, private configuration and private conversation data from reports. Keep changes scoped to their owning project. Do not create, change or require licence files, move release tags, or change package/security infrastructure without explicit maintainer approval. For a private vulnerability report, follow [SECURITY.md](SECURITY.md), not a public issue. @@ -8,4 +8,4 @@ Keep changes scoped to their owning project. Do not create, change or require li Open control-repository pull requests in [SNodeC/.github](https://github.com/SNodeC/.github/pulls). Repository identity belongs in `catalog.yml`; build settings belong in the owning repository's manifest. The profile is generated from `catalog.yml` (rows) and `profile/template.md` (prose). Edit those two files, never `profile/README.md`. Optional `tier` selects product, learn, install or secondary; `title` and `purpose` are single-line product display text; boolean `student` adds an entry to Student projects. Product rows require title/purpose and product/app kind; learn titles are optional, and secondary products require `student: true`. -Run the generator and checks described in [README.md](README.md). Cite sources for identity changes; use `confirm: true` for summaries needing maintainer confirmation. The [scoped README frame](templates/readme-frame.md) applies only to the four repositories explicitly enrolled in that frame. +Run the generator and checks described in [README.md](README.md#banner). Cite sources for identity changes; use `confirm: true` for summaries needing maintainer confirmation. The [scoped README frame](templates/readme-frame.md) applies only to the four repositories explicitly enrolled in that frame. diff --git a/README.md b/README.md index eeddab8..2368afc 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,18 @@ + +
@@ -34,26 +39,26 @@ SNode.C builds event-driven networking in C++. At its centre is [SNode.C](https:
| Project | What it is for | Status |
| --- | --- | --- |
-| **[SNode.C](https://github.com/SNodeC/snode.c#project-overview)** | Write networked programs and your own protocols in C++: event-driven, with HTTP, WebSocket, SSE and MQTT
[Quick start](https://github.com/SNodeC/snode.c#quick-start) · [Install](https://github.com/SNodeC/snode.c#install) · [Releases](https://github.com/SNodeC/snode.c/releases) | [](https://github.com/SNodeC/snode.c/actions/workflows/build-and-test.yml) |
-| **[MQTTSuite](https://github.com/SNodeC/mqttsuite#project-overview)** | Run an MQTT broker, translate topics, bridge brokers and store messages
[Quick start](https://github.com/SNodeC/mqttsuite#quick-start) · [Install](https://github.com/SNodeC/mqttsuite#install) · [Releases](https://github.com/SNodeC/mqttsuite/releases) | [](https://github.com/SNodeC/mqttsuite/actions/workflows/build-and-test.yml) |
-| **[AISuite](https://github.com/SNodeC/AISuite#project-overview)** | Connect applications to coding agents: asynchronous C++ and TypeScript
[Quick start](https://github.com/SNodeC/AISuite#quick-start) · [Install](https://github.com/SNodeC/AISuite#install) | [](https://github.com/SNodeC/AISuite/actions/workflows/build-and-test.yml) |
-| **[Codex(W)UI](https://github.com/SNodeC/CodexUI#project-overview)** | Follow a coding agent's work in a native Qt or browser workspace
[Quick start](https://github.com/SNodeC/CodexUI#quick-start) · [Install](https://github.com/SNodeC/CodexUI#install) | [](https://github.com/SNodeC/CodexUI/actions/workflows/build-and-qualify.yml) |
+| **[SNode.C](https://github.com/SNodeC/snode.c#banner)** | Write networked programs and your own protocols in C++: event-driven, with HTTP, WebSocket, SSE and MQTT
[Quick start](https://github.com/SNodeC/snode.c#quick-start) · [Install](https://github.com/SNodeC/snode.c#install) · [Releases](https://github.com/SNodeC/snode.c/releases) | [](https://github.com/SNodeC/snode.c/actions/workflows/build-and-test.yml) |
+| **[MQTTSuite](https://github.com/SNodeC/mqttsuite#banner)** | Run an MQTT broker, translate topics, bridge brokers and store messages
[Quick start](https://github.com/SNodeC/mqttsuite#quick-start) · [Install](https://github.com/SNodeC/mqttsuite#install) · [Releases](https://github.com/SNodeC/mqttsuite/releases) | [](https://github.com/SNodeC/mqttsuite/actions/workflows/build-and-test.yml) |
+| **[AISuite](https://github.com/SNodeC/AISuite#banner)** | Connect applications to coding agents: asynchronous C++ and TypeScript
[Quick start](https://github.com/SNodeC/AISuite#quick-start) · [Install](https://github.com/SNodeC/AISuite#install) | [](https://github.com/SNodeC/AISuite/actions/workflows/build-and-test.yml) |
+| **[Codex(W)UI](https://github.com/SNodeC/CodexUI#banner)** | Follow a coding agent's work in a native Qt or browser workspace
[Quick start](https://github.com/SNodeC/CodexUI#quick-start) · [Install](https://github.com/SNodeC/CodexUI#install) | [](https://github.com/SNodeC/CodexUI/actions/workflows/build-and-qualify.yml) |
| **[SNode.C-idp](https://github.com/SNodeC/snode.c-idp)** | SNode.C Identity Provider: OAuth2 and OpenID Connect with TOTP multi-factor authentication | |
## Install
-SNode.C and MQTTSuite are available as signed packages from [Packages](https://github.com/SNodeC/Packages#readme). Pick the guide for your installed distribution; each covers quick and custom installation, manual repository setup and updates.
+SNode.C and MQTTSuite are available as signed packages from [Packages](https://github.com/SNodeC/Packages#banner). Pick the guide for your installed distribution; each covers quick and custom installation, manual repository setup and updates.
| Distribution | Install guide |
| --- | --- |
-| OpenWrt | [OpenWrt guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/openwrt.md#page-overview) |
-| Raspberry Pi OS | [Raspberry Pi OS guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/raspberry-pi-os.md#page-overview) |
-| Debian | [Debian guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/debian.md#page-overview) |
-| Ubuntu | [Ubuntu guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/ubuntu.md#page-overview) |
-| Rocky Linux | [Rocky Linux guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/rocky-linux.md#page-overview) |
-| Fedora | [Fedora guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/fedora.md#page-overview) |
+| OpenWrt | [OpenWrt guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/openwrt.md#banner) |
+| Raspberry Pi OS | [Raspberry Pi OS guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/raspberry-pi-os.md#banner) |
+| Debian | [Debian guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/debian.md#banner) |
+| Ubuntu | [Ubuntu guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/ubuntu.md#banner) |
+| Rocky Linux | [Rocky Linux guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/rocky-linux.md#banner) |
+| Fedora | [Fedora guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/fedora.md#banner) |
-Supported releases, architectures and current builds: [package status](https://github.com/SNodeC/Packages/blob/main/status/README.md#page-overview).
+Supported releases, architectures and current builds: [package status](https://github.com/SNodeC/Packages/blob/main/status/README.md#banner).
## Learn
@@ -112,8 +117,8 @@ Further example programs are listed under [More from SNode.C](#more-from-snodec)
| Project | Purpose |
| --- | --- |
-| [DistributionPackages](https://github.com/SNodeC/DistributionPackages) | Build recipes, release CI and signing for distribution packages |
-| [.github](https://github.com/SNodeC/.github) | Organization catalog, profile, brand tokens and reusable CI workflows |
+| [DistributionPackages](https://github.com/SNodeC/DistributionPackages#banner) | Build recipes, release CI and signing for distribution packages |
+| [.github](https://github.com/SNodeC/.github#banner) | Organization catalog, profile, brand tokens and reusable CI workflows |
@@ -150,5 +155,5 @@ Issues and pull requests are welcome in each project's repository. Read the [con
Copyright © Volker Christian and contributors. Each project states its own license.
-Maintainer: [Volker Christian](https://github.com/VolkerChristian). [Contributing](https://github.com/SNodeC/.github/blob/main/CONTRIBUTING.md) · [Security](https://github.com/SNodeC/.github/blob/main/SECURITY.md)
+Maintainer: [Volker Christian](https://github.com/VolkerChristian#banner). [Contributing](https://github.com/SNodeC/.github/blob/main/CONTRIBUTING.md) · [Security](https://github.com/SNodeC/.github/blob/main/SECURITY.md)
diff --git a/profile/github-metadata.json b/profile/github-metadata.json
index 1796a3a..afc19fb 100644
--- a/profile/github-metadata.json
+++ b/profile/github-metadata.json
@@ -1,11 +1,12 @@
{
".github": {
"default_branch": "main",
+ "readme_anchor": "banner",
"workflow": ".github/workflows/validate-organization.yml"
},
"AISuite": {
"default_branch": "master",
- "readme_anchor": "project-overview",
+ "readme_anchor": "banner",
"source_commit": "45bbc477546bca8055575c17cebbb16db7bb24be",
"workflow": ".github/workflows/build-and-test.yml"
},
@@ -21,12 +22,13 @@
},
"CodexUI": {
"default_branch": "master",
- "readme_anchor": "project-overview",
+ "readme_anchor": "banner",
"source_commit": "33a5357bee5978ecaa31a2b7dab55b858843e9f7",
"workflow": ".github/workflows/build-and-qualify.yml"
},
"DistributionPackages": {
"default_branch": "main",
+ "readme_anchor": "banner",
"source_commit": "f941021a88953cf962ac2b926e456cb25d2fda18",
"workflow": ".github/workflows/sign-and-publish-packages.yml"
},
@@ -61,6 +63,7 @@
},
"Packages": {
"default_branch": "main",
+ "readme_anchor": "banner",
"source_commit": "5db17156d81577f85705c114ccb4c73e635dfe75"
},
"SNode.C-Book-Companion": {
@@ -111,7 +114,7 @@
},
"mqttsuite": {
"default_branch": "master",
- "readme_anchor": "project-overview",
+ "readme_anchor": "banner",
"release": {
"prerelease": false,
"tag": "v1.0.2"
@@ -134,7 +137,7 @@
},
"snode.c": {
"default_branch": "master",
- "readme_anchor": "project-overview",
+ "readme_anchor": "banner",
"release": {
"prerelease": false,
"tag": "v2.0.0"
diff --git a/profile/media/nav/account-dark.svg b/profile/media/nav/account-dark.svg
new file mode 100644
index 0000000..3ae0841
--- /dev/null
+++ b/profile/media/nav/account-dark.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/account-icon-dark.svg b/profile/media/nav/account-icon-dark.svg
new file mode 100644
index 0000000..a86e189
--- /dev/null
+++ b/profile/media/nav/account-icon-dark.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/account-icon-light.svg b/profile/media/nav/account-icon-light.svg
new file mode 100644
index 0000000..87f6230
--- /dev/null
+++ b/profile/media/nav/account-icon-light.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/account-light.svg b/profile/media/nav/account-light.svg
new file mode 100644
index 0000000..e2e6ee1
--- /dev/null
+++ b/profile/media/nav/account-light.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/organization-dark.svg b/profile/media/nav/organization-dark.svg
new file mode 100644
index 0000000..c0d96ad
--- /dev/null
+++ b/profile/media/nav/organization-dark.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/organization-icon-dark.svg b/profile/media/nav/organization-icon-dark.svg
new file mode 100644
index 0000000..83b391c
--- /dev/null
+++ b/profile/media/nav/organization-icon-dark.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/organization-icon-light.svg b/profile/media/nav/organization-icon-light.svg
new file mode 100644
index 0000000..ba05659
--- /dev/null
+++ b/profile/media/nav/organization-icon-light.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/organization-light.svg b/profile/media/nav/organization-light.svg
new file mode 100644
index 0000000..3462c04
--- /dev/null
+++ b/profile/media/nav/organization-light.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/repository-dark.svg b/profile/media/nav/repository-dark.svg
new file mode 100644
index 0000000..b6a0d0d
--- /dev/null
+++ b/profile/media/nav/repository-dark.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/repository-icon-dark.svg b/profile/media/nav/repository-icon-dark.svg
new file mode 100644
index 0000000..a47adf8
--- /dev/null
+++ b/profile/media/nav/repository-icon-dark.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/repository-icon-light.svg b/profile/media/nav/repository-icon-light.svg
new file mode 100644
index 0000000..ba93b86
--- /dev/null
+++ b/profile/media/nav/repository-icon-light.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/media/nav/repository-light.svg b/profile/media/nav/repository-light.svg
new file mode 100644
index 0000000..f7d0586
--- /dev/null
+++ b/profile/media/nav/repository-light.svg
@@ -0,0 +1,22 @@
+
diff --git a/profile/template.md b/profile/template.md
index c9fca2f..0897c96 100644
--- a/profile/template.md
+++ b/profile/template.md
@@ -1,4 +1,5 @@
+
@@ -36,18 +41,18 @@ SNode.C builds event-driven networking in C++. At its centre is [SNode.C](https: ## Install -SNode.C and MQTTSuite are available as signed packages from [Packages](https://github.com/SNodeC/Packages#readme). Pick the guide for your installed distribution; each covers quick and custom installation, manual repository setup and updates. +SNode.C and MQTTSuite are available as signed packages from [Packages](https://github.com/SNodeC/Packages#banner). Pick the guide for your installed distribution; each covers quick and custom installation, manual repository setup and updates. | Distribution | Install guide | | --- | --- | -| OpenWrt | [OpenWrt guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/openwrt.md#page-overview) | -| Raspberry Pi OS | [Raspberry Pi OS guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/raspberry-pi-os.md#page-overview) | -| Debian | [Debian guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/debian.md#page-overview) | -| Ubuntu | [Ubuntu guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/ubuntu.md#page-overview) | -| Rocky Linux | [Rocky Linux guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/rocky-linux.md#page-overview) | -| Fedora | [Fedora guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/fedora.md#page-overview) | +| OpenWrt | [OpenWrt guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/openwrt.md#banner) | +| Raspberry Pi OS | [Raspberry Pi OS guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/raspberry-pi-os.md#banner) | +| Debian | [Debian guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/debian.md#banner) | +| Ubuntu | [Ubuntu guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/ubuntu.md#banner) | +| Rocky Linux | [Rocky Linux guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/rocky-linux.md#banner) | +| Fedora | [Fedora guide](https://github.com/SNodeC/Packages/blob/main/docs/installation/fedora.md#banner) | -Supported releases, architectures and current builds: [package status](https://github.com/SNodeC/Packages/blob/main/status/README.md#page-overview). +Supported releases, architectures and current builds: [package status](https://github.com/SNodeC/Packages/blob/main/status/README.md#banner). ## Learn @@ -66,5 +71,5 @@ Issues and pull requests are welcome in each project's repository. Read the [con Copyright © Volker Christian and contributors. Each project states its own license. -Maintainer: [Volker Christian](https://github.com/VolkerChristian). [Contributing](https://github.com/SNodeC/.github/blob/main/CONTRIBUTING.md) · [Security](https://github.com/SNodeC/.github/blob/main/SECURITY.md) +Maintainer: [Volker Christian](https://github.com/VolkerChristian#banner). [Contributing](https://github.com/SNodeC/.github/blob/main/CONTRIBUTING.md) · [Security](https://github.com/SNodeC/.github/blob/main/SECURITY.md) diff --git a/templates/readme-frame.md b/templates/readme-frame.md index dbfb3da..fa52ddb 100644 --- a/templates/readme-frame.md +++ b/templates/readme-frame.md @@ -63,11 +63,11 @@ Install with multiple routes begins with **Choose your route.**; omit that promp Configuration is an H2 overview in all four READMEs: endpoints, persisted settings and trust boundaries, then the authoritative runtime guide. Build guides own installation and verification; first-success procedures are never duplicated in those guides. Footer contribution links point to the repository's own Contributing section; shared organization defaults must not describe control-repository operations as product contribution instructions. -Supporting pages enrolled in `navigation/plan.yml` use the generated `page-header` block and `#page-overview` anchor. Section folders use `README.md`. The banner identifies the repository and section; its button row has ↑ parent on the left and Repository/Organization on the right. Organization comes first in the HTML because both right-side buttons use `align="right"`. All navigation buttons are 160 px wide; native phone wrapping is accepted. The Organization label stays Organization. Existing root banners stay unchanged, with a right-aligned Organization button underneath and the stable `#project-overview` anchor. Header and section-list blocks are owned exclusively by `python tools/snodec_sync page-headers`; do not hand-edit them. Asset notes and coding-agent instructions are linked documentation, not presentation pages. +Supporting pages enrolled in `navigation/plan.yml` use the generated `page-header` block and a stable `#banner` anchor immediately before the slim banner. Root and profile pages put the same anchor before their tall banner. Section folders use `README.md`. The banner row places ↑ parent on the left, then named repository, SNode.C organization and Volker Christian account buttons on the right, each with its corresponding Octicon. Right floats use reverse HTML order to retain that visible order. Hover titles and accessible image labels distinguish the SNode.C repository and organization. Identity buttons use 36×28 icons below 640 px; desktop widths accommodate the names. All page-level and Up links target the destination banner when it exists; intentional section, code, release, download and external-documentation links keep their targets. Existing overview anchors remain valid. Header and section-list blocks are owned exclusively by `python tools/snodec_sync page-headers`; do not hand-edit them. Asset notes and coding-agent instructions are linked documentation, not presentation pages. Docs indexes retain the common menu as route maps. Individual L2 guides use the generated page header for return navigation and only relevant local navigation, not another complete README menu or a self-linking Build button. Standard menu targets are available on preview branches; preserve meaningful existing anchors when they still name substantive sections. Do not fabricate compatibility or platform support from version numbers alone. -The generated Repository, Organization and ↑ parent buttons provide return navigation; do not add duplicate Back blocks. User guides and implementation/qualification records occupy separately labelled groups in docs indexes; historical records do not define current product behavior. +The generated repository, organization, account and ↑ parent buttons provide return navigation; do not add duplicate Back blocks. User guides and implementation/qualification records occupy separately labelled groups in docs indexes; historical records do not define current product behavior. ## Navigation and tables diff --git a/tests/test_navigation.py b/tests/test_navigation.py index 879f0ed..692e872 100644 --- a/tests/test_navigation.py +++ b/tests/test_navigation.py @@ -123,8 +123,9 @@ def test_all_generated_links_and_assets_resolve(self): before_root = (repo / 'README.md').read_text() page_headers(repo) self.assertNotIn('page-header', (repo / 'README.md').read_text()) - self.assertEqual(re.findall(r'href="[^"]+"', before_root), - re.findall(r'href="[^"]+"', (repo / 'README.md').read_text())) + strip_identity = lambda value: re.sub(r'.*?', '', value, flags=re.S) + self.assertEqual(re.findall(r'href="[^"]+"', strip_identity(before_root)), + re.findall(r'href="[^"]+"', strip_identity((repo / 'README.md').read_text()))) for page in config['pages']: if page.get('deleted'): continue @@ -137,7 +138,7 @@ def test_all_generated_links_and_assets_resolve(self): self.assertNotIn('')[1].split('
')[0]) for target in re.findall(r'(?:href|src|srcset)="([^"]+)"', header): if target.startswith('https:'): - self.assertEqual(target, 'https://github.com/SNodeC') + self.assertIn(target, ('https://github.com/SNodeC#banner', 'https://github.com/VolkerChristian#banner')) continue file, _, fragment = target.partition('#') destination = (repo / page['new']).parent / file @@ -153,7 +154,7 @@ def test_all_generated_links_and_assets_resolve(self): def test_project_registry_extension_inherits_generated_policy(self): text = render_header('Packages', 'status/third-project.md') - self.assertIn('href="README.md#page-overview"', text) + self.assertIn('href="README.md#banner"', text) self.assertIn('banner-package-status.svg', text) with self.assertRaises(ValueError): render_header('Packages', 'docs/unplanned.md') @@ -178,7 +179,7 @@ def test_menu_changes_and_protected_body(self): self.assertIn('```sh\necho unchanged\n```', p.read_text()) self.assertIn('id="historic-anchor"', p.read_text()) section = (repo / 'docs/installation/README.md').read_text() - self.assertIn('[Debian](debian.md#page-overview)', section) + self.assertIn('[Debian](debian.md#banner)', section) self.assertNotIn('install-snodec.md', section) def test_read_only_check_and_cli(self): @@ -224,7 +225,7 @@ def test_mobile_sources_intrinsic_sizes_and_shared_font_spec(self): from tools.snodec_sync.navigation import _header_button, FONT header = render_header('snode.c', 'docs/guides/README.md') self.assertLess(header.index('SNode.C organization'), header.index('SNode.C repository')) - self.assertEqual(header.count('(max-width: 640px) and (prefers-color-scheme: dark)'), 2) + self.assertEqual(header.count('(max-width: 640px) and (prefers-color-scheme: dark)'), 3) self.assertEqual(header.count('width="160" height="28"'), 1) for width in (36, 160): svg = ET.fromstring(_header_button('Repository', 'Repository', 'repo', '#075985', 'light', width)) @@ -247,5 +248,32 @@ def test_companion_root_organization_is_generated_without_page_enrollment(self): self.assertIn('Preserved reader text.', text) self.assertLess(text.index('snodec:begin organization'), text.index('# Companion')) self.assertTrue((repo / 'docs/media/nav/organization-light.svg').is_file()) - self.assertFalse((repo / 'docs/media/nav/repository-light.svg').exists()) + self.assertTrue((repo / 'docs/media/nav/repository-light.svg').exists()) + self.assertTrue((repo / 'docs/media/nav/account-light.svg').exists()) self.assertEqual(page_headers(repo, check=True), []) + + def test_banner_precedes_image_and_identity_destinations(self): + repo = self.fixture('snode.c') + page_headers(repo) + for path in ['README.md', 'docs/README.md', 'docs/guides/build-from-source.md']: + body = (repo / path).read_text() + self.assertEqual(body.count('id="banner"'), 1) + self.assertLess(body.index('id="banner"'), body.index('# ')) + if path != 'README.md': + self.assertLess(body.index('id="banner"'), body.index('' +
- _button('docs/media/nav', 'organization', 'SNode.C organization',
- 'https://github.com/SNodeC', True) +
- '
' + ''.join(buttons) + '
' + buttons + '
' +
+ _identity('docs/media/nav', config['display'], '#banner') +
+ '