185 | {% endif %}
186 | ```
187 |
188 | #### base_url
189 |
190 | The `base_url` provides a relative path to the root of the MkDocs project. While
191 | this can be used directly by prepending it to a local relative URL, it is best
192 | to use the [url](#url) template filter, which is smarter about how it applies
193 | `base_url`.
194 |
195 | #### mkdocs_version
196 |
197 | Contains the current MkDocs version.
198 |
199 | #### build_date_utc
200 |
201 | A Python datetime object that represents the date and time the documentation
202 | was built in UTC. This is useful for showing how recently the documentation
203 | was updated.
204 |
205 | #### pages
206 |
207 | A list of [page](#page) objects including *all* pages in the project. The list
208 | is a flat list with all pages sorted alphanumerically by directory and file
209 | name. Note that index pages sort to the top within a directory. This list can
210 | contain pages not included in the global [navigation](#nav) and may not match
211 | the order of pages within that navigation.
212 |
213 | #### page
214 |
215 | In templates which are not rendered from a Markdown source file, the `page`
216 | variable is `None`. In templates which are rendered from a Markdown source file,
217 | the `page` variable contains a `page` object. The same `page` objects are used
218 | as `page` [navigation objects](#navigation-objects) in the global
219 | [navigation](#nav) and in the [pages](#pages) template variable.
220 |
221 | All `page` objects contain the following attributes:
222 |
223 | ##### page.title
224 |
225 | Contains the Title for the current page.
226 |
227 | ##### page.content
228 |
229 | The rendered Markdown as HTML, this is the contents of the documentation.
230 |
231 | ##### page.toc
232 |
233 | An iterable object representing the Table of contents for a page. Each item in
234 | the `toc` is an `AnchorLink` which contains the following attributes:
235 |
236 | * `AnchorLink.title`: The text of the item.
237 | * `AnchorLink.url`: The hash fragment of a URL pointing to the item.
238 | * `AnchorLink.level`: The zero-based level of the item.
239 | * `AnchorLink.children`: An iterable of any child items.
240 |
241 | The following example would display the top two levels of the Table of Contents
242 | for a page.
243 |
244 | ```django
245 |
253 | ```
254 |
255 | ##### page.meta
256 |
257 | A mapping of the metadata included at the top of the markdown page. In this
258 | example we define a `source` property above the page title.
259 |
260 | ```no-highlight
261 | source: generics.py
262 | mixins.py
263 |
264 | # Page title
265 |
266 | Content...
267 | ```
268 |
269 | A template can access this metadata for the page with the `meta.source`
270 | variable. This could then be used to link to source files related to the
271 | documentation page.
272 |
273 | ```django
274 | {% for filename in page.meta.source %}
275 |
276 | {{ filename }}
277 |
278 | {% endfor %}
279 | ```
280 |
281 | ##### page.url
282 |
283 | The URL of the page relative to the MkDocs `site_dir`. It is expected that this
284 | be used with the [url](#url) filter to ensure the URL is relative to the current
285 | page.
286 |
287 | ```django
288 | {{ page.title }}
289 | ```
290 |
291 | [base_url]: #base_url
292 |
293 | ##### page.abs_url
294 |
295 | The absolute URL of the page from the server root as determined by the value
296 | assigned to the [site_url] configuration setting. The value includes any
297 | subdirectory included in the `site_url`, but not the domain. [base_url] should
298 | not be used with this variable.
299 |
300 | For example, if `site_url: https://example.com/`, then the value of
301 | `page.abs_url` for the page `foo.md` would be `/foo/`. However, if
302 | `site_url: https://example.com/bar/`, then the value of `page.abs_url` for the
303 | page `foo.md` would be `/bar/foo/`.
304 |
305 | [site_url]: ./configuration.md#site_url
306 |
307 | ##### page.canonical_url
308 |
309 | The full, canonical URL to the current page as determined by the value assigned
310 | to the [site_url] configuration setting. The value includes the domain and any
311 | subdirectory included in the `site_url`. [base_url] should not be used with this
312 | variable.
313 |
314 | ##### page.edit_url
315 |
316 | The full URL to the source page in the source repository. Typically used to
317 | provide a link to edit the source page. [base_url] should not be used with this
318 | variable.
319 |
320 | ##### page.is_homepage
321 |
322 | Evaluates to `True` for the homepage of the site and `False` for all other
323 | pages. This can be used in conjunction with other attributes of the `page`
324 | object to alter the behavior. For example, to display a different title
325 | on the homepage:
326 |
327 | ```django
328 | {% if not page.is_homepage %}{{ page.title }} - {% endif %}{{ site_name }}
329 | ```
330 |
331 | ##### page.previous_page
332 |
333 | The page object for the previous page or `None`. The value will be `None` if the
334 | current page is the first item in the site navigation or if the current page is
335 | not included in the navigation at all. When the value is a page object, the
336 | usage is the same as for `page`.
337 |
338 | ##### page.next_page
339 |
340 | The page object for the next page or `None`. The value will be `None` if the
341 | current page is the last item in the site navigation or if the current page is
342 | not included in the navigation at all. When the value is a page object, the
343 | usage is the same as for `page`.
344 |
345 | ##### page.parent
346 |
347 | The immediate parent of the page in the [site navigation](#nav). `None` if the
348 | page is at the top level.
349 |
350 | ##### page.children
351 |
352 | Pages do not contain children and the attribute is always `None`.
353 |
354 | ##### page.active
355 |
356 | When `True`, indicates that this page is the currently viewed page. Defaults
357 | to `False`.
358 |
359 | ##### page.is_section
360 |
361 | Indicates that the navigation object is a "section" object. Always `False` for
362 | page objects.
363 |
364 | ##### page.is_page
365 |
366 | Indicates that the navigation object is a "page" object. Always `True` for
367 | page objects.
368 |
369 | ##### page.is_link
370 |
371 | Indicates that the navigation object is a "link" object. Always `False` for
372 | page objects.
373 |
374 | ### Navigation Objects
375 |
376 | Navigation objects contained in the [nav](#nav) template variable may be one of
377 | [section](#section) objects, [page](#page) objects, and [link](#link) objects.
378 | While section objects may contain nested navigation objects, pages and links do
379 | not.
380 |
381 | Page objects are the full page object as used for the current [page](#page) with
382 | all of the same attributes available. Section and Link objects contain a subset
383 | of those attributes as defined below:
384 |
385 | #### Section
386 |
387 | A `section` navigation object defines a named section in the navigation and
388 | contains a list of child navigation objects. Note that sections do not contain
389 | URLs and are not links of any kind. However, by default, MkDocs sorts index
390 | pages to the top and the first child might be used as the URL for a section if a
391 | theme choses to do so.
392 |
393 | The following attributes are available on `section` objects:
394 |
395 | ##### section.title
396 |
397 | The title of the section.
398 |
399 | ##### section.parent
400 |
401 | The immediate parent of the section or `None` if the section is at the top
402 | level.
403 |
404 | ##### section.children
405 |
406 | An iterable of all child navigation objects. Children may include nested
407 | sections, pages and links.
408 |
409 | ##### section.active
410 |
411 | When `True`, indicates that a child page of this section is the current page and
412 | can be used to highlight the section as the currently viewed section. Defaults
413 | to `False`.
414 |
415 | ##### section.is_section
416 |
417 | Indicates that the navigation object is a "section" object. Always `True` for
418 | section objects.
419 |
420 | ##### section.is_page
421 |
422 | Indicates that the navigation object is a "page" object. Always `False` for
423 | section objects.
424 |
425 | ##### section.is_link
426 |
427 | Indicates that the navigation object is a "link" object. Always `False` for
428 | section objects.
429 |
430 | #### Link
431 |
432 | A `link` navigation object contains a link which does not point to an internal
433 | MkDocs page. The following attributes are available on `link` objects:
434 |
435 | ##### link.title
436 |
437 | The title of the link. This would generally be used as the label of the link.
438 |
439 | ##### link.url
440 |
441 | The URL that the link points to. The URL should always be an absolute URLs and
442 | should not need to have `base_url` prepened.
443 |
444 | ##### link.parent
445 |
446 | The immediate parent of the link. `None` if the link is at the top level.
447 |
448 | ##### link.children
449 |
450 | Links do not contain children and the attribute is always `None`.
451 |
452 | ##### link.active
453 |
454 | External links cannot be "active" and the attribute is always `False`.
455 |
456 | ##### link.is_section
457 |
458 | Indicates that the navigation object is a "section" object. Always `False` for
459 | link objects.
460 |
461 | ##### link.is_page
462 |
463 | Indicates that the navigation object is a "page" object. Always `False` for
464 | link objects.
465 |
466 | ##### link.is_link
467 |
468 | Indicates that the navigation object is a "link" object. Always `True` for
469 | link objects.
470 |
471 | ### Extra Context
472 |
473 | Additional variables can be passed to the template with the
474 | [`extra`](/user-guide/configuration.md#extra) configuration option. This is a
475 | set of key value pairs that can make custom templates far more flexible.
476 |
477 | For example, this could be used to include the project version of all pages
478 | and a list of links related to the project. This can be achieved with the
479 | following `extra` configuration:
480 |
481 | ```yaml
482 | extra:
483 | version: 0.13.0
484 | links:
485 | - https://github.com/mkdocs
486 | - https://docs.readthedocs.org/en/latest/builds.html#mkdocs
487 | - https://www.mkdocs.org/
488 | ```
489 |
490 | And then displayed with this HTML in the custom theme.
491 |
492 | ```django
493 | {{ config.extra.version }}
494 |
495 | {% if config.extra.links %}
496 |
497 | {% for link in config.extra.links %}
498 |
{{ link }}
499 | {% endfor %}
500 |
501 | {% endif %}
502 | ```
503 |
504 | ## Template Filters
505 |
506 | In addition to Jinja's default filters, the following custom filters are
507 | available to use in MkDocs templates:
508 |
509 | ### url
510 |
511 | Normalizes a URL. Absolute URLs are passed through unaltered. If the URL is
512 | relative and the template context includes a page object, then the URL is
513 | returned relative to the page object. Otherwise, the URL is returned with
514 | [base_url](#base_url) prepended.
515 |
516 | ```django
517 | {{ page.title }}
518 | ```
519 |
520 | ### tojson
521 |
522 | Safety convert a Python object to a value in a JavaScript script.
523 |
524 | ```django
525 |
528 | ```
529 |
530 | ## Search and themes
531 |
532 | As of MkDocs version *0.17* client side search support has been added to MkDocs
533 | via the `search` plugin. A theme needs to provide a few things for the plugin to
534 | work with the theme.
535 |
536 | While the `search` plugin is activated by default, users can disable the plugin
537 | and themes should account for this. It is recommended that theme templates wrap
538 | search specific markup with a check for the plugin:
539 |
540 | ```django
541 | {% if 'search' in config['plugins'] %}
542 | search stuff here...
543 | {% endif %}
544 | ```
545 |
546 | At its most basic functionality, the search plugin will simply provide an index
547 | file which is no more than a JSON file containing the content of all pages.
548 | The theme would need to implement its own search functionality client-side.
549 | However, with a few settings and the necessary templates, the plugin can provide
550 | a complete functioning client-side search tool based on [lunr.js].
551 |
552 | The following HTML needs to be added to the theme so that the provided
553 | JavaScript is able to properly load the search scripts and make relative links
554 | to the search results from the current page.
555 |
556 | ```django
557 |
558 | ```
559 |
560 | With properly configured settings, the following HTML in a template will add a
561 | full search implementation to your theme.
562 |
563 | ```django
564 |
Search Results
565 |
566 |
569 |
570 |
571 | Sorry, page not found.
572 |
573 | ```
574 |
575 | The JavaScript in the plugin works by looking for the specific ID's used in the
576 | above HTML. The form input for the user to type the search query must be
577 | identified with `id="mkdocs-search-query"` and the div where the results will be
578 | placed must be identified with `id="mkdocs-search-results"`.
579 |
580 | The plugin supports the following options being set in the [theme's
581 | configuration file], `mkdocs_theme.yml`:
582 |
583 | ### include_search_page
584 |
585 | Determines whether the search plugin expects the theme to provide a dedicated
586 | search page via a template located at `search/search.html`.
587 |
588 | When `include_search_page` is set to `true`, the search template will be built
589 | and available at `search/search.html`. This method is used by the `readthedocs`
590 | theme.
591 |
592 | When `include_search_page` is set to `false` or not defined, it is expected that
593 | the theme provide some other mechanisms for displaying search results. For
594 | example, the `mkdocs` theme displays results on any page via a modal.
595 |
596 | ### search_index_only
597 |
598 | Determines whether the search plugin should only generate a search index or a
599 | complete search solution.
600 |
601 | When `search_index_only` is set to `false`, then the search plugin modifies the
602 | Jinja environment by adding its own `templates` directory (with a lower
603 | precedence than the theme) and adds its scripts to the `extra_javascript` config
604 | setting.
605 |
606 | When `search_index_only` is set to `true` or not defined, the search plugin
607 | makes no modifications to the Jinja environment. A complete solution using the
608 | provided index file is the responsibility of the theme.
609 |
610 | The search index is written to a JSON file at `search/search_index.json` in the
611 | [site_dir]. The JSON object contained within the file may contain up to three
612 | objects.
613 |
614 | ```json
615 | {
616 | config: {...},
617 | data: [...],
618 | index: {...}
619 | }
620 | ```
621 |
622 | If present, the `config` object contains the key/value pairs of config options
623 | defined for the plugin in the user's `mkdocs.yml` config file under
624 | `plugings.search`. The `config` object was new in MkDocs version *1.0*.
625 |
626 | The `data` object contains a list of document objects. Each document object is
627 | made up of a `location` (URL), a `title`, and `text` which can be used to create
628 | a search index and/or display search results.
629 |
630 | If present, the `index` object contains a pre-built index which offers
631 | performance improvements for larger sites. Note that the pre-built index is only
632 | created if the user explicitly enables the [prebuild_index] config option.
633 | Themes should expect the index to not be present, but can choose to use the
634 | index when it is available. The `index` object was new in MkDocs version *1.0*.
635 |
636 | [Jinja2 template]: http://jinja.pocoo.org/docs/dev/
637 | [built-in themes]: https://github.com/mkdocs/mkdocs/tree/master/mkdocs/themes
638 | [theme's configuration file]: #theme-configuration
639 | [lunr.js]: https://lunrjs.com/
640 | [site_dir]: configuration.md#site_dir
641 | [prebuild_index]: configuration.md#prebuild_index
642 |
643 | ## Packaging Themes
644 |
645 | MkDocs makes use of [Python packaging] to distribute themes. This comes with a
646 | few requirements.
647 |
648 | To see an example of a package containing one theme, see the [MkDocs Bootstrap
649 | theme] and to see a package that contains many themes, see the [MkDocs
650 | Bootswatch theme].
651 |
652 | !!! Note
653 |
654 | It is not strictly necessary to package a theme, as the entire theme
655 | can be contained in the `custom_dir`. If you have created a "one-off theme,"
656 | that should be sufficient. However, if you intend to distribute your theme
657 | for others to use, packaging the theme has some advantages. By packaging
658 | your theme, your users can more easily install it and they can then take
659 | advantage of the [custom_dir] to make tweaks to your theme to better suit
660 | their needs.
661 |
662 | [Python packaging]: https://packaging.python.org/en/latest/
663 | [MkDocs Bootstrap theme]: https://mkdocs.github.io/mkdocs-bootstrap/
664 | [MkDocs Bootswatch theme]: https://mkdocs.github.io/mkdocs-bootswatch/
665 |
666 | ### Package Layout
667 |
668 | The following layout is recommended for themes. Two files at the top level
669 | directory called `MANIFEST.in` and `setup.py` beside the theme directory which
670 | contains an empty `__init__.py` file, a theme configuration file
671 | (`mkdocs-theme.yml`), and your template and media files.
672 |
673 | ```no-highlight
674 | .
675 | |-- MANIFEST.in
676 | |-- theme_name
677 | | |-- __init__.py
678 | | |-- mkdocs-theme.yml
679 | | |-- main.html
680 | | |-- styles.css
681 | `-- setup.py
682 | ```
683 |
684 | The `MANIFEST.in` file should contain the following contents but with
685 | theme_name updated and any extra file extensions added to the include.
686 |
687 | ```no-highlight
688 | recursive-include theme_name *.ico *.js *.css *.png *.html *.eot *.svg *.ttf *.woff
689 | recursive-exclude * __pycache__
690 | recursive-exclude * *.py[co]
691 | ```
692 |
693 | The `setup.py` should include the following text with the modifications
694 | described below.
695 |
696 | ```python
697 | from setuptools import setup, find_packages
698 |
699 | VERSION = '0.0.1'
700 |
701 |
702 | setup(
703 | name="mkdocs-themename",
704 | version=VERSION,
705 | url='',
706 | license='',
707 | description='',
708 | author='',
709 | author_email='',
710 | packages=find_packages(),
711 | include_package_data=True,
712 | entry_points={
713 | 'mkdocs.themes': [
714 | 'themename = theme_name',
715 | ]
716 | },
717 | zip_safe=False
718 | )
719 | ```
720 |
721 | Fill in the URL, license, description, author and author email address.
722 |
723 | The name should follow the convention `mkdocs-themename` (like `mkdocs-
724 | bootstrap` and `mkdocs-bootswatch`), starting with MkDocs, using hyphens to
725 | separate words and including the name of your theme.
726 |
727 | Most of the rest of the file can be left unedited. The last section we need to
728 | change is the entry_points. This is how MkDocs finds the theme(s) you are
729 | including in the package. The name on the left is the one that users will use
730 | in their mkdocs.yml and the one on the right is the directory containing your
731 | theme files.
732 |
733 | The directory you created at the start of this section with the main.html file
734 | should contain all of the other theme files. The minimum requirement is that
735 | it includes a `main.html` for the theme. It **must** also include a
736 | `__init__.py` file which should be empty, this file tells Python that the
737 | directory is a package.
738 |
739 | ### Theme Configuration
740 |
741 | A packaged theme is required to include a configuration file named
742 | `mkdocs_theme.yml` which is placed in the root of your template files. The file
743 | should contain default configuration options for the theme. However, if the
744 | theme offers no configuration options, the file is still required and can be
745 | left blank.
746 |
747 | The theme author is free to define any arbitrary options deemed necessary and
748 | those options will be made available in the templates to control behavior.
749 | For example, a theme might want to make a sidebar optional and include the
750 | following in the `mkdocs_theme.yml` file:
751 |
752 | ```yaml
753 | show_sidebar: true
754 | ```
755 |
756 | Then in a template, that config option could be referenced:
757 |
758 | ```django
759 | {% if config.theme.show_sidebar %}
760 |
...
761 | {% endif %}
762 | ```
763 |
764 | And the user could override the default in their project's `mkdocs.yml` config
765 | file:
766 |
767 | ```yaml
768 | theme:
769 | name: themename
770 | show_sidebar: false
771 | ```
772 |
773 | In addition to arbitrary options defined by the theme, MkDocs defines a few
774 | special options which alters its behavior:
775 |
776 | !!! block ""
777 |
778 | #### static_templates
779 |
780 | This option mirrors the [theme] config option of the same name and allows
781 | some defaults to be set by the theme. Note that while the user can add
782 | templates to this list, the user cannot remove templates included in the
783 | theme's config.
784 |
785 | #### extends
786 |
787 | Defines a parent theme that this theme inherits from. The value should be
788 | the string name of the parent theme. Normal Jinja inheritance rules apply.
789 |
790 | Plugins may also define some options which allow the theme to inform a plugin
791 | about which set of plugin options it expects. See the documentation for any
792 | plugins you may wish to support in your theme.
793 |
794 | ### Distributing Themes
795 |
796 | With the above changes, your theme should now be ready to install. This can be
797 | done with pip, using `pip install .` if you are still in the same directory as
798 | the setup.py.
799 |
800 | Most Python packages, including MkDocs, are distributed on PyPI. To do this,
801 | you should run the following command.
802 |
803 | ```no-highlight
804 | python setup.py register
805 | ```
806 |
807 | If you don't have an account setup, you should be prompted to create one.
808 |
809 | For a much more detailed guide, see the official Python packaging
810 | documentation for [Packaging and Distributing Projects].
811 |
812 | [Packaging and Distributing Projects]: https://packaging.python.org/en/latest/distributing/
813 | [theme]: ./configuration.md#theme
814 |
--------------------------------------------------------------------------------
/docs/user-guide/deploying-your-docs.md:
--------------------------------------------------------------------------------
1 | # Deploying your docs
2 |
3 | A basic guide to deploying your docs to various hosting providers
4 |
5 | ---
6 |
7 | ## GitHub Pages
8 |
9 | If you host the source code for a project on [GitHub], you can easily use
10 | [GitHub Pages] to host the documentation for your project. There are two basic
11 | types of GitHub Pages sites: [Project Pages] sites, and [User and Organization
12 | Pages] sites. They are nearly identical but have some important differences,
13 | which require a different work flow when deploying.
14 |
15 | ### Project Pages
16 |
17 | Project Pages sites are simpler as the site files get deployed to a branch
18 | within the project repository (`gh-pages` by default). After you `checkout` the
19 | primary working branch (usually `master`) of the git repository where you
20 | maintain the source documentation for your project, run the following command:
21 |
22 | ```sh
23 | mkdocs gh-deploy
24 | ```
25 |
26 | That's it! Behind the scenes, MkDocs will build your docs and use the
27 | [ghp-import] tool to commit them to the `gh-pages` branch and push the
28 | `gh-pages` branch to GitHub.
29 |
30 | Use `mkdocs gh-deploy --help` to get a full list of options available for the
31 | `gh-deploy` command.
32 |
33 | Be aware that you will not be able to review the built site before it is pushed
34 | to GitHub. Therefore, you may want to verify any changes you make to the docs
35 | beforehand by using the `build` or `serve` commands and reviewing the built
36 | files locally.
37 |
38 | !!! warning
39 |
40 | You should never edit files in your pages repository by hand if you're using
41 | the `gh-deploy` command because you will lose your work the next time you
42 | run the command.
43 |
44 | ### Organization and User Pages
45 |
46 | User and Organization Pages sites are not tied to a specific project, and the
47 | site files are deployed to the `master` branch in a dedicated repository named
48 | with the GitHub account name. Therefore, you need working copies of two
49 | repositories on our local system. For example, consider the following file
50 | structure:
51 |
52 | ```no-highlight
53 | my-project/
54 | mkdocs.yml
55 | docs/
56 | orgname.github.io/
57 | ```
58 |
59 | After making and verifying updates to your project you need to change
60 | directories to the `orgname.github.io` repository and call the
61 | `mkdocs gh-deploy` command from there:
62 |
63 | ```sh
64 | cd ../orgname.github.io/
65 | mkdocs gh-deploy --config-file ../my-project/mkdocs.yml --remote-branch master
66 | ```
67 |
68 | Note that you need to explicitly point to the `mkdocs.yml` configuration file as
69 | it is no longer in the current working directory. You also need to inform the
70 | deploy script to commit to the `master` branch. You may override the default
71 | with the [remote_branch] configuration setting, but if you forget to change
72 | directories before running the deploy script, it will commit to the `master`
73 | branch of your project, which you probably don't want.
74 |
75 | Be aware that you will not be able to review the built site before it is pushed
76 | to GitHub. Therefore, you may want to verify any changes you make to the docs
77 | beforehand by using the `build` or `serve` commands and reviewing the built
78 | files locally.
79 |
80 | !!! warning
81 |
82 | You should never edit files in your pages repository by hand if you're using
83 | the `gh-deploy` command because you will lose your work the next time you
84 | run the command.
85 |
86 | ### Custom Domains
87 |
88 | GitHub Pages includes support for using a [Custom Domain] for your site. In
89 | addition to the steps documented by GitHub, you need to take one additional step
90 | so that MkDocs will work with your custom domain. You need to add a `CNAME` file
91 | to the root of your [docs_dir]. The file must contain a single bare domain or
92 | subdomain on a single line (see MkDocs' own [CNAME file] as an example). You may
93 | create the file manually, or use GitHub's web interface to set up the custom
94 | domain (under Settings / Custom Domain). If you use the web interface, GitHub
95 | will create the `CNAME` file for you and save it to the root of your "pages"
96 | branch. So that the file does not get removed the next time you deploy, you need
97 | to copy the file to your `docs_dir`. With the file properly included in your
98 | `docs_dir`, MkDocs will include the file in your built site and push it to your
99 | "pages" branch each time you run the `gh-deploy` command.
100 |
101 | If you are having problems getting a custom domain to work, see GitHub's
102 | documentation on [Troubleshooting custom domains].
103 |
104 | [GitHub]: https://github.com/
105 | [GitHub Pages]: https://pages.github.com/
106 | [Project Pages]: https://help.github.com/articles/user-organization-and-project-pages/#project-pages-sites
107 | [User and Organization Pages]: https://help.github.com/articles/user-organization-and-project-pages/#user-and-organization-pages-sites
108 | [ghp-import]: https://github.com/davisp/ghp-import
109 | [remote_branch]: ./configuration.md#remote_branch
110 | [Custom Domain]: https://help.github.com/articles/adding-or-removing-a-custom-domain-for-your-github-pages-site
111 | [docs_dir]: ./configuration.md#docs_dir
112 | [CNAME file]: https://github.com/mkdocs/mkdocs/blob/master/docs/CNAME
113 | [Troubleshooting custom domains]: https://help.github.com/articles/troubleshooting-custom-domains/
114 |
115 | ## Read the Docs
116 |
117 | [Read the Docs][rtd] offers free documentation hosting. You can import your docs
118 | using any major version control system, including Mercurial, Git, Subversion,
119 | and Bazaar. Read the Docs supports MkDocs out-of-the-box. Follow the
120 | [instructions] on their site to arrange the files in your repository properly,
121 | create an account and point it at your publicly hosted repository. If properly
122 | configured, your documentation will update each time you push commits to your
123 | public repository.
124 |
125 | !!! note
126 |
127 | To benefit from all of the [features] offered by Read the Docs, you will need
128 | to use the [Read the Docs theme][theme] which ships with MkDocs. The various
129 | themes which may be referenced in Read the Docs' documentation are Sphinx
130 | specific themes and will not work with MkDocs.
131 |
132 | [rtd]: https://readthedocs.org/
133 | [instructions]: https://read-the-docs.readthedocs.io/en/latest/getting_started.html#in-markdown
134 | [features]: http://read-the-docs.readthedocs.io/en/latest/features.html
135 | [theme]: ./styling-your-docs.md#readthedocs
136 |
137 | ## Other Providers
138 |
139 | Any hosting provider which can serve static files can be used to serve
140 | documentation generated by MkDocs. While it would be impossible to document how
141 | to upload the docs to every hosting provider out there, the following guidelines
142 | should provide some general assistance.
143 |
144 | When you build your site (using the `mkdocs build` command), all of the files
145 | are written to the directory assigned to the [site_dir] configuration option
146 | (defaults to `"site"`) in your `mkdocs.yaml` config file. Generally, you will
147 | simply need to copy the contents of that directory to the root directory of your
148 | hosting provider's server. Depending on your hosting provider's setup, you may
149 | need to use a graphical or command line [ftp], [ssh] or [scp] client to transfer
150 | the files.
151 |
152 | For example, a typical set of commands from the command line might look
153 | something like this:
154 |
155 | ```sh
156 | mkdocs build
157 | scp -r ./site user@host:/path/to/server/root
158 | ```
159 |
160 | Of course, you will need to replace `user` with the username you have with your
161 | hosting provider and `host` with the appropriate domain name. Additionally, you
162 | will need to adjust the `/path/to/server/root` to match the configuration of
163 | your hosts' file system.
164 |
165 | [ftp]: https://en.wikipedia.org/wiki/File_Transfer_Protocol
166 | [ssh]: https://en.wikipedia.org/wiki/Secure_Shell
167 | [scp]: https://en.wikipedia.org/wiki/Secure_copy
168 |
169 | See your host's documentation for specifics. You will likely want to search
170 | their documentation for "ftp" or "uploading site".
171 |
172 | ## 404 Pages
173 |
174 | When MkDocs builds the documentation it will include a 404.html file in the
175 | [build directory][site_dir]. This file will be automatically used when
176 | deploying to [GitHub](#github-pages) but only on a custom domain. Other web
177 | servers may be configured to use it but the feature won't always be available.
178 | See the documentation for your server of choice for more information.
179 |
180 | [site_dir]: ./configuration.md#site_dir
181 |
--------------------------------------------------------------------------------
/docs/user-guide/plugins.md:
--------------------------------------------------------------------------------
1 | # MkDocs Plugins
2 |
3 | A Guide to installing, using and creating MkDocs Plugins
4 |
5 | ---
6 |
7 | ## Installing Plugins
8 |
9 | Before a plugin can be used, it must be installed on the system. If you are
10 | using a plugin which comes with MkDocs, then it was installed when you installed
11 | MkDocs. However, to install third party plugins, you need to determine the
12 | appropriate package name and install it using `pip`:
13 |
14 | pip install mkdocs-foo-plugin
15 |
16 | Once a plugin has been successfully installed, it is ready to use. It just needs
17 | to be [enabled](#using-plugins) in the configuration file.
18 |
19 | ## Using Plugins
20 |
21 | The [`plugins`][config] configuration option should contain a list of plugins to
22 | use when building the site. Each "plugin" must be a string name assigned to the
23 | plugin (see the documentation for a given plugin to determine its "name"). A
24 | plugin listed here must already be [installed](#installing-plugins).
25 |
26 | ```yaml
27 | plugins:
28 | - search
29 | ```
30 |
31 | Some plugins may provide configuration options of their own. If you would like
32 | to set any configuration options, then you can nest a key/value mapping
33 | (`option_name: option value`) of any options that a given plugin supports. Note
34 | that a colon (`:`) must follow the plugin name and then on a new line the option
35 | name and value must be indented and separated by a colon. If you would like to
36 | define multiple options for a single plugin, each option must be defined on a
37 | separate line.
38 |
39 | ```yaml
40 | plugins:
41 | - search:
42 | lang: en
43 | foo: bar
44 | ```
45 |
46 | For information regarding the configuration options available for a given plugin,
47 | see that plugin's documentation.
48 |
49 | For a list of default plugins and how to override them, see the
50 | [configuration][config] documentation.
51 |
52 | ## Developing Plugins
53 |
54 | Like MkDocs, plugins must be written in Python. It is generally expected that
55 | each plugin would be distributed as a separate Python module, although it is
56 | possible to define multiple plugins in the same module. At a minimum, a MkDocs
57 | Plugin must consist of a [BasePlugin] subclass and an [entry point] which
58 | points to it.
59 |
60 | ### BasePlugin
61 |
62 | A subclass of `mkdocs.plugins.BasePlugin` should define the behavior of the plugin.
63 | The class generally consists of actions to perform on specific events in the build
64 | process as well as a configuration scheme for the plugin.
65 |
66 | All `BasePlugin` subclasses contain the following attributes:
67 |
68 | #### config_scheme
69 |
70 | : A tuple of configuration validation instances. Each item must consist of a
71 | two item tuple in which the first item is the string name of the
72 | configuration option and the second item is an instance of
73 | `mkdocs.config.config_options.BaseConfigOption` or any of its subclasses.
74 |
75 | For example, the following `config_scheme` defines three configuration options: `foo`, which accepts a string; `bar`, which accepts an integer; and `baz`, which accepts a boolean value.
76 |
77 | class MyPlugin(mkdocs.plugins.BasePlugin):
78 | config_scheme = (
79 | ('foo', mkdocs.config.config_options.Type(mkdocs.utils.string_types, default='a default value')),
80 | ('bar', mkdocs.config.config_options.Type(int, default=0)),
81 | ('baz', mkdocs.config.config_options.Type(bool, default=True))
82 | )
83 |
84 | When the user's configuration is loaded, the above scheme will be used to
85 | validate the configuration and fill in any defaults for settings not
86 | provided by the user. The validation classes may be any of the classes
87 | provided in `mkdocs.config.config_options` or a third party subclass defined
88 | in the plugin.
89 |
90 | Any settings provided by the user which fail validation or are not defined
91 | in the `config_scheme` will raise a `mkdocs.config.base.ValidationError`.
92 |
93 | #### config
94 |
95 | : A dictionary of configuration options for the plugin, which is populated by
96 | the `load_config` method after configuration validation has completed. Use
97 | this attribute to access options provided by the user.
98 |
99 | def on_pre_build(self, config):
100 | if self.config['bool_option']:
101 | # implement "bool_option" functionality here...
102 |
103 | All `BasePlugin` subclasses contain the following method(s):
104 |
105 | #### load_config(options)
106 |
107 | : Loads configuration from a dictionary of options. Returns a tuple of
108 | `(errors, warnings)`. This method is called by MkDocs during configuration
109 | validation and should not need to be called by the plugin.
110 |
111 | #### on_<event_name>()
112 |
113 | : Optional methods which define the behavior for specific [events]. The plugin
114 | should define its behavior within these methods. Replace `` with
115 | the actual name of the event. For example, the `pre_build` event would be
116 | defined in the `on_pre_build` method.
117 |
118 | Most events accept one positional argument and various keyword arguments. It
119 | is generally expected that the positional argument would be modified (or
120 | replaced) by the plugin and returned. If nothing is returned (the method
121 | returns `None`), then the original, unmodified object is used. The keyword
122 | arguments are simply provided to give context and/or supply data which may
123 | be used to determine how the positional argument should be modified. It is
124 | good practice to accept keyword arguments as `**kwargs`. In the event that
125 | additional keywords are provided to an event in a future version of MkDocs,
126 | there will be no need to alter your plugin.
127 |
128 | For example, the following event would add an additional static_template to
129 | the theme config:
130 |
131 | class MyPlugin(BasePlugin):
132 | def on_config(self, config, **kwargs):
133 | config['theme'].static_templates.add('my_template.html')
134 | return config
135 |
136 | ### Events
137 |
138 | There are three kinds of events: [Global Events], [Page Events] and
139 | [Template Events].
140 |
141 | #### Global Events
142 |
143 | Global events are called once per build at either the beginning or end of the
144 | build process. Any changes made in these events will have a global effect on the
145 | entire site.
146 |
147 | ##### on_serve
148 |
149 | : The `serve` event is only called when the `serve` command is used during
150 | development. It is passed the `Server` instance which can be modified before
151 | it is activated. For example, additional files or directories could be added
152 | to the list of "watched" files for auto-reloading.
153 |
154 | Parameters:
155 | : __server:__ `livereload.Server` instance
156 | : __config:__ global configuration object
157 |
158 | Returns:
159 | : `livereload.Server` instance
160 |
161 | ##### on_config
162 |
163 | : The `config` event is the first event called on build and is run immediately
164 | after the user configuration is loaded and validated. Any alterations to the
165 | config should be made here.
166 |
167 | Parameters:
168 | : __config:__ global configuration object
169 |
170 | Returns:
171 | : global configuration object
172 |
173 | ##### on_pre_build
174 |
175 | : The `pre_build` event does not alter any variables. Use this event to call
176 | pre-build scripts.
177 |
178 | Parameters:
179 | : __config:__ global configuration object
180 |
181 | ##### on_files
182 |
183 | : The `files` event is called after the files collection is populated from the
184 | `docs_dir`. Use this event to add, remove, or alter files in the
185 | collection. Note that Page objects have not yet been associated with the
186 | file objects in the collection. Use [Page Events] to manipulate page
187 | specific data.
188 |
189 | Parameters:
190 | : __files:__ global files collection
191 | : __config:__ global configuration object
192 |
193 | Returns:
194 | : global files collection
195 |
196 | ##### on_nav
197 |
198 | : The `nav` event is called after the site navigation is created and can
199 | be used to alter the site navigation.
200 |
201 | Parameters:
202 | : __nav:__ global navigation object
203 | : __config:__ global configuration object
204 | : __files:__ global files collection
205 |
206 | Returns:
207 | : global navigation object
208 |
209 | ##### on_env
210 |
211 | : The `env` event is called after the Jinja template environment is created
212 | and can be used to alter the Jinja environment.
213 |
214 | Parameters:
215 | : __env:__ global Jinja environment
216 | : __config:__ global configuration object
217 | : __site_navigation:__ global navigation object
218 |
219 | Returns:
220 | : global Jinja Environment
221 |
222 | ##### on_post_build
223 |
224 | : The `post_build` event does not alter any variables. Use this event to call
225 | post-build scripts.
226 |
227 | Parameters:
228 | : __config:__ global configuration object
229 |
230 | #### Template Events
231 |
232 | Template events are called once for each non-page template. Each template event
233 | will be called for each template defined in the [extra_templates] config setting
234 | as well as any [static_templates] defined in the theme. All template events are
235 | called after the [env] event and before any [page events].
236 |
237 | ##### on_pre_template
238 |
239 | : The `pre_template` event is called immediately after the subject template is
240 | loaded and can be used to alter the content of the template.
241 |
242 | Parameters:
243 | : __template__: the template contents as string
244 | : __template_name__: string filename of template
245 | : __config:__ global configuration object
246 |
247 | Returns:
248 | : template contents as string
249 |
250 | ##### on_template_context
251 |
252 | : The `template_context` event is called immediately after the context is created
253 | for the subject template and can be used to alter the context for that specific
254 | template only.
255 |
256 | Parameters:
257 | : __context__: dict of template context variables
258 | : __template_name__: string filename of template
259 | : __config:__ global configuration object
260 |
261 | Returns:
262 | : dict of template context variables
263 |
264 | ##### on_post_template
265 |
266 | : The `post_template` event is called after the template is rendered, but before
267 | it is written to disc and can be used to alter the output of the template.
268 | If an empty string is returned, the template is skipped and nothing is is
269 | written to disc.
270 |
271 | Parameters:
272 | : __output_content__: output of rendered template as string
273 | : __template_name__: string filename of template
274 | : __config:__ global configuration object
275 |
276 | Returns:
277 | : output of rendered template as string
278 |
279 | #### Page Events
280 |
281 | Page events are called once for each Markdown page included in the site. All
282 | page events are called after the [post_template] event and before the
283 | [post_build] event.
284 |
285 | ##### on_pre_page
286 |
287 | : The `pre_page` event is called before any actions are taken on the subject
288 | page and can be used to alter the `Page` instance.
289 |
290 | Parameters:
291 | : __page:__ `mkdocs.nav.Page` instance
292 | : __config:__ global configuration object
293 | : __site_navigation:__ global navigation object
294 |
295 | Returns:
296 | : `mkdocs.nav.Page` instance
297 |
298 | ##### on_page_read_source
299 |
300 | : The `on_page_read_source` event can replace the default mechanism to read
301 | the contents of a page's source from the filesystem.
302 |
303 | Parameters:
304 | : __page:__ `mkdocs.nav.Page` instance
305 | : __config:__ global configuration object
306 |
307 | Returns:
308 | : The raw source for a page as unicode string. If `None` is returned, the
309 | default loading from a file will be performed.
310 |
311 | ##### on_page_markdown
312 |
313 | : The `page_markdown` event is called after the page's markdown is loaded
314 | from file and can be used to alter the Markdown source text. The meta-
315 | data has been stripped off and is available as `page.meta` at this point.
316 |
317 | Parameters:
318 | : __markdown:__ Markdown source text of page as string
319 | : __page:__ `mkdocs.nav.Page` instance
320 | : __config:__ global configuration object
321 | : __site_navigation:__ global navigation object
322 |
323 | Returns:
324 | : Markdown source text of page as string
325 |
326 | ##### on_page_content
327 |
328 | : The `page_content` event is called after the Markdown text is rendered to
329 | HTML (but before being passed to a template) and can be used to alter the
330 | HTML body of the page.
331 |
332 | Parameters:
333 | : __html:__ HTML rendered from Markdown source as string
334 | : __page:__ `mkdocs.nav.Page` instance
335 | : __config:__ global configuration object
336 | : __site_navigation:__ global navigation object
337 |
338 | Returns:
339 | : HTML rendered from Markdown source as string
340 |
341 | ##### on_page_context
342 |
343 | : The `page_context` event is called after the context for a page is created
344 | and can be used to alter the context for that specific page only.
345 |
346 | Parameters:
347 | : __context__: dict of template context variables
348 | : __page:__ `mkdocs.nav.Page` instance
349 | : __config:__ global configuration object
350 | : __site_navigation:__ global navigation object
351 |
352 | Returns:
353 | : dict of template context variables
354 |
355 | ##### on_post_page
356 |
357 | : The `post_template` event is called after the template is rendered, but
358 | before it is written to disc and can be used to alter the output of the
359 | page. If an empty string is returned, the page is skipped and nothing is
360 | written to disc.
361 |
362 | Parameters:
363 | : __output_content:__ output of rendered template as string
364 | : __page:__ `mkdocs.nav.Page` instance
365 | : __config:__ global configuration object
366 | : __site_navigation:__ global navigation object
367 |
368 | Returns:
369 | : output of rendered template as string
370 |
371 | ### Entry Point
372 |
373 | Plugins need to be packaged as Python libraries (distributed on PyPI separate
374 | from MkDocs) and each must register as a Plugin via a setuptools entry_point.
375 | Add the following to your `setup.py` script:
376 |
377 | ```python
378 | entry_points={
379 | 'mkdocs.plugins': [
380 | 'pluginname = path.to.some_plugin:SomePluginClass',
381 | ]
382 | }
383 | ```
384 |
385 | The `pluginname` would be the name used by users (in the config file) and
386 | `path.to.some_plugin:SomePluginClass` would be the importable plugin itself
387 | (`from path.to.some_plugin import SomePluginClass`) where `SomePluginClass` is a
388 | subclass of [BasePlugin] which defines the plugin behavior. Naturally, multiple
389 | Plugin classes could exist in the same module. Simply define each as a separate
390 | entry_point.
391 |
392 | ```python
393 | entry_points={
394 | 'mkdocs.plugins': [
395 | 'featureA = path.to.my_plugins:PluginA',
396 | 'featureB = path.to.my_plugins:PluginB'
397 | ]
398 | }
399 | ```
400 |
401 | Note that registering a plugin does not activate it. The user still needs to
402 | tell MkDocs to use if via the config.
403 |
404 | [BasePlugin]:#baseplugin
405 | [config]: configuration.md#plugins
406 | [entry point]: #entry-point
407 | [env]: #on_env
408 | [events]: #events
409 | [extra_templates]: configuration.md#extra_templates
410 | [Global Events]: #global-events
411 | [Page Events]: #page-events
412 | [post_build]: #on_post_build
413 | [post_template]: #on_post_template
414 | [static_templates]: configuration.md#static_templates
415 | [Template Events]: #template-events
416 |
--------------------------------------------------------------------------------
/docs/user-guide/styling-your-docs.md:
--------------------------------------------------------------------------------
1 | # Styling your docs
2 |
3 | How to style and theme your documentation.
4 |
5 | ---
6 |
7 | MkDocs includes a couple [built-in themes] as well as various [third party
8 | themes], all of which can easily be customized with [extra CSS or
9 | JavaScript][docs_dir] or overridden from the theme's [custom_dir]. You can also
10 | create your own [custom theme] from the ground up for your documentation.
11 |
12 | To use a theme that is included in MkDocs, simply add this to your
13 | `mkdocs.yml` config file.
14 |
15 | theme: readthedocs
16 |
17 | Replace [`readthedocs`](#readthedocs) with any of the [built-in themes] listed below.
18 |
19 | To create a new custom theme see the [Custom Themes][custom theme] page, or to
20 | more heavily customize an existing theme, see
21 | the [Customizing a Theme][customize] section below.
22 |
23 | ## Built-in themes
24 |
25 | ### mkdocs
26 |
27 | The default theme, which was built as a custom [Bootstrap] theme, supports most
28 | every feature of MkDocs. It only officially supports two levels in the
29 | navigation (see #1107).
30 |
31 | 
32 |
33 | In addition to the default [theme configuration options], the `mkdocs` theme
34 | supports the following options:
35 |
36 | * __`highlightjs`__: Enables highlighting of source code in code blocks using
37 | the [highlight.js] JavaScript library. Default: `True`.
38 |
39 | * __`hljs_style`__: The highlight.js library provides 79 different [styles]
40 | (color variations) for highlighting source code in code blocks. Set this to
41 | the name of the desired style. Default: `github`.
42 |
43 | * __`hljs_languages`__: By default, highlight.js only supports 23 common
44 | languages. List additional languages here to include support for them.
45 |
46 | theme:
47 | name: mkdocs
48 | highlightjs: true
49 | hljs_languages:
50 | - yaml
51 | - rust
52 |
53 | * __`shortcuts`__: Defines keyboard shortcut keys.
54 |
55 | theme:
56 | name: mkdocs
57 | shortcuts:
58 | help: 191 # ?
59 | next: 78 # n
60 | previous: 80 # p
61 | search: 83 # s
62 |
63 | All values much be numeric key codes. It is best to use keys which are
64 | available on all keyboards. You may use to determine
65 | the key code for a given key.
66 |
67 | * __`help`__: Display a help modal which lists the keyboard shortcuts.
68 | Default: `191` (?)
69 |
70 | * __`next`__: Navigate to the "next" page. Default: `78` (n)
71 |
72 | * __`previous`__: Navigate to the "previous" page. Default: `80` (p)
73 |
74 | * __`search`__: Display the search modal. Default: `83` (s)
75 |
76 | [styles]: https://highlightjs.org/static/demo/
77 |
78 | ### readthedocs
79 |
80 | A clone of the default theme used by the [Read the Docs] service, which offers
81 | the same restricted feature-set as its parent theme. Like its parent theme, only
82 | two levels of navigation are supported.
83 |
84 | 
85 |
86 | In addition to the default [theme configuration options], the `readthedocs`
87 | theme supports the following options:
88 |
89 | * __`highlightjs`__: Enables highlighting of source code in code blocks using
90 | the [highlight.js] JavaScript library. Default: `True`.
91 |
92 | * __`hljs_languages`__: By default, highlight.js only supports 23 common
93 | languages. List additional languages here to include support for them.
94 |
95 | theme:
96 | name: readthedocs
97 | highlightjs: true
98 | hljs_languages:
99 | - yaml
100 | - rust
101 |
102 | ### Third Party Themes
103 |
104 | A list of third party themes can be found in the MkDocs [community wiki]. If you
105 | have created your own, please feel free to add it to the list.
106 |
107 | ## Customizing a Theme
108 |
109 | If you would like to make a few tweaks to an existing theme, there is no need to
110 | create your own theme from scratch. For minor tweaks which only require some CSS
111 | and/or JavaScript, you can use the [docs_dir]. However, for more complex
112 | customizations, including overriding templates, you will need to use the theme
113 | [custom_dir] setting.
114 |
115 | ### Using the docs_dir
116 |
117 | The [extra_css] and [extra_javascript] configuration options can be used to
118 | make tweaks and customizations to existing themes. To use these, you simply
119 | need to include either CSS or JavaScript files within your [documentation
120 | directory].
121 |
122 | For example, to change the colour of the headers in your documentation, create
123 | a file called `extra.css` and place it next to the documentation Markdown. In
124 | that file add the following CSS.
125 |
126 | ```CSS
127 | h1 {
128 | color: red;
129 | }
130 | ```
131 |
132 | !!! note
133 |
134 | If you are deploying your documentation with [ReadTheDocs]. You will need
135 | to explicitly list the CSS and JavaScript files you want to include in
136 | your config. To do this, add the following to your mkdocs.yml.
137 |
138 | extra_css: [extra.css]
139 |
140 | After making these changes, they should be visible when you run
141 | `mkdocs serve` - if you already had this running, you should see that the CSS
142 | changes were automatically picked up and the documentation will be updated.
143 |
144 | !!! note
145 |
146 | Any extra CSS or JavaScript files will be added to the generated HTML
147 | document after the page content. If you desire to include a JavaScript
148 | library, you may have better success including the library by using the
149 | theme [custom_dir].
150 |
151 | ### Using the theme custom_dir
152 |
153 | The theme.[custom_dir] configuration option can be used to point to a directory
154 | of files which override the files in a parent theme. The parent theme would be
155 | the theme defined in the theme.[name] configuration option. Any file in the
156 | `custom_dir` with the same name as a file in the parent theme will replace the
157 | file of the same name in the parent theme. Any additional files in the
158 | `custom_dir` will be added to the parent theme. The contents of the `custom_dir`
159 | should mirror the directory structure of the parent theme. You may include
160 | templates, JavaScript files, CSS files, images, fonts, or any other media
161 | included in a theme.
162 |
163 | !!! Note
164 |
165 | For this to work, the theme `name` setting must be set to a known installed theme.
166 | If the `name` setting is instead set to `null` (or not defined), then there
167 | is no theme to override and the contents of the `custom_dir` must be a
168 | complete, standalone theme. See [Custom Themes][custom theme] for more
169 | information.
170 |
171 | For example, the [mkdocs] theme ([browse source]), contains the following
172 | directory structure (in part):
173 |
174 | ```nohighlight
175 | - css\
176 | - fonts\
177 | - img\
178 | - favicon.ico
179 | - grid.png
180 | - js\
181 | - 404.html
182 | - base.html
183 | - content.html
184 | - nav-sub.html
185 | - nav.html
186 | - toc.html
187 | ```
188 |
189 | To override any of the files contained in that theme, create a new directory
190 | next to your `docs_dir`:
191 |
192 | ```bash
193 | mkdir custom_theme
194 | ```
195 |
196 | And then point your `mkdocs.yml` configuration file at the new directory:
197 |
198 | ```yaml
199 | theme:
200 | name: mkdocs
201 | custom_dir: custom_theme/
202 | ```
203 |
204 | To override the 404 error page ("file not found"), add a new template file named
205 | `404.html` to the `custom_theme` directory. For information on what can be
206 | included in a template, review the documentation for building a [custom theme].
207 |
208 | To override the favicon, you can add a new icon file at
209 | `custom_theme/img/favicon.ico`.
210 |
211 | To include a JavaScript library, copy the library to the `custom_theme/js/`
212 | directory.
213 |
214 | Your directory structure should now look like this:
215 |
216 | ```nohighlight
217 | - docs/
218 | - index.html
219 | - custom_theme/
220 | - img/
221 | - favicon.ico
222 | - js/
223 | - somelib.js
224 | - 404.html
225 | - config.yml
226 | ```
227 |
228 | !!! Note
229 |
230 | Any files included in the parent theme (defined in `name`) but not included
231 | in the `custom_dir` will still be utilized. The `custom_dir` will only
232 | override/replace files in the parent theme. If you want to remove files, or
233 | build a theme from scratch, then you should review the documentation for
234 | building a [custom theme].
235 |
236 | #### Overriding Template Blocks
237 |
238 | The built-in themes implement many of their parts inside template blocks which
239 | can be individually overridden in the `main.html` template. Simply create a
240 | `main.html` template file in your `custom_dir` and define replacement blocks
241 | within that file. Just make sure that the `main.html` extends `base.html`. For
242 | example, to alter the title of the MkDocs theme, your replacement `main.html`
243 | template would contain the following:
244 |
245 | ```django
246 | {% extends "base.html" %}
247 |
248 | {% block title %}
249 | Custom title goes here
250 | {% endblock %}
251 | ```
252 |
253 | In the above example, the title block defined in your custom `main.html` file
254 | will be used in place of the default title block defined in the parent theme.
255 | You may re-define as many blocks as you desire, as long as those blocks are
256 | defined in the parent. For example, you could replace the Google Analytics
257 | script with one for a different service or replace the search feature with your
258 | own. You will need to consult the parent theme you are using to determine what
259 | blocks are available to override. The MkDocs and ReadTheDocs themes provide the
260 | following blocks:
261 |
262 | * `site_meta`: Contains meta tags in the document head.
263 | * `htmltitle`: Contains the page title in the document head.
264 | * `styles`: Contains the link tags for stylesheets.
265 | * `libs`: Contains the JavaScript libraries (jQuery, etc) included in the page header.
266 | * `scripts`: Contains JavaScript scripts which should execute after a page loads.
267 | * `analytics`: Contains the analytics script.
268 | * `extrahead`: An empty block in the `` to insert custom tags/scripts/etc.
269 | * `site_name`: Contains the site name in the navigation bar.
270 | * `site_nav`: Contains the site navigation in the navigation bar.
271 | * `search_box`: Contains the search box in the navigation bar.
272 | * `next_prev`: Contains the next and previous buttons in the navigation bar.
273 | * `repo`: Contains the repository link in the navigation bar.
274 | * `content`: Contains the page content and table of contents for the page.
275 | * `footer`: Contains the page footer.
276 |
277 | You may need to view the source template files to ensure your modifications will
278 | work with the structure of the site. See [Template Variables] for a list of
279 | variables you can use within your custom blocks. For a more complete
280 | explanation of blocks, consult the [Jinja documentation].
281 |
282 | #### Combining the custom_dir and Template Blocks
283 |
284 | Adding a JavaScript library to the `custom_dir` will make it available, but
285 | won't include it in the pages generated by MkDocs. Therefore, a link needs to
286 | be added to the library from the HTML.
287 |
288 | Starting the with directory structure above (truncated):
289 |
290 | ```nohighlight
291 | - docs/
292 | - custom_theme/
293 | - js/
294 | - somelib.js
295 | - config.yml
296 | ```
297 |
298 | A link to the `custom_theme/js/somelib.js` file needs to be added to the
299 | template. As `somelib.js` is a JavaScript library, it would logically go in the
300 | `libs` block. However, a new `libs` block that only includes the new script will
301 | replace the block defined in the parent template and any links to libraries in
302 | the parent template will be removed. To avoid breaking the template, a
303 | [super block] can be used with a call to `super` from within the block:
304 |
305 | ```django
306 | {% extends "base.html" %}
307 |
308 | {% block libs %}
309 | {{ super() }}
310 |
311 | {% endblock %}
312 | ```
313 |
314 | Note that the [base_url] template variable was used to ensure that the link is
315 | always relative to the current page.
316 |
317 | Now the generated pages will include links to the template provided libraries as
318 | well as the library included in the `custom_dir`. The same would be required for
319 | any additional CSS files included in the `custom_dir`.
320 |
321 | [browse source]: https://github.com/mkdocs/mkdocs/tree/master/mkdocs/themes/mkdocs
322 | [built-in themes]: #built-in-themes
323 | [Bootstrap]: https://getbootstrap.com/
324 | [theme configuration options]: ./configuration.md#theme
325 | [Read the Docs]: https://readthedocs.org/
326 | [community wiki]: https://github.com/mkdocs/mkdocs/wiki/MkDocs-Themes
327 | [custom theme]: ./custom-themes.md
328 | [customize]: #customizing-a-theme
329 | [docs_dir]: #using-the-docs_dir
330 | [documentation directory]: ./configuration.md#docs_dir
331 | [extra_css]: ./configuration.md#extra_css
332 | [extra_javascript]: ./configuration.md#extra_javascript
333 | [Jinja documentation]: http://jinja.pocoo.org/docs/dev/templates/#template-inheritance
334 | [mkdocs]: #mkdocs
335 | [ReadTheDocs]: ./deploying-your-docs.md#readthedocs
336 | [Template Variables]: ./custom-themes.md#template-variables
337 | [custom_dir]: ./configuration.md#custom_dir
338 | [name]: ./configuration.md#name
339 | [third party themes]: #third-party-themes
340 | [super block]: http://jinja.pocoo.org/docs/dev/templates/#super-blocks
341 | [base_url]: ./custom-themes.md#base_url
342 | [highlight.js]: https://highlightjs.org/
343 |
--------------------------------------------------------------------------------
/docs/user-guide/writing-your-docs.md:
--------------------------------------------------------------------------------
1 | # Writing your docs
2 |
3 | How to layout and write your Markdown source files.
4 |
5 | ---
6 |
7 | ## File layout
8 |
9 | Your documentation source should be written as regular Markdown files (see
10 | [Writing with Markdown](#writing-with-markdown) below), and placed in the
11 | [documentation directory](configuration.md#docs_dir). By default, this directory
12 | will be named `docs` and will exist at the top level of your project, alongside
13 | the `mkdocs.yml` configuration file.
14 |
15 | The simplest project you can create will look something like this:
16 |
17 | ```no-highlight
18 | mkdocs.yml
19 | docs/
20 | index.md
21 | ```
22 |
23 | By convention your project homepage should always be named `index`. Any of the
24 | following extensions may be used for your Markdown source files: `markdown`,
25 | `mdown`, `mkdn`, `mkd`, `md`. All Markdown files included in your documentation
26 | directory will be rendered in the built site regardless of any settings.
27 |
28 | You can also create multi-page documentation, by creating several Markdown
29 | files:
30 |
31 | ```no-highlight
32 | mkdocs.yml
33 | docs/
34 | index.md
35 | about.md
36 | license.md
37 | ```
38 |
39 | The file layout you use determines the URLs that are used for the generated
40 | pages. Given the above layout, pages would be generated for the following URLs:
41 |
42 | ```no-highlight
43 | /
44 | /about/
45 | /license/
46 | ```
47 |
48 | You can also include your Markdown files in nested directories if that better
49 | suits your documentation layout.
50 |
51 | ```no-highlight
52 | docs/
53 | index.md
54 | user-guide/getting-started.md
55 | user-guide/configuration-options.md
56 | license.md
57 | ```
58 |
59 | Source files inside nested directories will cause pages to be generated with
60 | nested URLs, like so:
61 |
62 | ```no-highlight
63 | /
64 | /user-guide/getting-started/
65 | /user-guide/configuration-options/
66 | /license/
67 | ```
68 |
69 | ### Index pages
70 |
71 | When a directory is requested, by default, most web servers will return an index
72 | file (usually named `index.html`) contained within that directory if one exists.
73 | For that reason, the homepage in all of the examples above has been named
74 | `index.md`, which MkDocs will render to `index.html` when building the site.
75 |
76 | Many repository hosting sites provide special treatment for README files by
77 | displaying the contents of the README file when browsing the contents of a
78 | directory. Therefore, MkDocs will allow you to name your index pages as
79 | `README.md` instead of `index.md`. In that way, when users are browsing your
80 | source code, the repository host can display the index page of that directory as
81 | it is a README file. However, when MkDocs renders your site, the file will be
82 | renamed to `index.html` so that the server will serve it as a proper index file.
83 |
84 | You should not include both an `index.md` file and a `README.md` file in the
85 | same directory. It is suggested that you chose a convention for your project and
86 | then stick to it.
87 |
88 | ### Configure Pages and Navigation
89 |
90 | The [nav](configuration.md#nav) configuration setting in your `mkdocs.yml` file
91 | defines which pages are included in the global site navigation menu as well as
92 | the structure of that menu. If not provided, the navigation will be
93 | automatically created by discovering all the Markdown files in the
94 | [documentation directory](configuration.md#docs_dir). An automatically created
95 | navigation configuration will always be sorted alphanumerically by file name
96 | (except that index files will always be listed first within a sub-section). You
97 | will need to manually define your navigation configuration if you would like
98 | your navigation menu sorted differently.
99 |
100 | A simple navigation configuration looks like this:
101 |
102 | ```no-highlight
103 | nav:
104 | - 'index.md'
105 | - 'about.md'
106 | ```
107 |
108 | All paths in the navigation configuration must be relative to the `docs_dir`
109 | configuration option. If that option is set to the default value, `docs`, the
110 | source files for the above configuration would be located at `docs/index.md` and
111 | `docs/about.md`.
112 |
113 | The above example will result in two navigation items being created at the top
114 | level and with their titles inferred from the contents of the file (or the
115 | filename if no title is defined within the file). To define a custom title for
116 | the pages, the title can be added before the filename.
117 |
118 | ```no-highlight
119 | nav:
120 | - Home: 'index.md'
121 | - About: 'about.md'
122 | ```
123 |
124 | Note that if a title is defined for a page in the navigation, that title will be
125 | used throughout the site for that page and will override any title defined
126 | within the page itself.
127 |
128 | Navigation sub-sections can be created by listing related pages together under a
129 | section title. For example:
130 |
131 | ```no-highlight
132 | nav:
133 | - Home: 'index.md'
134 | - User Guide:
135 | - 'Writing your docs': 'writing-your-docs.md'
136 | - 'Styling your docs': 'styling-your-docs.md'
137 | - About:
138 | - 'License': 'license.md'
139 | - 'Release Notes': 'release-notes.md'
140 | ```
141 |
142 | With the above configuration we have three top level items: "Home", "User Guide"
143 | and "About." "Home" is a link to the homepage for the site. Under the "User
144 | Guide" section two pages are listed: "Writing your docs" and "Styling your
145 | docs." Under the "About" section two more pages are listed: "License" and
146 | "Release Notes."
147 |
148 | Note that a section cannot have a page assigned to it. Sections are only
149 | containers for child pages and sub-sections. You may nest sections as deeply as
150 | you like. However, be careful that you don't make it too difficult for your
151 | users to navigate through the site navigation by over-complicating the nesting.
152 | While sections may mirror your directly structure, they do not have to.
153 |
154 | Any pages not listed in your navigation configuration will still be rendered and
155 | included with the built site, however, they will not be linked from the global
156 | navigation and will not be included in the `previous` and `next` links. Such
157 | pages will be "hidden" unless linked to directly.
158 |
159 | ## Writing with Markdown
160 |
161 | MkDocs pages must be authored in [Markdown][md], a lightweight markup language
162 | which results in easy-to-read, easy-to-write plain text documents that can be
163 | converted to valid HTML documents in a predictable manner.
164 |
165 | MkDocs uses the [Python-Markdown] library to render Markdown documents to HTML.
166 | Python-Markdown is almost completely compliant with the [reference
167 | implementation][md], although there are a few very minor [differences].
168 |
169 | In addition to the base Markdown [syntax] which is common across all Markdown
170 | implementations, MkDocs includes support for extending the Markdown syntax with
171 | Python-Markdown [extensions]. See the MkDocs' [markdown_extensions]
172 | configuration setting for details on how to enable extensions.
173 |
174 | MkDocs includes some extensions by default, which are highlighted below.
175 |
176 | [Python-Markdown]: https://python-markdown.github.io/
177 | [md]: https://daringfireball.net/projects/markdown/
178 | [differences]: https://python-markdown.github.io/#differences
179 | [syntax]: https://daringfireball.net/projects/markdown/syntax
180 | [extensions]: https://python-markdown.github.io/extensions/
181 | [markdown_extensions]: configuration.md#markdown_extensions
182 |
183 | ### Internal links
184 |
185 | MkDocs allows you to interlink your documentation by using regular Markdown
186 | [links]. However, there are a few additional benefits to formatting those links
187 | specifically for MkDocs as outlined below.
188 |
189 | [links]: https://daringfireball.net/projects/markdown/syntax#link
190 |
191 | #### Linking to pages
192 |
193 | When linking between pages in the documentation you can simply use the regular
194 | Markdown [linking][links] syntax, including the *relative path* to the Markdown
195 | document you wish to link to.
196 |
197 | ```no-highlight
198 | Please see the [project license](license.md) for further details.
199 | ```
200 |
201 | When the MkDocs build runs, these Markdown links will automatically be
202 | transformed into an HTML hyperlink to the appropriate HTML page.
203 |
204 | If the target documentation file is in another directory you'll need to make
205 | sure to include any relative directory path in the link.
206 |
207 | ```no-highlight
208 | Please see the [project license](../about/license.md) for further details.
209 | ```
210 |
211 | The [toc] extension is used by MkDocs to generate an ID for every header in your
212 | Markdown documents. You can use that ID to link to a section within a target
213 | document by using an anchor link. The generated HTML will correctly transform
214 | the path portion of the link, and leave the anchor portion intact.
215 |
216 | ```no-highlight
217 | Please see the [project license](about.md#license) for further details.
218 | ```
219 |
220 | Note that IDs are created from the text of a header. All text is converted to
221 | lowercase and any disallowed characters, including white-space, are converted to
222 | dashes. Consecutive dashes are then reduced to a single dash.
223 |
224 | There are a few configuration settings provided by the toc extension which you
225 | can set in your `mkdocs.yml` configuration file to alter the default behavior:
226 |
227 | `permalink`:
228 |
229 | : Generate permanent links at the end of each header. Default: `False`.
230 |
231 | When set to True the paragraph symbol (¶ or `¶`) is used as the
232 | link text. When set to a string, the provided string is used as the link
233 | text. For example, to use the hash symbol (`#`) instead, do:
234 |
235 | markdown_extensions:
236 | - toc:
237 | permalink: "#"
238 |
239 | `baselevel`:
240 |
241 | : Base level for headers. Default: `1`.
242 |
243 | This setting allows the header levels to be automatically adjusted to fit
244 | within the hierarchy of your HTML templates. For example, if the Markdown
245 | text for a page should not contain any headers higher than level 2 (`
`),
246 | do:
247 |
248 | markdown_extensions:
249 | - toc:
250 | baselevel: 2
251 |
252 | Then any headers in your document would be increased by 1. For example, the
253 | header `# Header` would be rendered as a level 2 header (`
`) in the HTML
254 | output.
255 |
256 | `separator`:
257 |
258 | : Word separator. Default: `-`.
259 |
260 | Character which replaces white-space in generated IDs. If you prefer
261 | underscores, then do:
262 |
263 | markdown_extensions:
264 | - toc:
265 | separator: "_"
266 |
267 | Note that if you would like to define multiple of the above settings, you must
268 | do so under a single `toc` entry in the `markdown_extensions` configuration
269 | option.
270 |
271 | ```yml
272 | markdown_extensions:
273 | - toc:
274 | permalink: "#"
275 | baselevel: 2
276 | separator: "_"
277 | ```
278 |
279 | [toc]: https://python-markdown.github.io/extensions/toc/
280 |
281 | #### Linking to images and media
282 |
283 | As well as the Markdown source files, you can also include other file types in
284 | your documentation, which will be copied across when generating your
285 | documentation site. These might include images and other media.
286 |
287 | For example, if your project documentation needed to include a [GitHub pages
288 | CNAME file] and a PNG formatted screenshot image then your file layout might
289 | look as follows:
290 |
291 | ```no-highlight
292 | mkdocs.yml
293 | docs/
294 | CNAME
295 | index.md
296 | about.md
297 | license.md
298 | img/
299 | screenshot.png
300 | ```
301 |
302 | To include images in your documentation source files, simply use any of the
303 | regular Markdown image syntaxes:
304 |
305 | ```Markdown
306 | Cupcake indexer is a snazzy new project for indexing small cakes.
307 |
308 | 
309 |
310 | *Above: Cupcake indexer in progress*
311 | ```
312 |
313 | Your image will now be embedded when you build the documentation, and should
314 | also be previewed if you're working on the documentation with a Markdown editor.
315 |
316 | [GitHub pages CNAME file]: https://help.github.com/articles/using-a-custom-domain-with-github-pages/
317 |
318 | #### Linking from raw HTML
319 |
320 | Markdown allows document authors to fall back to raw HTML when the Markdown
321 | syntax does not meets the author's needs. MkDocs does not limit Markdown in this
322 | regard. However, as all raw HTML is ignored by the Markdown parser, MkDocs is
323 | not able to validate or convert links contained in raw HTML. When including
324 | internal links within raw HTML, you will need to manually format the link
325 | appropriately for the rendered document.
326 |
327 | ### Meta-Data
328 |
329 | MkDocs includes support for both YAML and MultiMarkdown style meta-data (often
330 | called front-matter). Meta-data consists of a series of keywords and values
331 | defined at the beginning of a Markdown document, which are stripped from the
332 | document prior to it being processing by Python-Markdown. The key/value pairs
333 | are passed by MkDocs to the page template. Therefore, if a theme includes
334 | support, the values of any keys can be displayed on the page or used to control
335 | the page rendering. See your theme's documentation for information about which
336 | keys may be supported, if any.
337 |
338 | In addition to displaying information in a template, MkDocs includes support for
339 | a few predefined meta-data keys which can alter the behavior of MkDocs for that
340 | specific page. The following keys are supported:
341 |
342 | `template`:
343 |
344 | : The template to use with the current page.
345 |
346 | By default, MkDocs uses the `main.html` template of a theme to render
347 | Markdown pages. You can use the `template` meta-data key to define a
348 | different template file for that specific page. The template file must be
349 | available on the path(s) defined in the theme's environment.
350 |
351 | `title`:
352 |
353 | : The "title" to use for the document.
354 |
355 | MkDocs will attempt to determine the title of a document in the following
356 | ways, in order:
357 |
358 | 1. A title defined in the [nav] configuration setting for a document.
359 | 2. A title defined in the `title` meta-data key of a document.
360 | 3. A level 1 Markdown header on the first line of the document body.
361 | 4. The filename of a document.
362 |
363 | Upon finding a title for a page, MkDoc does not continue checking any
364 | additional sources in the above list.
365 |
366 | #### YAML Style Meta-Data
367 |
368 | YAML style meta-data consists of [YAML] key/value pairs wrapped in YAML style
369 | deliminators to mark the start and/or end of the meta-data. The first line of
370 | a document must be `---`. The meta-data ends at the first line containing an
371 | end deliminator (either `---` or `...`). The content between the deliminators is
372 | parsed as [YAML].
373 |
374 | ```no-highlight
375 | ---
376 | title: My Document
377 | summary: A brief description of my document.
378 | authors:
379 | - Waylan Limberg
380 | - Tom Christie
381 | date: 2018-07-10
382 | some_url: https://example.com
383 | ---
384 | This is the first paragraph of the document.
385 | ```
386 |
387 | YAML is able to detect data types. Therefore, in the above example, the values
388 | of `title`, `summary` and `some_url` are strings, the value of `authors` is a
389 | list of strings and the value of `date` is a `datetime.date` object. Note that
390 | the YAML keys are case sensitive and MkDocs expects keys to be all lowercase.
391 | The top level of the YAML must be a collection of key/value pairs, which results
392 | in a Python `dict` being returned. If any other type is returned or the YAML
393 | parser encounters an error, then MkDocs does not recognize the section as
394 | meta-data, the page's `meta` attribute will be empty, and the section is not
395 | removed from the document.
396 |
397 | #### MultiMarkdown Style Meta-Data
398 |
399 | MultiMarkdown style meta-data uses a format first introduced by the
400 | [MultiMarkdown] project. The data consists of a series of keywords and values
401 | defined at the beginning of a Markdown document, like this:
402 |
403 | ```no-highlight
404 | Title: My Document
405 | Summary: A brief description of my document.
406 | Authors: Waylan Limberg
407 | Tom Christie
408 | Date: January 23, 2018
409 | blank-value:
410 | some_url: https://example.com
411 |
412 | This is the first paragraph of the document.
413 | ```
414 |
415 | The keywords are case-insensitive and may consist of letters, numbers,
416 | underscores and dashes and must end with a colon. The values consist of anything
417 | following the colon on the line and may even be blank.
418 |
419 | If a line is indented by 4 or more spaces, that line is assumed to be an
420 | additional line of the value for the previous keyword. A keyword may have as
421 | many lines as desired. All lines are joined into a single string.
422 |
423 | The first blank line ends all meta-data for the document. Therefore, the first
424 | line of a document must not be blank.
425 |
426 | !!! note
427 |
428 | MkDocs does not support YAML style deliminators (`---` or `...`) for
429 | MultiMarkdown style meta-data. In fact, MkDocs relies on the the presence or
430 | absence of the deliminators to determine whether YAML style meta-data or
431 | MultiMarkdown style meta-data is being used. If the deliminators are
432 | detected, but the content between the deliminators is not valid YAML
433 | meta-data, MkDocs does not attempt to parse the content as MultiMarkdown
434 | style meta-data.
435 |
436 | [YAML]: http://yaml.org
437 | [MultiMarkdown]: http://fletcherpenney.net/MultiMarkdown_Syntax_Guide#metadata
438 | [nav]: configuration.md#nav
439 |
440 | ### Tables
441 |
442 | The [tables] extension adds a basic table syntax to Markdown which is popular
443 | across multiple implementations. The syntax is rather simple and is generally
444 | only useful for simple tabular data.
445 |
446 | A simple table looks like this:
447 |
448 | ```no-highlight
449 | First Header | Second Header | Third Header
450 | ------------ | ------------- | ------------
451 | Content Cell | Content Cell | Content Cell
452 | Content Cell | Content Cell | Content Cell
453 | ```
454 |
455 | If you wish, you can add a leading and tailing pipe to each line of the table:
456 |
457 | ```no-highlight
458 | | First Header | Second Header | Third Header |
459 | | ------------ | ------------- | ------------ |
460 | | Content Cell | Content Cell | Content Cell |
461 | | Content Cell | Content Cell | Content Cell |
462 | ```
463 |
464 | Specify alignment for each column by adding colons to separator lines:
465 |
466 | ```no-highlight
467 | First Header | Second Header | Third Header
468 | :----------- |:-------------:| -----------:
469 | Left | Center | Right
470 | Left | Center | Right
471 | ```
472 |
473 | Note that table cells cannot contain any block level elements and cannot contain
474 | multiple lines of text. They can, however, include inline Markdown as defined in
475 | Markdown's [syntax] rules.
476 |
477 | Additionally, a table must be surrounded by blank lines. There must be a blank
478 | line before and after the table.
479 |
480 | [tables]: https://python-markdown.github.io/extensions/tables/
481 |
482 | ### Fenced code blocks
483 |
484 | The [fenced code blocks] extension adds an alternate method of defining code
485 | blocks without indentation.
486 |
487 | The first line should contain 3 or more backtick (`` ` ``) characters, and the
488 | last line should contain the same number of backtick characters (`` ` ``):
489 |
490 | ~~~no-highlight
491 | ```
492 | Fenced code blocks are like Standard
493 | Markdown’s regular code blocks, except that
494 | they’re not indented and instead rely on
495 | start and end fence lines to delimit the
496 | code block.
497 | ```
498 | ~~~
499 |
500 | With this approach, the language can optionally be specified on the first line
501 | after the backticks which informs any syntax highlighters of the language used:
502 |
503 | ~~~no-highlight
504 | ```python
505 | def fn():
506 | pass
507 | ```
508 | ~~~
509 |
510 | Note that fenced code blocks can not be indented. Therefore, they cannot be
511 | nested inside list items, blockquotes, etc.
512 |
513 | [fenced code blocks]: https://python-markdown.github.io/extensions/fenced_code_blocks/
514 |
--------------------------------------------------------------------------------
/global.h:
--------------------------------------------------------------------------------
1 | #ifndef GLOBALE_H
2 | #define GLOBALE_H
3 |
4 | #include
5 |
6 |
7 | namespace Global
8 | {
9 |
10 | typedef struct
11 | {
12 | QString ipAdd="192.168.0.100";
13 | int DB_Read=1;
14 | int DB_Len=100;
15 | byte DB_Buffer[DB_Len];// resize array before using
16 | } st_PLC;
17 |
18 | st_PLC PLC;
19 |
20 | } // namespace Global
21 |
22 | #endif // GLOBALE_H
23 |
--------------------------------------------------------------------------------
/images/S71200-DB1 monitor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abedGNU/QtSnap7/fa9cedc137408377cfe77457e46d1b332a7612ea/images/S71200-DB1 monitor.png
--------------------------------------------------------------------------------
/images/S71200-DB1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abedGNU/QtSnap7/fa9cedc137408377cfe77457e46d1b332a7612ea/images/S71200-DB1.png
--------------------------------------------------------------------------------
/images/Thumbs.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abedGNU/QtSnap7/fa9cedc137408377cfe77457e46d1b332a7612ea/images/Thumbs.db
--------------------------------------------------------------------------------
/images/Thumbs.db:encryptable:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abedGNU/QtSnap7/fa9cedc137408377cfe77457e46d1b332a7612ea/images/Thumbs.db:encryptable
--------------------------------------------------------------------------------
/lib.pri:
--------------------------------------------------------------------------------
1 | # read librarias from the lib folder for linux or windows
2 | LIBS += -L$$PWD/lib/ -lsnap7
3 |
4 | INCLUDEPATH += $$PWD/.
5 | DEPENDPATH += $$PWD/.
6 |
--------------------------------------------------------------------------------
/lib/snap7.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abedGNU/QtSnap7/fa9cedc137408377cfe77457e46d1b332a7612ea/lib/snap7.dll
--------------------------------------------------------------------------------
/lib/snap7.lib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abedGNU/QtSnap7/fa9cedc137408377cfe77457e46d1b332a7612ea/lib/snap7.lib
--------------------------------------------------------------------------------
/main.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 | #include
3 |
4 | int main(int argc, char *argv[])
5 | {
6 | QApplication a(argc, argv);
7 | MainWindow w;
8 | w.show();
9 |
10 | return a.exec();
11 | }
12 |
--------------------------------------------------------------------------------
/mainwindow.cpp:
--------------------------------------------------------------------------------
1 | #include "mainwindow.h"
2 |
3 |
4 | MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)
5 | {
6 | setupUi(this);
7 |
8 | Italian = new QTranslator(this);
9 | Italian->load(":/translations/translation/translation_it.qm");
10 |
11 | pbWrite->setText(tr("Write"));
12 | ipLabel->setText(tr("PLC IP address")+settings.PlcIpAddress);
13 |
14 | plcSiemens = new PLC_Siemens(settings.PlcIpAddress,settings.NoDB, settings.BufferLen);
15 | plcSiemens->start();
16 |
17 | timer= new QTimer(this);
18 | connect(timer, SIGNAL(timeout()), this, SLOT(update()));
19 | timer->start(100);
20 |
21 | }
22 |
23 | void MainWindow::byteCastingtest()
24 | {
25 | // uint8_t pBuff = { 0x11 , 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19 };
26 | PtestStruct_t pStruct = (PtestStruct_t)plcSiemens->DB_Buffer;
27 | qDebug()<< "Test casting";
28 | }
29 |
30 | void MainWindow::changeEvent(QEvent *event)
31 | {
32 | if(event->type() == QEvent::LanguageChange)
33 | {
34 | retranslateUi(this);
35 | }
36 | else
37 | {
38 | QMainWindow::changeEvent(event);
39 | }
40 | }
41 |
42 |
43 | void MainWindow::on_pbWrite_clicked()
44 | {
45 | int dbNo, offset;
46 | dbNo=1;
47 | offset=20;
48 | plcSiemens->WriteVal(plcSiemens->eByte,dbNo,offset,(byte)spinBox->value());
49 | }
50 |
51 | void MainWindow::update()
52 | {
53 | if (plcSiemens->connect() )
54 | {
55 | QString txt = "counter 0: " + QString::number( plcSiemens->getUInt32(0)) + "\n\n";
56 | txt = txt + "counterByte 4: "+ QString::number( plcSiemens->DB_Buffer[4]) + "\n\n";
57 | txt = txt + "cInt 6: " + QString::number( plcSiemens->getInt16(plcSiemens->DB_Buffer,6 )) + "\n\n";
58 | txt = txt + "cWord 8: " + QString::number( plcSiemens->getUInt16(plcSiemens->DB_Buffer,8 )) + "\n\n";
59 | txt = txt + "cDword 10: " + QString::number( plcSiemens->getUInt32(plcSiemens->DB_Buffer,10 )) + "\n\n";
60 | txt = txt + "cReal 14: " + QString::number( plcSiemens->getReal(plcSiemens->DB_Buffer,14 )) + "\n\n";
61 |
62 | for(int i=18;i<30;i++)
63 | {
64 | txt = txt + "Byte "+ QString::number(i) +" : " + QString::number( plcSiemens->DB_Buffer[i]) + "\n";
65 | }
66 | label->setText(txt );
67 | }
68 | }
69 |
70 |
71 |
72 | void MainWindow::on_pbTestCasting_clicked()
73 | {
74 | byteCastingtest();
75 | }
76 |
77 | void MainWindow::on_actionEnglish_triggered()
78 | {
79 | qApp->removeTranslator(Italian);
80 | lblLanguage->setText(tr("English"));
81 | }
82 |
83 | void MainWindow::on_actionItalian_triggered()
84 | {
85 | qApp->installTranslator(Italian);
86 | lblLanguage->setText(tr("Italian"));
87 | }
88 |
--------------------------------------------------------------------------------
/mainwindow.h:
--------------------------------------------------------------------------------
1 | #ifndef MAINWINDOW_H
2 | #define MAINWINDOW_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | #include "ui_mainwindow.h"
10 | #include "snap7.h"
11 | #include "plc_siemens.h"
12 |
13 | #include "settings.h"
14 |
15 | class MainWindow : public QMainWindow, private Ui::MainWindow
16 | {
17 | Q_OBJECT
18 |
19 | public:
20 | explicit MainWindow(QWidget *parent = 0);
21 |
22 | Settings settings;
23 |
24 | PLC_Siemens *plcSiemens;
25 |
26 | QTimer *timer ;
27 |
28 | void byteCastingtest();
29 |
30 | #pragma pack(push, 1)
31 | typedef struct
32 | {
33 | int32_t counterDint;
34 | uint8_t counterByte;
35 | int16_t cInt;
36 | uint16_t cWord;
37 | uint32_t cDWord;
38 | float_t cReal;
39 | uint8_t cByte18;
40 | uint8_t cByte19;
41 | uint8_t cByte20;
42 | uint8_t cByte21;
43 | uint8_t cByte22;
44 | } testStruct_t, *PtestStruct_t;
45 | #pragma pack(pop)
46 |
47 | private:
48 | QTranslator *Italian;
49 |
50 | protected:
51 | //void closeEvent(QCloseEvent *event);
52 | void changeEvent(QEvent *event);
53 |
54 | private slots:
55 | void on_pbWrite_clicked();
56 |
57 | void update();
58 |
59 | void on_pbTestCasting_clicked();
60 | void on_actionEnglish_triggered();
61 | void on_actionItalian_triggered();
62 | };
63 |
64 | #endif // MAINWINDOW_H
65 |
--------------------------------------------------------------------------------
/mainwindow.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 656
10 | 625
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 |
19 |
20 | 20
21 | 130
22 | 321
23 | 351
24 |
25 |
26 |
27 | PLC data
28 |
29 |
30 |
31 |
32 |
33 | 20
34 | 60
35 | 131
36 | 41
37 |
38 |
39 |
40 | Write
41 |
42 |
43 |
44 |
45 |
46 | 170
47 | 60
48 | 91
49 | 41
50 |
51 |
52 |
53 |
54 |
55 |
56 | 500
57 | 80
58 | 131
59 | 41
60 |
61 |
62 |
63 | TestCasting
64 |
65 |
66 |
67 |
68 |
69 | 40
70 | 10
71 | 301
72 | 31
73 |
74 |
75 |
76 | Ip address
77 |
78 |
79 |
80 |
81 |
82 | 440
83 | 10
84 | 131
85 | 41
86 |
87 |
88 |
89 | TextLabel
90 |
91 |
92 |
93 |
94 |
95 |
96 | 0
97 | 0
98 | 656
99 | 22
100 |
101 |
102 |
103 |
104 | Language
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | TopToolBarArea
114 |
115 |
116 | false
117 |
118 |
119 |
120 |
121 |
122 | English
123 |
124 |
125 |
126 |
127 | Italian
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/plc_siemens.cpp:
--------------------------------------------------------------------------------
1 | #include "plc_siemens.h"
2 |
3 | PLC_Siemens::PLC_Siemens(QString ipAddress)
4 | {
5 | MyS7Client = new TS7Client();
6 | this->ipAddress = ipAddress;
7 | connect();
8 | }
9 |
10 | PLC_Siemens::PLC_Siemens(QString ipAddress, int DB_No, int DB_Length)
11 | {
12 | MyS7Client = new TS7Client();
13 | this->ipAddress = ipAddress;
14 | this->DB_No= DB_No;
15 | this->DB_Length = DB_Length;
16 | connect();
17 | }
18 |
19 | bool PLC_Siemens::connect()
20 | {
21 | if ( !MyS7Client->Connected() )
22 | {
23 | return MyS7Client->ConnectTo(ipAddress.toStdString().c_str() ,0,0);
24 | }
25 | else {
26 | return MyS7Client->Connected();
27 | }
28 | }
29 |
30 | void PLC_Siemens::ReadCycle()
31 | {
32 | int res;
33 | res = MyS7Client->DBRead(1, 0, 30, &DB_Buffer);
34 | if (res!=0)
35 | {
36 | qDebug()<< "Error read from DB:" << "1 "<Connected())
45 | {
46 | if (typ == eByte )
47 | {
48 | int res = MyS7Client->DBWrite(dbNum, offset,1,&val);
49 | qDebug()<< "Write to DB" << dbNum <<".DBB"<
6 | #include
7 | #include
8 | #include
9 |
10 | class PLC_Siemens : public QThread
11 | {
12 |
13 |
14 | typedef float *pfloat;
15 |
16 | public:
17 | enum dataType {eBit, eByte, eInt, eDInt, eWord, eDowrd, eReal};
18 | PLC_Siemens(QString ipAddress);
19 | PLC_Siemens(QString ipAddress, int DB_No, int DB_Length);
20 | //
21 | bool connect();
22 | void ReadCycle();
23 | bool WriteVal( dataType typ, int dbNum, int offset, int val);
24 | //
25 | QMutex mutex;
26 |
27 | // Helper functions
28 | uint getUInt16(int Pos);
29 | uint getUInt16(byte* Buffer, int Pos);
30 |
31 | int getInt16(int Pos);
32 | int getInt16(byte* Buffer, int Pos);
33 |
34 | int getUInt32( int Pos);
35 | uint getUInt32(byte* Buffer, int Pos);
36 |
37 | int getInt32(int Pos);
38 | int getInt32(byte* Buffer, int Pos);
39 |
40 | double getReal(int Pos);
41 | double getReal(byte* Buffer, int Pos);
42 | //
43 | QString ipAddress;
44 | int DB_No=1;
45 | int DB_Length=20;
46 |
47 | TS7Client *MyS7Client;
48 | byte DB_Buffer[200];
49 |
50 | protected:
51 | void run();
52 | private:
53 | int old_value;
54 | };
55 |
56 | #endif // PLC_SIEMENS_H
57 |
--------------------------------------------------------------------------------
/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | images/S71200-DB1.png
4 |
5 |
6 | translation/translation_it.qm
7 |
8 |
9 |
--------------------------------------------------------------------------------
/settings.cpp:
--------------------------------------------------------------------------------
1 | #include "settings.h"
2 |
3 | Settings::Settings()
4 | {
5 | QFile settFile(settingsFileName);
6 | int res =-1;
7 | /* If settings file doesn't exist in the default directory
8 | * create new one with default value Or select one
9 | **/
10 | settings = new QSettings(settingsFileName, QSettings::IniFormat);
11 | if (!settFile.exists())
12 | {
13 | createDefaultSettings();
14 | qDebug() << "Creating default setting in: " << "done " << res;
15 | }
16 | else
17 | {
18 | //choose a file from dialog windows??
19 | }
20 |
21 | /* Load settings from file
22 | **/
23 | res=loadSettings();
24 | qDebug() << "Loading setting from: " << "done " << res;
25 | }
26 |
27 | int Settings::loadSettings()
28 | {
29 | settings->beginGroup("PLC");
30 | PlcIpAddress = settings->value("PlcAddress").toString();
31 | NoDB = settings->value("DBNumber").toInt();
32 | BufferLen = settings->value("Bufferlength").toInt();
33 | settings->endGroup();
34 | return 0;
35 | }
36 |
37 | int Settings::saveSettings()
38 | {
39 | settings->beginGroup("PLC");
40 | settings->setValue("PlcAddress", PlcIpAddress);
41 | settings->setValue("DBNumber",NoDB );
42 | settings->setValue("Bufferlength", BufferLen);
43 | settings->endGroup();
44 | return 0;
45 | }
46 |
47 | int Settings::createDefaultSettings()
48 | {
49 | settings->beginGroup("PLC");
50 | settings->setValue("PlcAddress", PlcIpAddressDef);
51 | settings->setValue("DBNumber",NoDBdef);
52 | settings->setValue("Bufferlength", BufferLendef);
53 | settings->endGroup();
54 | return 0;
55 | }
56 |
--------------------------------------------------------------------------------
/settings.h:
--------------------------------------------------------------------------------
1 | #ifndef SETTINGS_H
2 | #define SETTINGS_H
3 |
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 | class Settings
10 | {
11 | public:
12 | Settings();
13 | QSettings *settings;
14 | int loadSettings();
15 | int saveSettings();
16 | int createDefaultSettings();
17 |
18 | QString PlcIpAddress;
19 | int NoDB;
20 | int BufferLen;
21 | //
22 |
23 | private:
24 | QString PlcIpAddressDef="192.168.0.100";
25 | int NoDBdef=1;
26 | int BufferLendef=20;
27 |
28 | QString settingsFileName = "settings.ini";
29 | };
30 |
31 | #endif // SETTINGS_H
32 |
--------------------------------------------------------------------------------
/snap7.cpp:
--------------------------------------------------------------------------------
1 | /*=============================================================================|
2 | | PROJECT SNAP7 1.4.0 |
3 | |==============================================================================|
4 | | Copyright (C) 2013, 2014 Davide Nardella |
5 | | All rights reserved. |
6 | |==============================================================================|
7 | | SNAP7 is free software: you can redistribute it and/or modify |
8 | | it under the terms of the Lesser GNU General Public License as published by |
9 | | the Free Software Foundation, either version 3 of the License, or |
10 | | (at your option) any later version. |
11 | | |
12 | | It means that you can distribute your commercial software linked with |
13 | | SNAP7 without the requirement to distribute the source code of your |
14 | | application and without the requirement that your application be itself |
15 | | distributed under LGPL. |
16 | | |
17 | | SNAP7 is distributed in the hope that it will be useful, |
18 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
20 | | Lesser GNU General Public License for more details. |
21 | | |
22 | | You should have received a copy of the GNU General Public License and a |
23 | | copy of Lesser GNU General Public License along with Snap7. |
24 | | If not, see http://www.gnu.org/licenses/ |
25 | |==============================================================================|
26 | | |
27 | | C++ Snap 7 classes Implementation |
28 | | |
29 | |=============================================================================*/
30 |
31 | #include "snap7.h"
32 |
33 | //==============================================================================
34 | // CLIENT
35 | //==============================================================================
36 | TS7Client::TS7Client()
37 | {
38 | Client=Cli_Create();
39 | }
40 | //---------------------------------------------------------------------------
41 | TS7Client::~TS7Client()
42 | {
43 | Cli_Destroy(&Client);
44 | }
45 | //---------------------------------------------------------------------------
46 | int TS7Client::Connect()
47 | {
48 | return Cli_Connect(Client);
49 | }
50 | //---------------------------------------------------------------------------
51 | int TS7Client::ConnectTo(const char *RemAddress, int Rack, int Slot)
52 | {
53 | return Cli_ConnectTo(Client, RemAddress, Rack, Slot);
54 | }
55 | //---------------------------------------------------------------------------
56 | int TS7Client::SetConnectionParams(const char *RemAddress, word LocalTSAP, word RemoteTSAP)
57 | {
58 | return Cli_SetConnectionParams(Client, RemAddress, LocalTSAP, RemoteTSAP);
59 | }
60 | //---------------------------------------------------------------------------
61 | int TS7Client::SetConnectionType(word ConnectionType)
62 | {
63 | return Cli_SetConnectionType(Client, ConnectionType);
64 | }
65 | //---------------------------------------------------------------------------
66 | int TS7Client::Disconnect()
67 | {
68 | return Cli_Disconnect(Client);
69 | }
70 | //---------------------------------------------------------------------------
71 | int TS7Client::GetParam(int ParamNumber, void *pValue)
72 | {
73 | return Cli_GetParam(Client, ParamNumber, pValue);
74 | }
75 | //---------------------------------------------------------------------------
76 | int TS7Client::SetParam(int ParamNumber, void *pValue)
77 | {
78 | return Cli_SetParam(Client, ParamNumber, pValue);
79 | }
80 | //---------------------------------------------------------------------------
81 | int TS7Client::ReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)
82 | {
83 | return Cli_ReadArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);
84 | }
85 | //---------------------------------------------------------------------------
86 | int TS7Client::WriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)
87 | {
88 | return Cli_WriteArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);
89 | }
90 | //---------------------------------------------------------------------------
91 | int TS7Client::ReadMultiVars(PS7DataItem Item, int ItemsCount)
92 | {
93 | return Cli_ReadMultiVars(Client, Item, ItemsCount);
94 | }
95 | //---------------------------------------------------------------------------
96 | int TS7Client::WriteMultiVars(PS7DataItem Item, int ItemsCount)
97 | {
98 | return Cli_WriteMultiVars(Client, Item, ItemsCount);
99 | }
100 | //---------------------------------------------------------------------------
101 | int TS7Client::DBRead(int DBNumber, int Start, int Size, void *pUsrData)
102 | {
103 | return Cli_DBRead(Client, DBNumber, Start, Size, pUsrData);
104 | }
105 | //---------------------------------------------------------------------------
106 | int TS7Client::DBWrite(int DBNumber, int Start, int Size, void *pUsrData)
107 | {
108 | return Cli_DBWrite(Client, DBNumber, Start, Size, pUsrData);
109 | }
110 | //---------------------------------------------------------------------------
111 | int TS7Client::MBRead(int Start, int Size, void *pUsrData)
112 | {
113 | return Cli_MBRead(Client, Start, Size, pUsrData);
114 | }
115 | //---------------------------------------------------------------------------
116 | int TS7Client::MBWrite(int Start, int Size, void *pUsrData)
117 | {
118 | return Cli_MBWrite(Client, Start, Size, pUsrData);
119 | }
120 | //---------------------------------------------------------------------------
121 | int TS7Client::EBRead(int Start, int Size, void *pUsrData)
122 | {
123 | return Cli_EBRead(Client, Start, Size, pUsrData);
124 | }
125 | //---------------------------------------------------------------------------
126 | int TS7Client::EBWrite(int Start, int Size, void *pUsrData)
127 | {
128 | return Cli_EBWrite(Client, Start, Size, pUsrData);
129 | }
130 | //---------------------------------------------------------------------------
131 | int TS7Client::ABRead(int Start, int Size, void *pUsrData)
132 | {
133 | return Cli_ABRead(Client, Start, Size, pUsrData);
134 | }
135 | //---------------------------------------------------------------------------
136 | int TS7Client::ABWrite(int Start, int Size, void *pUsrData)
137 | {
138 | return Cli_ABWrite(Client, Start, Size, pUsrData);
139 | }
140 | //---------------------------------------------------------------------------
141 | int TS7Client::TMRead(int Start, int Amount, void *pUsrData)
142 | {
143 | return Cli_TMRead(Client, Start, Amount, pUsrData);
144 | }
145 | //---------------------------------------------------------------------------
146 | int TS7Client::TMWrite(int Start, int Amount, void *pUsrData)
147 | {
148 | return Cli_TMWrite(Client, Start, Amount, pUsrData);
149 | }
150 | //---------------------------------------------------------------------------
151 | int TS7Client::CTRead(int Start, int Amount, void *pUsrData)
152 | {
153 | return Cli_CTRead(Client, Start, Amount, pUsrData);
154 | }
155 | //---------------------------------------------------------------------------
156 | int TS7Client::CTWrite(int Start, int Amount, void *pUsrData)
157 | {
158 | return Cli_CTWrite(Client, Start, Amount, pUsrData);
159 | }
160 | //---------------------------------------------------------------------------
161 | int TS7Client::ListBlocks(PS7BlocksList pUsrData)
162 | {
163 | return Cli_ListBlocks(Client, pUsrData);
164 | }
165 | //---------------------------------------------------------------------------
166 | int TS7Client::GetAgBlockInfo(int BlockType, int BlockNum, PS7BlockInfo pUsrData)
167 | {
168 | return Cli_GetAgBlockInfo(Client, BlockType, BlockNum, pUsrData);
169 | }
170 | //---------------------------------------------------------------------------
171 | int TS7Client::GetPgBlockInfo(void *pBlock, PS7BlockInfo pUsrData, int Size)
172 | {
173 | return Cli_GetPgBlockInfo(Client, pBlock, pUsrData, Size);
174 | }
175 | //---------------------------------------------------------------------------
176 | int TS7Client::ListBlocksOfType(int BlockType, TS7BlocksOfType *pUsrData, int *ItemsCount)
177 | {
178 | return Cli_ListBlocksOfType(Client, BlockType, pUsrData, ItemsCount);
179 | }
180 | //---------------------------------------------------------------------------
181 | int TS7Client::Upload(int BlockType, int BlockNum, void *pUsrData, int *Size)
182 | {
183 | return Cli_Upload(Client, BlockType, BlockNum, pUsrData, Size);
184 | }
185 | //---------------------------------------------------------------------------
186 | int TS7Client::FullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size)
187 | {
188 | return Cli_FullUpload(Client, BlockType, BlockNum, pUsrData, Size);
189 | }
190 | //---------------------------------------------------------------------------
191 | int TS7Client::Download(int BlockNum, void *pUsrData, int Size)
192 | {
193 | return Cli_Download(Client, BlockNum, pUsrData, Size);
194 | }
195 | //---------------------------------------------------------------------------
196 | int TS7Client::Delete(int BlockType, int BlockNum)
197 | {
198 | return Cli_Delete(Client, BlockType, BlockNum);
199 | }
200 | //---------------------------------------------------------------------------
201 | int TS7Client::DBGet(int DBNumber, void *pUsrData, int *Size)
202 | {
203 | return Cli_DBGet(Client, DBNumber, pUsrData, Size);
204 | }
205 | //---------------------------------------------------------------------------
206 | int TS7Client::DBFill(int DBNumber, int FillChar)
207 | {
208 | return Cli_DBFill(Client, DBNumber, FillChar);
209 | }
210 | //---------------------------------------------------------------------------
211 | int TS7Client::GetPlcDateTime(tm *DateTime)
212 | {
213 | return Cli_GetPlcDateTime(Client, DateTime);
214 | }
215 | //---------------------------------------------------------------------------
216 | int TS7Client::SetPlcDateTime(tm *DateTime)
217 | {
218 | return Cli_SetPlcDateTime(Client, DateTime);
219 | }
220 | //---------------------------------------------------------------------------
221 | int TS7Client::SetPlcSystemDateTime()
222 | {
223 | return Cli_SetPlcSystemDateTime(Client);
224 | }
225 | //---------------------------------------------------------------------------
226 | int TS7Client::GetOrderCode(PS7OrderCode pUsrData)
227 | {
228 | return Cli_GetOrderCode(Client, pUsrData);
229 | }
230 | //---------------------------------------------------------------------------
231 | int TS7Client::GetCpuInfo(PS7CpuInfo pUsrData)
232 | {
233 | return Cli_GetCpuInfo(Client, pUsrData);
234 | }
235 | //---------------------------------------------------------------------------
236 | int TS7Client::GetCpInfo(PS7CpInfo pUsrData)
237 | {
238 | return Cli_GetCpInfo(Client, pUsrData);
239 | }
240 | //---------------------------------------------------------------------------
241 | int TS7Client::ReadSZL(int ID, int Index, PS7SZL pUsrData, int *Size)
242 | {
243 | return Cli_ReadSZL(Client, ID, Index, pUsrData, Size);
244 | }
245 | //---------------------------------------------------------------------------
246 | int TS7Client::ReadSZLList(PS7SZLList pUsrData, int *ItemsCount)
247 | {
248 | return Cli_ReadSZLList(Client, pUsrData, ItemsCount);
249 | }
250 | //---------------------------------------------------------------------------
251 | int TS7Client::PlcHotStart()
252 | {
253 | return Cli_PlcHotStart(Client);
254 | }
255 | //---------------------------------------------------------------------------
256 | int TS7Client::PlcColdStart()
257 | {
258 | return Cli_PlcColdStart(Client);
259 | }
260 | //---------------------------------------------------------------------------
261 | int TS7Client::PlcStop()
262 | {
263 | return Cli_PlcStop(Client);
264 | }
265 | //---------------------------------------------------------------------------
266 | int TS7Client::CopyRamToRom(int Timeout)
267 | {
268 | return Cli_CopyRamToRom(Client, Timeout);
269 | }
270 | //---------------------------------------------------------------------------
271 | int TS7Client::Compress(int Timeout)
272 | {
273 | return Cli_Compress(Client, Timeout);
274 | }
275 | //---------------------------------------------------------------------------
276 | int TS7Client::GetProtection(PS7Protection pUsrData)
277 | {
278 | return Cli_GetProtection(Client, pUsrData);
279 | }
280 | //---------------------------------------------------------------------------
281 | int TS7Client::SetSessionPassword(char *Password)
282 | {
283 | return Cli_SetSessionPassword(Client, Password);
284 | }
285 | //---------------------------------------------------------------------------
286 | int TS7Client::ClearSessionPassword()
287 | {
288 | return Cli_ClearSessionPassword(Client);
289 | }
290 | //---------------------------------------------------------------------------
291 | int TS7Client::ExecTime()
292 | {
293 | int Time;
294 | int Result = Cli_GetExecTime(Client, &Time);
295 | if (Result==0)
296 | return Time;
297 | else
298 | return Result;
299 | }
300 | //---------------------------------------------------------------------------
301 | int TS7Client::LastError()
302 | {
303 | int LastError;
304 | int Result =Cli_GetLastError(Client, &LastError);
305 | if (Result==0)
306 | return LastError;
307 | else
308 | return Result;
309 | }
310 | //---------------------------------------------------------------------------
311 | int TS7Client::PDULength()
312 | {
313 | int Requested, Negotiated;
314 | if (Cli_GetPduLength(Client, &Requested, &Negotiated)==0)
315 | return Negotiated;
316 | else
317 | return 0;
318 | }
319 | //---------------------------------------------------------------------------
320 | int TS7Client::PDURequested()
321 | {
322 | int Requested, Negotiated;
323 | if (Cli_GetPduLength(Client, &Requested, &Negotiated)==0)
324 | return Requested;
325 | else
326 | return 0;
327 | }
328 | //---------------------------------------------------------------------------
329 | int TS7Client::PlcStatus()
330 | {
331 | int Status;
332 | int Result = Cli_GetPlcStatus(Client, &Status);
333 | if (Result==0)
334 | return Status;
335 | else
336 | return Result;
337 | }
338 | //---------------------------------------------------------------------------
339 | bool TS7Client::Connected()
340 | {
341 | int ClientStatus;
342 | if (Cli_GetConnected(Client ,&ClientStatus)==0)
343 | return ClientStatus!=0;
344 | else
345 | return false;
346 | }
347 | //---------------------------------------------------------------------------
348 | int TS7Client::SetAsCallback(pfn_CliCompletion pCompletion, void *usrPtr)
349 | {
350 | return Cli_SetAsCallback(Client, pCompletion, usrPtr);
351 | }
352 | //---------------------------------------------------------------------------
353 | bool TS7Client::CheckAsCompletion(int *opResult)
354 | {
355 | return Cli_CheckAsCompletion(Client ,opResult)==JobComplete;
356 | }
357 | //---------------------------------------------------------------------------
358 | int TS7Client::WaitAsCompletion(longword Timeout)
359 | {
360 | return Cli_WaitAsCompletion(Client, Timeout);
361 | }
362 | //---------------------------------------------------------------------------
363 | int TS7Client::AsReadArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)
364 | {
365 | return Cli_AsReadArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);
366 | }
367 | //---------------------------------------------------------------------------
368 | int TS7Client::AsWriteArea(int Area, int DBNumber, int Start, int Amount, int WordLen, void *pUsrData)
369 | {
370 | return Cli_AsWriteArea(Client, Area, DBNumber, Start, Amount, WordLen, pUsrData);
371 | }
372 | //---------------------------------------------------------------------------
373 | int TS7Client::AsListBlocksOfType(int BlockType, PS7BlocksOfType pUsrData, int *ItemsCount)
374 | {
375 | return Cli_AsListBlocksOfType(Client, BlockType, pUsrData, ItemsCount);
376 | }
377 | //---------------------------------------------------------------------------
378 | int TS7Client::AsReadSZL(int ID, int Index, PS7SZL pUsrData, int *Size)
379 | {
380 | return Cli_AsReadSZL(Client, ID, Index, pUsrData, Size);
381 | }
382 | //---------------------------------------------------------------------------
383 | int TS7Client::AsReadSZLList(PS7SZLList pUsrData, int *ItemsCount)
384 | {
385 | return Cli_AsReadSZLList(Client, pUsrData, ItemsCount);
386 | }
387 | //---------------------------------------------------------------------------
388 | int TS7Client::AsUpload(int BlockType, int BlockNum, void *pUsrData, int *Size)
389 | {
390 | return Cli_AsUpload(Client, BlockType, BlockNum, pUsrData, Size);
391 | }
392 | //---------------------------------------------------------------------------
393 | int TS7Client::AsFullUpload(int BlockType, int BlockNum, void *pUsrData, int *Size)
394 | {
395 | return Cli_AsFullUpload(Client, BlockType, BlockNum, pUsrData, Size);
396 | }
397 | //---------------------------------------------------------------------------
398 | int TS7Client::AsDownload(int BlockNum, void *pUsrData, int Size)
399 | {
400 | return Cli_AsDownload(Client, BlockNum, pUsrData, Size);
401 | }
402 | //---------------------------------------------------------------------------
403 | int TS7Client::AsCopyRamToRom(int Timeout)
404 | {
405 | return Cli_AsCopyRamToRom(Client, Timeout);
406 | }
407 | //---------------------------------------------------------------------------
408 | int TS7Client::AsCompress(int Timeout)
409 | {
410 | return Cli_AsCompress(Client, Timeout);
411 | }
412 | //---------------------------------------------------------------------------
413 | int TS7Client::AsDBRead(int DBNumber, int Start, int Size, void *pUsrData)
414 | {
415 | return Cli_AsDBRead(Client, DBNumber, Start, Size, pUsrData);
416 | }
417 | //---------------------------------------------------------------------------
418 | int TS7Client::AsDBWrite(int DBNumber, int Start, int Size, void *pUsrData)
419 | {
420 | return Cli_AsDBWrite(Client, DBNumber, Start, Size, pUsrData);
421 | }
422 | //---------------------------------------------------------------------------
423 | int TS7Client::AsMBRead(int Start, int Size, void *pUsrData)
424 | {
425 | return Cli_AsMBRead(Client, Start, Size, pUsrData);
426 | }
427 | //---------------------------------------------------------------------------
428 | int TS7Client::AsMBWrite(int Start, int Size, void *pUsrData)
429 | {
430 | return Cli_AsMBWrite(Client, Start, Size, pUsrData);
431 | }
432 | //---------------------------------------------------------------------------
433 | int TS7Client::AsEBRead(int Start, int Size, void *pUsrData)
434 | {
435 | return Cli_AsEBRead(Client, Start, Size, pUsrData);
436 | }
437 | //---------------------------------------------------------------------------
438 | int TS7Client::AsEBWrite(int Start, int Size, void *pUsrData)
439 | {
440 | return Cli_AsEBWrite(Client, Start, Size, pUsrData);
441 | }
442 | //---------------------------------------------------------------------------
443 | int TS7Client::AsABRead(int Start, int Size, void *pUsrData)
444 | {
445 | return Cli_AsABRead(Client, Start, Size, pUsrData);
446 | }
447 | //---------------------------------------------------------------------------
448 | int TS7Client::AsABWrite(int Start, int Size, void *pUsrData)
449 | {
450 | return Cli_AsABWrite(Client, Start, Size, pUsrData);
451 | }
452 | //---------------------------------------------------------------------------
453 | int TS7Client::AsTMRead(int Start, int Amount, void *pUsrData)
454 | {
455 | return Cli_AsTMRead(Client, Start, Amount, pUsrData);
456 | }
457 | //---------------------------------------------------------------------------
458 | int TS7Client::AsTMWrite(int Start, int Amount, void *pUsrData)
459 | {
460 | return Cli_AsTMWrite(Client, Start, Amount, pUsrData);
461 | }
462 | //---------------------------------------------------------------------------
463 | int TS7Client::AsCTRead(int Start, int Amount, void *pUsrData)
464 | {
465 | return Cli_AsCTRead(Client, Start, Amount, pUsrData);
466 | }
467 | //---------------------------------------------------------------------------
468 | int TS7Client::AsCTWrite(int Start, int Amount, void *pUsrData)
469 | {
470 | return Cli_AsCTWrite(Client, Start, Amount, pUsrData);
471 | }
472 | //---------------------------------------------------------------------------
473 | int TS7Client::AsDBGet(int DBNumber, void *pUsrData, int *Size)
474 | {
475 | return Cli_AsDBGet(Client, DBNumber, pUsrData, Size);
476 | }
477 | //---------------------------------------------------------------------------
478 | int TS7Client::AsDBFill(int DBNumber, int FillChar)
479 | {
480 | return Cli_AsDBFill(Client, DBNumber, FillChar);
481 | }
482 | //==============================================================================
483 | // SERVER
484 | //==============================================================================
485 | TS7Server::TS7Server()
486 | {
487 | Server=Srv_Create();
488 | }
489 | //---------------------------------------------------------------------------
490 | TS7Server::~TS7Server()
491 | {
492 | Srv_Destroy(&Server);
493 | }
494 | //---------------------------------------------------------------------------
495 | int TS7Server::Start()
496 | {
497 | return Srv_Start(Server);
498 | }
499 | //---------------------------------------------------------------------------
500 | int TS7Server::StartTo(const char *Address)
501 | {
502 | return Srv_StartTo(Server, Address);
503 | }
504 | //---------------------------------------------------------------------------
505 | int TS7Server::Stop()
506 | {
507 | return Srv_Stop(Server);
508 | }
509 | //---------------------------------------------------------------------------
510 | int TS7Server::GetParam(int ParamNumber, void *pValue)
511 | {
512 | return Srv_GetParam(Server, ParamNumber, pValue);
513 | }
514 | //---------------------------------------------------------------------------
515 | int TS7Server::SetParam(int ParamNumber, void *pValue)
516 | {
517 | return Srv_SetParam(Server, ParamNumber, pValue);
518 | }
519 | //---------------------------------------------------------------------------
520 | int TS7Server::SetEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr)
521 | {
522 | return Srv_SetEventsCallback(Server, PCallBack, UsrPtr);
523 | }
524 | //---------------------------------------------------------------------------
525 | int TS7Server::SetReadEventsCallback(pfn_SrvCallBack PCallBack, void *UsrPtr)
526 | {
527 | return Srv_SetReadEventsCallback(Server, PCallBack, UsrPtr);
528 | }
529 | //---------------------------------------------------------------------------
530 | int TS7Server::SetRWAreaCallback(pfn_RWAreaCallBack PCallBack, void *UsrPtr)
531 | {
532 | return Srv_SetRWAreaCallback(Server, PCallBack, UsrPtr);
533 | }
534 | //---------------------------------------------------------------------------
535 | bool TS7Server::PickEvent(TSrvEvent *pEvent)
536 | {
537 | int EvtReady;
538 | if (Srv_PickEvent(Server, pEvent, &EvtReady)==0)
539 | return EvtReady!=0;
540 | else
541 | return false;
542 | }
543 | //---------------------------------------------------------------------------
544 | void TS7Server::ClearEvents()
545 | {
546 | Srv_ClearEvents(Server);
547 | }
548 | //---------------------------------------------------------------------------
549 | longword TS7Server::GetEventsMask()
550 | {
551 | longword Mask;
552 | int Result = Srv_GetMask(Server, mkEvent, &Mask);
553 | if (Result==0)
554 | return Mask;
555 | else
556 | return 0;
557 | }
558 | //---------------------------------------------------------------------------
559 | longword TS7Server::GetLogMask()
560 | {
561 | longword Mask;
562 | int Result = Srv_GetMask(Server, mkLog, &Mask);
563 | if (Result==0)
564 | return Mask;
565 | else
566 | return 0;
567 | }
568 | //---------------------------------------------------------------------------
569 | void TS7Server::SetEventsMask(longword Mask)
570 | {
571 | Srv_SetMask(Server, mkEvent, Mask);
572 | }
573 | //---------------------------------------------------------------------------
574 | void TS7Server::SetLogMask(longword Mask)
575 | {
576 | Srv_SetMask(Server, mkLog, Mask);
577 | }
578 | //---------------------------------------------------------------------------
579 | int TS7Server::RegisterArea(int AreaCode, word Index, void *pUsrData, word Size)
580 | {
581 | return Srv_RegisterArea(Server, AreaCode, Index, pUsrData, Size);
582 | }
583 | //---------------------------------------------------------------------------
584 | int TS7Server::UnregisterArea(int AreaCode, word Index)
585 | {
586 | return Srv_UnregisterArea(Server, AreaCode, Index);
587 | }
588 | //---------------------------------------------------------------------------
589 | int TS7Server::LockArea(int AreaCode, word Index)
590 | {
591 | return Srv_LockArea(Server, AreaCode, Index);
592 | }
593 | //---------------------------------------------------------------------------
594 | int TS7Server::UnlockArea(int AreaCode, word Index)
595 | {
596 | return Srv_UnlockArea(Server, AreaCode, Index);
597 | }
598 | //---------------------------------------------------------------------------
599 | int TS7Server::ServerStatus()
600 | {
601 | int ServerStatus, CpuStatus, ClientsCount;
602 | int Result =Srv_GetStatus(Server, &ServerStatus, &CpuStatus, &ClientsCount);
603 | if (Result==0)
604 | return ServerStatus;
605 | else
606 | return Result;
607 | }
608 | //---------------------------------------------------------------------------
609 | int TS7Server::GetCpuStatus()
610 | {
611 | int ServerStatus, CpuStatus, ClientsCount;
612 | int Result =Srv_GetStatus(Server, &ServerStatus, &CpuStatus, &ClientsCount);
613 | if (Result==0)
614 | return CpuStatus;
615 | else
616 | return Result;
617 | }
618 | //---------------------------------------------------------------------------
619 | int TS7Server::ClientsCount()
620 | {
621 | int ServerStatus, CpuStatus, ClientsCount;
622 | int Result =Srv_GetStatus(Server, &ServerStatus, &CpuStatus, &ClientsCount);
623 | if (Result==0)
624 | return ClientsCount;
625 | else
626 | return Result;
627 | }
628 | //---------------------------------------------------------------------------
629 | int TS7Server::SetCpuStatus(int Status)
630 | {
631 | return Srv_SetCpuStatus(Server, Status);
632 | }
633 | //==============================================================================
634 | // PARTNER
635 | //==============================================================================
636 | TS7Partner::TS7Partner(bool Active)
637 | {
638 | Partner=Par_Create(int(Active));
639 | }
640 | //---------------------------------------------------------------------------
641 | TS7Partner::~TS7Partner()
642 | {
643 | Par_Destroy(&Partner);
644 | }
645 | //---------------------------------------------------------------------------
646 | int TS7Partner::GetParam(int ParamNumber, void *pValue)
647 | {
648 | return Par_GetParam(Partner, ParamNumber, pValue);
649 | }
650 | //---------------------------------------------------------------------------
651 | int TS7Partner::SetParam(int ParamNumber, void *pValue)
652 | {
653 | return Par_SetParam(Partner, ParamNumber, pValue);
654 | }
655 | //---------------------------------------------------------------------------
656 | int TS7Partner::Start()
657 | {
658 | return Par_Start(Partner);
659 | }
660 | //---------------------------------------------------------------------------
661 | int TS7Partner::StartTo(const char *LocalAddress, const char *RemoteAddress, int LocalTSAP, int RemoteTSAP)
662 | {
663 | return Par_StartTo(Partner, LocalAddress, RemoteAddress, LocalTSAP, RemoteTSAP);
664 | }
665 | //---------------------------------------------------------------------------
666 | int TS7Partner::Stop()
667 | {
668 | return Par_Stop(Partner);
669 | }
670 | //---------------------------------------------------------------------------
671 | int TS7Partner::BSend(longword R_ID, void *pUsrData, int Size)
672 | {
673 | return Par_BSend(Partner, R_ID, pUsrData, Size);
674 | }
675 | //---------------------------------------------------------------------------
676 | int TS7Partner::AsBSend(longword R_ID, void *pUsrData, int Size)
677 | {
678 | return Par_AsBSend(Partner, R_ID, pUsrData, Size);
679 | }
680 | //---------------------------------------------------------------------------
681 | bool TS7Partner::CheckAsBSendCompletion(int *opResult)
682 | {
683 | return Par_CheckAsBSendCompletion(Partner ,opResult)==JobComplete;
684 | }
685 | //---------------------------------------------------------------------------
686 | int TS7Partner::WaitAsBSendCompletion(longword Timeout)
687 | {
688 | return Par_WaitAsBSendCompletion(Partner, Timeout);
689 | }
690 | //---------------------------------------------------------------------------
691 | int TS7Partner::SetSendCallback(pfn_ParSendCompletion pCompletion, void *usrPtr)
692 | {
693 | return Par_SetSendCallback(Partner, pCompletion, usrPtr);
694 | }
695 | //---------------------------------------------------------------------------
696 | int TS7Partner::BRecv(longword *R_ID, void *pUsrData, int *Size, longword Timeout)
697 | {
698 | return Par_BRecv(Partner, R_ID, pUsrData, Size, Timeout);
699 | }
700 | //---------------------------------------------------------------------------
701 | bool TS7Partner::CheckAsBRecvCompletion(int *opResult, longword *R_ID, void *pUsrData, int *Size)
702 | {
703 | return Par_CheckAsBRecvCompletion(Partner, opResult, R_ID, pUsrData, Size) == JobComplete;
704 | }
705 | //---------------------------------------------------------------------------
706 | int TS7Partner::SetRecvCallback(pfn_ParRecvCallBack pCallback, void *usrPtr)
707 | {
708 | return Par_SetRecvCallback(Partner, pCallback, usrPtr);
709 | }
710 | //---------------------------------------------------------------------------
711 | int TS7Partner::Status()
712 | {
713 | int ParStatus;
714 | int Result = Par_GetStatus(Partner, &ParStatus);
715 | if (Result==0)
716 | return ParStatus;
717 | else
718 | return Result;
719 | }
720 | //---------------------------------------------------------------------------
721 | int TS7Partner::LastError()
722 | {
723 | int Error;
724 | int Result = Par_GetLastError(Partner, &Error);
725 | if (Result==0)
726 | return Error;
727 | else
728 | return Result;
729 | }
730 | //---------------------------------------------------------------------------
731 | int TS7Partner::GetTimes(longword *SendTime, longword *RecvTime)
732 | {
733 | return Par_GetTimes(Partner, SendTime, RecvTime);
734 | }
735 | //---------------------------------------------------------------------------
736 | int TS7Partner::GetStats(longword *BytesSent, longword *BytesRecv, longword *ErrSend, longword *ErrRecv)
737 | {
738 | return Par_GetStats(Partner, BytesSent, BytesRecv, ErrSend, ErrRecv);
739 | }
740 | //---------------------------------------------------------------------------
741 | bool TS7Partner::Linked()
742 | {
743 | return Status()==par_linked;
744 | }
745 | //==============================================================================
746 | // Text routines
747 | //==============================================================================
748 | TextString CliErrorText(int Error)
749 | {
750 | char text[TextLen];
751 | Cli_ErrorText(Error, text, TextLen);
752 | return TextString(text);
753 | }
754 | //---------------------------------------------------------------------------
755 | TextString SrvErrorText(int Error)
756 | {
757 | char text[TextLen];
758 | Srv_ErrorText(Error, text, TextLen);
759 | return TextString(text);
760 | }
761 | //---------------------------------------------------------------------------
762 | TextString ParErrorText(int Error)
763 | {
764 | char text[TextLen];
765 | Par_ErrorText(Error, text, TextLen);
766 | return TextString(text);
767 | }
768 | //---------------------------------------------------------------------------
769 | TextString SrvEventText(TSrvEvent *Event)
770 | {
771 | char text[TextLen];
772 | Srv_EventText(Event, text, TextLen);
773 | return TextString(text);
774 | }
775 |
776 |
--------------------------------------------------------------------------------
/translation/translation_it.qm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/abedGNU/QtSnap7/fa9cedc137408377cfe77457e46d1b332a7612ea/translation/translation_it.qm
--------------------------------------------------------------------------------
/translation/translation_it.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MainWindow
6 |
7 |
8 | MainWindow
9 |
10 |
11 |
12 |
13 | PLC data
14 |
15 |
16 |
17 |
18 |
19 | Write
20 | Scrivi
21 |
22 |
23 |
24 | TestCasting
25 |
26 |
27 |
28 |
29 | Ip address
30 | Indirizzo ip
31 |
32 |
33 |
34 | TextLabel
35 |
36 |
37 |
38 |
39 | Language
40 |
41 |
42 |
43 |
44 |
45 | English
46 | Inglese
47 |
48 |
49 |
50 |
51 | Italian
52 | Italiano
53 |
54 |
55 |
56 | PLC IP address
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------