forked from mfulz_github/qmk_firmware
		
	Reworked docs rendering using jinja2.
This commit is contained in:
		
							parent
							
								
									1e723e6647
								
							
						
					
					
						commit
						69e9c80ec3
					
				
							
								
								
									
										7
									
								
								data/templates/xap/docs/docs.md.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								data/templates/xap/docs/docs.md.j2
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | |||||||
|  | {%- for item in xap.documentation.order -%} | ||||||
|  | {%- if not item[0:1] == '!' -%} | ||||||
|  | {{ xap.documentation.get(item) }} | ||||||
|  | {% else %} | ||||||
|  | {%- include item[1:] %} | ||||||
|  | {% endif %} | ||||||
|  | {% endfor %} | ||||||
							
								
								
									
										9
									
								
								data/templates/xap/docs/response_flags.md.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								data/templates/xap/docs/response_flags.md.j2
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | |||||||
|  | |{% for bitnum, bitinfo in xap.response_flags.bits | dictsort | reverse %} Bit {{ bitnum }} |{% endfor %} | ||||||
|  | |{% for bitnum, bitinfo in xap.response_flags.bits | dictsort | reverse %} -- |{% endfor %} | ||||||
|  | |{% for bitnum, bitinfo in xap.response_flags.bits | dictsort | reverse %} `{{ bitinfo.define }}` |{%- endfor %} | ||||||
|  | 
 | ||||||
|  | {% for bitnum, bitinfo in xap.response_flags.bits | dictsort | reverse %} | ||||||
|  | {%- if bitinfo.define != "-" -%} | ||||||
|  | * Bit {{ bitnum }} (`{{ bitinfo.define }}`): {{ bitinfo.description }} | ||||||
|  | {% endif %} | ||||||
|  | {%- endfor %} | ||||||
							
								
								
									
										5
									
								
								data/templates/xap/docs/term_definitions.md.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								data/templates/xap/docs/term_definitions.md.j2
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | | Name | Definition | | ||||||
|  | | -- | -- | | ||||||
|  | {%- for type, definition in xap.term_definitions | dictsort %} | ||||||
|  | | _{{ type }}_ | {{ definition }} | | ||||||
|  | {%- endfor %} | ||||||
							
								
								
									
										5
									
								
								data/templates/xap/docs/type_docs.md.j2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								data/templates/xap/docs/type_docs.md.j2
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | |||||||
|  | | Name | Definition | | ||||||
|  | | -- | -- | | ||||||
|  | {%- for type, definition in xap.type_docs | dictsort %} | ||||||
|  | | _{{ type }}_ | {{ definition }} | | ||||||
|  | {%- endfor %} | ||||||
| @ -9,13 +9,13 @@ | |||||||
|         order: [ |         order: [ | ||||||
|             page_header |             page_header | ||||||
|             type_docs |             type_docs | ||||||
|             !type_docs! |             !type_docs.md.j2 | ||||||
|             term_definitions |             term_definitions | ||||||
|             !term_definitions! |             !term_definitions.md.j2 | ||||||
|             request_response |             request_response | ||||||
|             reserved_tokens |             reserved_tokens | ||||||
|             response_flags |             response_flags | ||||||
|             !response_flags! |             !response_flags.md.j2 | ||||||
|             example_conversation |             example_conversation | ||||||
|         ] |         ] | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -41,10 +41,11 @@ This token is followed by a `u8` signifying the length of data in the request. | |||||||
| Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length: | Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length: | ||||||
| 
 | 
 | ||||||
| | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | | | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | | ||||||
| |--|--|--|--|--|--|--|--| | | -- | -- | -- | -- | -- | -- | -- | -- | | ||||||
| | - | - | - | - | - | - | - | Success | | | `-` | `-` | `-` | `-` | `-` | `-` | `-` | `SUCCESS` | | ||||||
|  | 
 | ||||||
|  | * Bit 0 (`SUCCESS`): When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token). | ||||||
| 
 | 
 | ||||||
| * `Bit 0`: When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token). |  | ||||||
| 
 | 
 | ||||||
| ### Example "conversation": | ### Example "conversation": | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -50,13 +50,14 @@ Any request will generate at least one corresponding response, with the exceptio | |||||||
| Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length: | Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length: | ||||||
| 
 | 
 | ||||||
| | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | | | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | | ||||||
| |--|--|--|--|--|--|--|--| | | -- | -- | -- | -- | -- | -- | -- | -- | | ||||||
| | Unlocked | Unlocking | - | - | - | - | Secure Failure | Success | | | `UNLOCKED` | `UNLOCK_IN_PROGRESS` | `-` | `-` | `-` | `-` | `SECURE_FAILURE` | `SUCCESS` | | ||||||
|  | 
 | ||||||
|  | * Bit 7 (`UNLOCKED`): When this bit is set, an _unlock sequence_ has completed, and _secure routes_ may be invoked. | ||||||
|  | * Bit 6 (`UNLOCK_IN_PROGRESS`): When this bit is set, an _unlock sequence_ is in progress. | ||||||
|  | * Bit 1 (`SECURE_FAILURE`): When this bit is set, the requested _route_ was marked _secure_ but an _unlock sequence_ has not completed. | ||||||
|  | * Bit 0 (`SUCCESS`): When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token). | ||||||
| 
 | 
 | ||||||
| * `Bit 7`: When this bit is set, an _unlock sequence_ has completed, and _secure routes_ may be invoked. |  | ||||||
| * `Bit 6`: When this bit is set, an _unlock sequence_ is in progress. |  | ||||||
| * `Bit 1`: When this bit is set, the requested _route_ was marked _secure_ but an _unlock sequence_ has not completed. |  | ||||||
| * `Bit 0`: When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token). |  | ||||||
| 
 | 
 | ||||||
| ### Example "conversation": | ### Example "conversation": | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -50,13 +50,14 @@ Any request will generate at least one corresponding response, with the exceptio | |||||||
| Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length: | Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length: | ||||||
| 
 | 
 | ||||||
| | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | | | Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 | | ||||||
| |--|--|--|--|--|--|--|--| | | -- | -- | -- | -- | -- | -- | -- | -- | | ||||||
| | Unlocked | Unlocking | - | - | - | - | Secure Failure | Success | | | `UNLOCKED` | `UNLOCK_IN_PROGRESS` | `-` | `-` | `-` | `-` | `SECURE_FAILURE` | `SUCCESS` | | ||||||
|  | 
 | ||||||
|  | * Bit 7 (`UNLOCKED`): When this bit is set, an _unlock sequence_ has completed, and _secure routes_ may be invoked. | ||||||
|  | * Bit 6 (`UNLOCK_IN_PROGRESS`): When this bit is set, an _unlock sequence_ is in progress. | ||||||
|  | * Bit 1 (`SECURE_FAILURE`): When this bit is set, the requested _route_ was marked _secure_ but an _unlock sequence_ has not completed. | ||||||
|  | * Bit 0 (`SUCCESS`): When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token). | ||||||
| 
 | 
 | ||||||
| * `Bit 7`: When this bit is set, an _unlock sequence_ has completed, and _secure routes_ may be invoked. |  | ||||||
| * `Bit 6`: When this bit is set, an _unlock sequence_ is in progress. |  | ||||||
| * `Bit 1`: When this bit is set, the requested _route_ was marked _secure_ but an _unlock sequence_ has not completed. |  | ||||||
| * `Bit 0`: When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token). |  | ||||||
| 
 | 
 | ||||||
| ### Example "conversation": | ### Example "conversation": | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,7 +16,8 @@ import_names = { | |||||||
|     # A mapping of package name to importable name |     # A mapping of package name to importable name | ||||||
|     'pep8-naming': 'pep8ext_naming', |     'pep8-naming': 'pep8ext_naming', | ||||||
|     'pyusb': 'usb.core', |     'pyusb': 'usb.core', | ||||||
|     'qmk-dotty-dict': 'dotty_dict' |     'qmk-dotty-dict': 'dotty_dict', | ||||||
|  |     'Jinja2': 'jinja2' | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| safe_commands = [ | safe_commands = [ | ||||||
|  | |||||||
| @ -1,10 +1,21 @@ | |||||||
| """This script handles the XAP protocol data files. | """This script handles the XAP protocol data files. | ||||||
| """ | """ | ||||||
| import re | import os | ||||||
| import hjson | import hjson | ||||||
|  | from jinja2 import Environment, FileSystemLoader, select_autoescape | ||||||
|  | from qmk.constants import QMK_FIRMWARE | ||||||
| from typing import OrderedDict | from typing import OrderedDict | ||||||
| 
 | 
 | ||||||
| from qmk.constants import QMK_FIRMWARE | 
 | ||||||
|  | def _get_jinja2_env(data_templates_xap_subdir: str): | ||||||
|  |     templates_dir = os.path.join(QMK_FIRMWARE, 'data', 'templates', 'xap', data_templates_xap_subdir) | ||||||
|  |     j2 = Environment(loader=FileSystemLoader(templates_dir), autoescape=select_autoescape()) | ||||||
|  |     return j2 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def render_xap_output(data_templates_xap_subdir, file_to_render, defs): | ||||||
|  |     j2 = _get_jinja2_env(data_templates_xap_subdir) | ||||||
|  |     return j2.get_template(file_to_render).render(xap=defs, xap_str=hjson.dumps(defs)) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def _merge_ordered_dicts(dicts): | def _merge_ordered_dicts(dicts): | ||||||
|  | |||||||
| @ -2,64 +2,7 @@ | |||||||
| """ | """ | ||||||
| import hjson | import hjson | ||||||
| from qmk.constants import QMK_FIRMWARE | from qmk.constants import QMK_FIRMWARE | ||||||
| from qmk.xap.common import get_xap_definition_files, update_xap_definitions | from qmk.xap.common import get_xap_definition_files, update_xap_definitions, render_xap_output | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def _update_type_docs(overall): |  | ||||||
|     defs = overall['type_docs'] |  | ||||||
| 
 |  | ||||||
|     type_docs = [] |  | ||||||
|     for (k, v) in sorted(defs.items(), key=lambda x: x[0]): |  | ||||||
|         type_docs.append(f'| _{k}_ | {v} |') |  | ||||||
| 
 |  | ||||||
|     desc_str = "\n".join(type_docs) |  | ||||||
| 
 |  | ||||||
|     overall['documentation']['!type_docs!'] = f'''\ |  | ||||||
| | Name | Definition | |  | ||||||
| | -- | -- | |  | ||||||
| {desc_str} |  | ||||||
| ''' |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def _update_term_definitions(overall): |  | ||||||
|     defs = overall['term_definitions'] |  | ||||||
| 
 |  | ||||||
|     term_descriptions = [] |  | ||||||
|     for (k, v) in sorted(defs.items(), key=lambda x: x[0]): |  | ||||||
|         term_descriptions.append(f'| _{k}_ | {v} |') |  | ||||||
| 
 |  | ||||||
|     desc_str = "\n".join(term_descriptions) |  | ||||||
| 
 |  | ||||||
|     overall['documentation']['!term_definitions!'] = f'''\ |  | ||||||
| | Name | Definition | |  | ||||||
| | -- | -- | |  | ||||||
| {desc_str} |  | ||||||
| ''' |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def _update_response_flags(overall): |  | ||||||
|     flags = overall['response_flags']['bits'] |  | ||||||
|     for n in range(0, 8): |  | ||||||
|         if str(n) not in flags: |  | ||||||
|             flags[str(n)] = {"name": "-", "description": "-"} |  | ||||||
| 
 |  | ||||||
|     header = '| ' + " | ".join([f'Bit {n}' for n in range(7, -1, -1)]) + ' |' |  | ||||||
|     dividers = '|' + "|".join(['--' for n in range(7, -1, -1)]) + '|' |  | ||||||
|     bit_names = '| ' + " | ".join([flags[str(n)]['name'] for n in range(7, -1, -1)]) + ' |' |  | ||||||
| 
 |  | ||||||
|     bit_descriptions = '' |  | ||||||
|     for n in range(7, -1, -1): |  | ||||||
|         bit_desc = flags[str(n)] |  | ||||||
|         if bit_desc['name'] != '-': |  | ||||||
|             desc = bit_desc['description'] |  | ||||||
|             bit_descriptions = bit_descriptions + f'\n* `Bit {n}`: {desc}' |  | ||||||
| 
 |  | ||||||
|     overall['documentation']['!response_flags!'] = f'''\ |  | ||||||
| {header} |  | ||||||
| {dividers} |  | ||||||
| {bit_names} |  | ||||||
| {bit_descriptions} |  | ||||||
| ''' |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def generate_docs(): | def generate_docs(): | ||||||
| @ -69,27 +12,18 @@ def generate_docs(): | |||||||
| 
 | 
 | ||||||
|     overall = None |     overall = None | ||||||
|     for file in get_xap_definition_files(): |     for file in get_xap_definition_files(): | ||||||
| 
 |  | ||||||
|         overall = update_xap_definitions(overall, hjson.load(file.open(encoding='utf-8'))) |         overall = update_xap_definitions(overall, hjson.load(file.open(encoding='utf-8'))) | ||||||
| 
 | 
 | ||||||
|         try: |         # Inject dummy bits for unspecified response flags | ||||||
|             if 'type_docs' in overall: |         for n in range(0, 8): | ||||||
|                 _update_type_docs(overall) |             if str(n) not in overall['response_flags']['bits']: | ||||||
|             if 'term_definitions' in overall: |                 overall['response_flags']['bits'][str(n)] = {'name': '', 'description': '', 'define': '-'} | ||||||
|                 _update_term_definitions(overall) |  | ||||||
|             if 'response_flags' in overall: |  | ||||||
|                 _update_response_flags(overall) |  | ||||||
|         except: |  | ||||||
|             print(hjson.dumps(overall)) |  | ||||||
|             exit(1) |  | ||||||
| 
 | 
 | ||||||
|         output_doc = QMK_FIRMWARE / "docs" / f"{file.stem}.md" |         output_doc = QMK_FIRMWARE / "docs" / f"{file.stem}.md" | ||||||
|         docs_list.append(output_doc) |         docs_list.append(output_doc) | ||||||
| 
 |         output = render_xap_output('docs', 'docs.md.j2', overall) | ||||||
|         with open(output_doc, "w", encoding='utf-8') as out_file: |         with open(output_doc, "w", encoding='utf-8') as out_file: | ||||||
|             for e in overall['documentation']['order']: |             out_file.write(output) | ||||||
|                 out_file.write(overall['documentation'][e].strip()) |  | ||||||
|                 out_file.write('\n\n') |  | ||||||
| 
 | 
 | ||||||
|     output_doc = QMK_FIRMWARE / "docs" / f"xap_protocol.md" |     output_doc = QMK_FIRMWARE / "docs" / f"xap_protocol.md" | ||||||
|     with open(output_doc, "w", encoding='utf-8') as out_file: |     with open(output_doc, "w", encoding='utf-8') as out_file: | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ colorama | |||||||
| fnvhash | fnvhash | ||||||
| hid | hid | ||||||
| hjson | hjson | ||||||
|  | Jinja2 | ||||||
| jsonschema>=3 | jsonschema>=3 | ||||||
| milc>=1.4.2 | milc>=1.4.2 | ||||||
| pygments | pygments | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Nick Brassel
						Nick Brassel