diff --git a/docs/reference/variables-macros.md b/docs/reference/variables-macros.md new file mode 100644 index 000000000..205224ea3 --- /dev/null +++ b/docs/reference/variables-macros.md @@ -0,0 +1,332 @@ +--- +template: overrides/main.html +--- + +# Variables and Macros + +The power of the Markdown language comes from its simplicity and +visual clarity. Its downside is that it far more limited than HTML. +That is the reason why Markdown extensions have been developed, +such as [Footnotes](../Footnotes) or [Admonition](../Admonition) +(for notes and tips). + +Sometimes, however, one wishes to add more customization +to Markdown pages, to perform tasks that are +specific to the documentation project. +This is the purpose of **variables** and **macros**, provided +by the [macros plugin](https://github.com/fralau/mkdocs_macros_plugin). + +!!! Note "Example" + + ``` + The unit price of product A is {{ unit_price }} EUR. + The sale price of {{ no }} units is {{ price(no, unit_price) }} EUR. + ``` + + If you defined a variable `no`w with a value of 50, + a variable `unit_price` with a value of 10, + and a macro `price()` (which multiplies the two), this could translate into: + + ``` + The unit price of product A is 10.00 EUR, + and the sale price of 50 units is 500.00 EUR. + ``` + + +Those who have used **wikis** engines (user-editable websites) +in the past are probably already familiar with those notions. + +!!!Tip + You may also use this + plugin to add **buttons** or other advanced functionality + (e.g. pulling data from a database) that is ordinarily + not provided by Markdown or one of its extensions. + + + +## Configuration + +The [macros plugin](https://github.com/fralau/mkdocs_macros_plugin) +makes it easier for contributors of an MkDocs website to produce richer and more beautiful pages. It enriches pages with calls to variables and macros. + + +!!! Note + This plugin has been tested to work with the **Material** theme. + It is also compatible with most other themes. + + +See the [installations instructions](https://mkdocs-macros-plugin.readthedocs.io/en/latest/#installation) for the plugin. + + +In order to make it work with your MkDocs project, +declare it in the config file: + +```yaml +plugins: + - search + - macros +``` + + +!!!Tip + The recommended way to check that the plugin works properly is to add the following line in one of the pages of your site + (typically `index.md`): + + ``` + {{ macros_info() }} + ``` + + If the plugin is properly installed, this will display + a test page with lots of information, especially predefined + variables and macros. + + +## Usage + +### Variables + +**Variables** are names with an attached value +(Markdown, HTML, ...), which can be reused anywhere in the pages. +Changing the value of the variable, will +change the text displayed, in all markdown pages +where this variable is called; this is useful for consistency. + + + +#### Predefined Variables + +With the macros plugin, a large set of predefined variables +are available out of the box, e.g. : + +Example | Description +--- | --- +`{{ config.site_name }}` | main title of the website +`{{ environment.system }}`| name of the OS +`{{ page.title }}` | title of the page +`{{ git.short_commit}} ({{ git.date}}) by {{ git.author}}` | **git information** (if applicable) + + +!!! Tip "Discoverability" + To explore the possibilities, just insert the + following code into one of the Markdown pages: + + ``` + {{ macros_info() }} + ``` + +#### Defining Variables + +All variables defined under `extra` in your config file become +available: + +```yaml +extra: + price: 12.50 + company: + name: Acme + address: .... + website: www.acme.com +``` + +This becomes available as, e.g.: + +```html +The price of the product is {{ price }}. + +See [more information on the website]({{ company.website }}). + +See more information on the website. +``` + +### Macros + +**Macros** are Python functions that return a value (Markdown, HTML...) +which depends on something else. + +A macro may have arguments, +or depend on conditions that change every time MkDocs +is run again (e.g. time or version number, etc.). + +Writing a macro is very easy: it requires only basic knowledge of Python, +and clear idea of what string result (Markdown, HTML, ...) +you want to produce. + +!!! Note + In principle the result must be a string, + but it could be _any type or class_ + as long it is translatable into a string. + + +#### Location of the Macros' Code + +By default, your macros are defined in a `main.py` file, +which is located in website's project directory +(generally beside the `mkdocs.yml` file). +You may [change that location and name](https://mkdocs-macros-plugin.readthedocs.io/en/latest/python/#location-of-the-module). + +#### Example 1: Arithmetics + +Imagine you want to calculate the cost of a batch, with +the unit price and the no of items, plus a 10% shipping costs: + +``` +This will cost {{ total_price(4, 12.50)}} dollars. +``` + +Which will be translated into: + +``` +This will cost 55 dollars. +``` + +But if `unit_price` and `quantity` have been defined under `extra`: + +```yaml +extra: + quantity: 4 + unit_price: 12.50 +``` + +``` +This will cost {{ total_price(quantity, unit_price)}} dollars. +``` + +??? Tip "Module content" + The module will look as follows: + + ```python + """ + Basic example of a Mkdocs-macros module + """ + + import math + + def define_env(env): + """ + This is the hook for defining macros + """ + + @env.macro + def total_price(quantity, unit_price): + "Calculate the price plus shipping costs + price = quantity * unit_price + shipping_costs = price * 10% + return price + shipping_costs + ``` + +#### Guidelines + +1. All you need to define is a `define_env(env)` function. + +2. To declare a Python function as a macro, just precede it by the +`@env.macro` decorator. +It will appear in the documentation produced by `{{ macros_info() }}` + +3. You may define as many macros as needed under `define_env()`. + +4. Write a macro's docstring from the viewpoint of the users who will + use it (it will be displayed in the macro's description). + +#### Example 2: Creating a Button + +This function is alternative, more flexible way to generate a button +(see [Buttons](../buttons#adding-buttons)): + +In your markdown page: + +``` +{{ button('Try this', 'https://your.website.com/page') }} +``` + +Result: + + + +[Try this](https://your.website.com/page){: .md-button } + + +??? Tip "Module content" + + In your Python module: + + ```python + def define_env(env): + """ + This is the hook for defining macros + """ + # Optional: a special function for making relative urls point to root + fix_url = env.variables.fix_url + + @env.macro + def button(label, url): + "Add a button" + url = fix_url(url) + HTML = """%s""" + return HTML % (url, label) + ``` + + + + +## Advanced Usage: Jinja2 Constructs + +The macros plugin relies on the [Jinja2](https://jinja.palletsprojects.com/en/2.11.x/templates/) template engine. + +This makes the facilities of that template engine available +within a Markdown page. + + + +!!! Note + Not that this is distinct from the standard, low-level use of Jinja2 by + MkDocs to convert the Markdown pages into HTML. + In principle this will **not** interfere with it. + +### Conditions and Loops +Most of what is described in its documentation, +including constructs such as + +- [conditions](https://jinja.palletsprojects.com/en/2.11.x/templates/#if): + `{% if ... %}` +- [loops](https://jinja.palletsprojects.com/en/2.11.x/templates/#for): + `{% for ... %} ` + + +will work out of the box. + +!!! Tip + Instead of using Jinja2 constructs to generate pure HTML + as in the examples shown, + you could use them to generate Markdown, + or whichever mix of Markdown, HTML, CSS + or even Javascript that might be required for your needs. + +### Filters + +Jinja2's [built-in filters](https://jinja.palletsprojects.com/en/2.11.x/templates/#list-of-builtin-filters) are available e.g. : + +`{{ "HELLO WORLD" | lower }}` results in `hello world` + +You may [write your own filters in the Python module](https://mkdocs-macros-plugin.readthedocs.io/en/latest/python/#defining-macros-and-filters-as-well-as-variables), +using the `@env.filter` decorator. + +### Including External Files + +Quite aside from variables and macros, you may include external files +containing snippets (typically, Markdown files). + +You may use the include directive from jinja2, directly in your markdown code e.g.: + + ## Paragraph + {% include 'snippet.md' %} + +Including another markdown file will therefore execute the macros. + +By default, the relative path for included files starts from `docs`, +but [this can be changed](https://mkdocs-macros-plugin.readthedocs.io/en/latest/advanced/#changing-the-directory-of-the-includes). + +## More Information on the Macros Plugin + +* [Main documentation page](https://mkdocs-macros-plugin.readthedocs.io/en/latest/) +* [Including git information in a page](https://mkdocs-macros-plugin.readthedocs.io/en/latest/git_info/) +* [Writing macros and filters](https://mkdocs-macros-plugin.readthedocs.io/en/latest/python/) diff --git a/mkdocs.yml b/mkdocs.yml index 8245583eb..27026050e 100755 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -178,6 +178,7 @@ nav: - Lists: reference/lists.md - MathJax: reference/mathjax.md - Meta tags: reference/meta-tags.md + - Variables and macros: reference/variables-macros.md - Changelog: - Release notes: changelog.md - Upgrading: upgrading.md diff --git a/package-lock.json b/package-lock.json index c77e81cad..dfe499138 100644 --- a/package-lock.json +++ b/package-lock.json @@ -306,9 +306,9 @@ } }, "@primer/octicons": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-10.1.0.tgz", - "integrity": "sha512-oXfV0uIe7I4cb3vUzBPlPZGL5SQ3+joyyRcmk28aJiGFySl8brzL0MJC63RahiNEnIFrL3D5BRVgz5ZGGuHCOg==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/@primer/octicons/-/octicons-11.0.0.tgz", + "integrity": "sha512-aMM2n7dl4ToEqQH9ZWQ8M8alGCoGsRk2k5hT5h3KXd54YFKte1twhJDvyQjIjjxqggNh5NUfyuqTOv6MPCVSKQ==", "dev": true, "requires": { "object-assign": "^4.1.1" @@ -505,9 +505,9 @@ "dev": true }, "@types/node": { - "version": "14.6.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.4.tgz", - "integrity": "sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==", + "version": "14.10.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.10.1.tgz", + "integrity": "sha512-aYNbO+FZ/3KGeQCEkNhHFRIzBOUgc7QvcVNKXbfnhDkSfwUv91JsQQa10rDgKSTSLkXZ1UIyPe4FJJNVgw1xWQ==", "dev": true }, "@types/normalize-package-data": { @@ -529,9 +529,9 @@ "dev": true }, "@types/ramda": { - "version": "0.27.14", - "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.27.14.tgz", - "integrity": "sha512-vbw/VAtEJeSJ6Z61QT+epirlnBeJiJIO7ndK1BJ0fKswnfbiTNga/jBG6R3OnBaFYx+UJv6Iv7ZfWDFSsSzNqA==", + "version": "0.27.17", + "resolved": "https://registry.npmjs.org/@types/ramda/-/ramda-0.27.17.tgz", + "integrity": "sha512-AHVwr1YdFdxeabfC1g34ZuJ61dKOcfdXlG+sqGUweD+5VrD6A9emwmc2OZY+N8CdEKdwl29hwvtTMSJ6ZVVsiQ==", "dev": true, "requires": { "ts-toolbelt": "^6.3.3" @@ -2581,9 +2581,9 @@ } }, "css-loader": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.2.2.tgz", - "integrity": "sha512-omVGsTkZPVwVRpckeUnLshPp12KsmMSLqYxs12+RzM9jRR5Y+Idn/tBffjXRvOE+qW7if24cuceFJqYR5FmGBg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.3.0.tgz", + "integrity": "sha512-rdezjCjScIrsL8BSYszgT4s476IcNKt6yX69t0pHjJVnPUTDpn4WfIpDQTN3wCJvUvfsz/mFjuGOekf3PY3NUg==", "dev": true, "requires": { "camelcase": "^6.0.0", @@ -2596,14 +2596,20 @@ "postcss-modules-scope": "^2.2.0", "postcss-modules-values": "^3.0.0", "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", + "schema-utils": "^2.7.1", "semver": "^7.3.2" }, "dependencies": { + "@types/json-schema": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.6.tgz", + "integrity": "sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==", + "dev": true + }, "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -2612,6 +2618,12 @@ "uri-js": "^4.2.2" } }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true + }, "camelcase": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz", @@ -2656,14 +2668,14 @@ "dev": true }, "schema-utils": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz", - "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", "dev": true, "requires": { - "@types/json-schema": "^7.0.4", - "ajv": "^6.12.2", - "ajv-keywords": "^3.4.1" + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" } }, "semver": { @@ -6203,9 +6215,9 @@ "dev": true }, "mini-css-extract-plugin": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.0.tgz", - "integrity": "sha512-dVWGuWJlQw2lZxsxBI3hOsoxg1k3DruLR0foHQLSkQMfk+qLJbv9dUk8fjmjWQKN9ef2n54ehA2FjClAsQhrWQ==", + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.11.2.tgz", + "integrity": "sha512-h2LknfX4U1kScXxH8xE9LCOqT5B+068EAj36qicMb8l4dqdJoyHcmWmpd+ueyZfgu/POvIn+teoUnTtei2ikug==", "dev": true, "requires": { "loader-utils": "^1.1.0", @@ -9015,9 +9027,9 @@ "dev": true }, "stylelint": { - "version": "13.7.0", - "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.7.0.tgz", - "integrity": "sha512-1wStd4zVetnlHO98VjcHQbjSDmvcA39smkZQMct2cf+hom40H0xlQNdzzbswoG/jGBh61/Ue9m7Lu99PY51O6A==", + "version": "13.7.1", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-13.7.1.tgz", + "integrity": "sha512-qzqazcyRxrSRdmFuO0/SZOJ+LyCxYy0pwcvaOBBnl8/2VfHSMrtNIE+AnyJoyq6uKb+mt+hlgmVrvVi6G6XHfQ==", "dev": true, "requires": { "@stylelint/postcss-css-in-js": "^0.37.2", @@ -9071,9 +9083,9 @@ }, "dependencies": { "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -10380,9 +10392,9 @@ } }, "ts-toolbelt": { - "version": "6.13.39", - "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.13.39.tgz", - "integrity": "sha512-VD/rJ6+NGFA7AK2KWmGzLifrqA060M9o7+R2BxJtLBlwmfEaGdqGeyUPRDKhMZPMgpT/JMQ6+X+/ppaZNzuhvw==", + "version": "6.15.5", + "resolved": "https://registry.npmjs.org/ts-toolbelt/-/ts-toolbelt-6.15.5.tgz", + "integrity": "sha512-FZIXf1ksVyLcfr7M317jbB67XFJhOO1YqdTcuGaq9q5jLUoTikukZ+98TPjKiP2jC5CgmYdWWYs0s2nLSU0/1A==", "dev": true }, "tsconfig-paths": { diff --git a/package.json b/package.json index bf3be142a..e9b01a920 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "devDependencies": { "@fortawesome/fontawesome-free": "^5.14.0", "@mdi/svg": "^5.5.55", - "@primer/octicons": "^10.1.0", + "@primer/octicons": "^11.0.0", "@types/clipboard": "^2.0.1", "@types/copy-webpack-plugin": "^6.0.0", "@types/escape-html": "1.0.0", @@ -52,14 +52,14 @@ "@types/html-minifier": "^4.0.0", "@types/lunr": "^2.3.3", "@types/mini-css-extract-plugin": "^0.9.1", - "@types/node": "^14.6.4", - "@types/ramda": "^0.27.14", + "@types/node": "^14.10.1", + "@types/ramda": "^0.27.17", "@types/resize-observer-browser": "^0.1.3", "@types/webpack": "^4.41.22", "@types/webpack-assets-manifest": "^3.0.1", "autoprefixer": "9.8.6", "copy-webpack-plugin": "^6.1.0", - "css-loader": "^4.2.2", + "css-loader": "^4.3.0", "event-hooks-webpack-plugin": "^2.1.7", "expose-loader": "^1.0.0", "github-types": "^1.0.0", @@ -69,7 +69,7 @@ "imagemin-webpack-plugin": "^2.4.2", "material-design-color": "^2.3.2", "material-shadows": "^3.0.1", - "mini-css-extract-plugin": "^0.11.0", + "mini-css-extract-plugin": "^0.11.2", "postcss-inline-svg": "^4.1.0", "postcss-loader": "^3.0.0", "postcss-svgo": "^4.0.2", @@ -77,7 +77,7 @@ "rimraf": "^3.0.2", "sass": "^1.26.10", "sass-loader": "^10.0.2", - "stylelint": "^13.7.0", + "stylelint": "^13.7.1", "stylelint-config-rational-order": "^0.1.2", "stylelint-config-standard": "^20.0.0", "stylelint-order": "^4.1.0",