Formatting Guide¶
This page provides guidelines on how to use the various markdown attributes and other MkDocs Material extensions we have enabled to enhance the documentation.
Page and Section Links¶
There are three types of links you can use:
- Section links - link to another section heading on the same page
- Document links - link to another document, or a section heading on another document
- External links - link to an external website
All internal links to other pages and sections should be relative to the docs directory. We have enabled a setting to ensure links are correctly copnverted to the correct html href, and enable permalinks for headings to support this.
Section Links¶
Links to sections on the same page should just use the permalink section heading name:
[Link to this section](#page-and-section-links)
Results in: Link to this section
Document Links¶
[Link to Contributing to Documentation Page](/contributing/1-contribute-docs.md)
Results in: Link to Contributing to Documentation Page
[Link to How to Contribute Section](/contributing/1-contribute-docs.md#how-to-contribute)
Results in: Link to How to Contribute Section
Note: when typing a link in VSCode, the intellisense dropdown will help you complete the link by following the path from the project directory. This creates links that start with "/docs" (for example "/docs/contributing/1-contribute-docs.md" ). These links will not work unless you manually detele the /docs prefix. Its a pain but we have raised a PR for VScode and mkDocs on this.
External Links¶
[Link to Google Search](https://www.google.com)
Results in: Link to Google Search
Search Links¶
We have added a link feature to directly invoke the mkDocs powerful search dialog. This is particularly useful when you wish to refer to imformation that may be spread over several places and possibly not yet written.
[Find out about PCA9685 servo controllers](?PCA9685)
Find out about PCA9685 servo controllers
Multi word searches are also accepted
[hidden turnouts](?hidden turnout)
Headings¶
Headings are simply defined by one or more leading #
, noting you can only have one top level heading on a page, which is the page title.
The top level heading defines how the page appears in menus, so for this page this is the top level heading:
# Standards and Formatting Guide
Further, this general section on "Headings" is a second level heading:
## Headings
Following are how to define the lower level headings with a demo of each.
Heading Level 3¶
### Heading Level 3
Heading Level 4¶
#### Heading Level 4
Heading Level 5¶
##### Heading Level 5
Glossary Terms and Linking¶
Glossary plugins seem to be either very complicated to implement, or don't yield the results we're looking for. Instead, we have opted for a simple DIY glossary to define the terms, and provide a search link to enable users to find where they have been used in the documentation.
To add a term to the glossary, use the search URL syntax and a second level heading:
## [Term](?term)
This is a new term being added to the glossary.
Code blocks¶
When including code blocks, be sure to include an appropriate language for syntax highlighting, and use triple backtick "`" characters to surround the code for highlighting.
For example:
```cpp
TURNOUTL(id, address, "description")
TURNOUT(id, shortAddress, subAddress, "description")
```
Will render as:
TURNOUTL(id, address, "description")
TURNOUT(id, shortAddress, subAddress, "description")
For EXRAIL and general configuration file code blocks (eg. config.h, myAutomation.h), "cpp" is as good as any, and for any others use an appropriate language specifier.
If appropriate, line numbers can also be displayed by appending linenums="X"
to the language, where "X" is the starting line number:
```cpp linenums="20"
TURNOUTL(id, address, "description")
TURNOUT(id, shortAddress, subAddress, "description")
```
Will render as:
20 21 22 |
|
This is a nonsense C++ code block generated by Gemini to demonstrate the full syntax highlighting:
#include <iostream> // Standard I/O library
#include <vector> // For dynamic arrays
#include <string> // For string manipulation
#include <map> // For key-value pairs
// A simple namespace to organize code
namespace MyLibrary {
const double PI_VALUE = 3.1415926535; // A global constant
/**
* @brief Represents a generic item with properties.
* This is a multi-line comment to test comment colors.
*/
class GenericItem {
private:
std::string itemName;
int itemId;
double itemPrice;
bool isAvailable;
public:
// Constructor with default values
GenericItem(const std::string& name = "Default Item", int id = 0, double price = 0.0, bool available = true)
: itemName(name), itemId(id), itemPrice(price), isAvailable(available) {}
// Member function to display item details
void displayDetails() const {
std::cout << "Item Name: " << itemName << std::endl;
std::cout << "Item ID: " << itemId << std::endl;
std::cout << "Price: $" << itemPrice << std::endl;
std::cout << "Available: " << (isAvailable ? "Yes" : "No") << std::endl;
}
// Getter for itemPrice
double getPrice() const {
return itemPrice;
}
// Setter for itemPrice (with a simple check)
void setPrice(double newPrice) {
if (newPrice >= 0.0) {
this->itemPrice = newPrice;
} else {
std::cerr << "Warning: Price cannot be negative." << std::endl;
}
}
}; // Don't forget the semicolon after class definition!
// Template function to find the maximum of two values
template <typename T>
T findMax(T a, T b) {
return (a > b) ? a : b; // Ternary operator test
}
} // end namespace MyLibrary
// Main function - entry point of the program
int main() {
using namespace MyLibrary; // Use MyLibrary namespace
// Create instances of GenericItem
GenericItem item1("Laptop", 101, 1200.50, true);
GenericItem* item2 = new GenericItem("Mouse", 202, 25.99, false); // Using 'new'
// Display details using a loop
std::vector<GenericItem> inventory;
inventory.push_back(item1);
inventory.push_back(*item2);
std::cout << "--- Inventory Details ---" << std::endl;
for (const auto& item : inventory) { // Range-based for loop
item.displayDetails();
std::cout << "-------------------------" << std::endl;
}
// Test the template function
int maxInt = findMax(10, 20);
double maxDouble = findMax(PI_VALUE, item2->getPrice()); // Accessing member via pointer
std::cout << "Maximum integer: " << maxInt << std::endl;
std::cout << "Maximum double: " << maxDouble << std::endl;
// Exception handling test
try {
if (item1.getPrice() < 1.0) {
throw "Price too low!"; // Throwing a string literal
}
item1.setPrice(1500.00); // Change price
} catch (const char* msg) { // Catching a C-style string
std::cerr << "Error: " << msg << std::endl;
}
// Clean up dynamic memory
delete item2; // Using 'delete'
item2 = nullptr; // Best practice to nullify pointer after delete
// Return 0 for successful execution (integer literal)
return 0;
}