tools: improve `v check-md` by checking for broken TOC headline links (#10417)
							parent
							
								
									90d04b0ce6
								
							
						
					
					
						commit
						7983495c57
					
				| 
						 | 
					@ -9,6 +9,7 @@ import rand
 | 
				
			||||||
import term
 | 
					import term
 | 
				
			||||||
import vhelp
 | 
					import vhelp
 | 
				
			||||||
import v.pref
 | 
					import v.pref
 | 
				
			||||||
 | 
					import regex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	too_long_line_length = 100
 | 
						too_long_line_length = 100
 | 
				
			||||||
| 
						 | 
					@ -162,6 +163,7 @@ fn (mut f MDFile) progress(message string) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn (mut f MDFile) check() CheckResult {
 | 
					fn (mut f MDFile) check() CheckResult {
 | 
				
			||||||
	mut res := CheckResult{}
 | 
						mut res := CheckResult{}
 | 
				
			||||||
 | 
						mut anchor_data := AnchorData{}
 | 
				
			||||||
	for j, line in f.lines {
 | 
						for j, line in f.lines {
 | 
				
			||||||
		// f.progress('line: $j')
 | 
							// f.progress('line: $j')
 | 
				
			||||||
		if line.len > too_long_line_length {
 | 
							if line.len > too_long_line_length {
 | 
				
			||||||
| 
						 | 
					@ -187,8 +189,14 @@ fn (mut f MDFile) check() CheckResult {
 | 
				
			||||||
				res.errors++
 | 
									res.errors++
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							if f.state == .markdown {
 | 
				
			||||||
 | 
								anchor_data.add_links(j, line)
 | 
				
			||||||
 | 
								anchor_data.add_link_targets(j, line)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		f.parse_line(j, line)
 | 
							f.parse_line(j, line)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						anchor_data.check_link_target_match(f.path, mut res)
 | 
				
			||||||
	res += f.check_examples()
 | 
						res += f.check_examples()
 | 
				
			||||||
	return res
 | 
						return res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -234,6 +242,121 @@ fn (mut f MDFile) parse_line(lnumber int, line string) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Headline {
 | 
				
			||||||
 | 
						line  int
 | 
				
			||||||
 | 
						lable string
 | 
				
			||||||
 | 
						level int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Anchor {
 | 
				
			||||||
 | 
						line int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type AnchorTarget = Anchor | Headline
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct AnchorLink {
 | 
				
			||||||
 | 
						line  int
 | 
				
			||||||
 | 
						lable string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct AnchorData {
 | 
				
			||||||
 | 
					mut:
 | 
				
			||||||
 | 
						links   map[string][]AnchorLink
 | 
				
			||||||
 | 
						anchors map[string][]AnchorTarget
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn (mut ad AnchorData) add_links(line_number int, line string) {
 | 
				
			||||||
 | 
						query := r'\[(?P<lable>[^\]]+)\]\(\s*#(?P<link>[a-z\-]+)\)'
 | 
				
			||||||
 | 
						mut re := regex.regex_opt(query) or { panic(err) }
 | 
				
			||||||
 | 
						res := re.find_all_str(line)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for elem in res {
 | 
				
			||||||
 | 
							re.match_string(elem)
 | 
				
			||||||
 | 
							link := re.get_group_by_name(elem, 'link')
 | 
				
			||||||
 | 
							ad.links[link] << AnchorLink{
 | 
				
			||||||
 | 
								line: line_number
 | 
				
			||||||
 | 
								lable: re.get_group_by_name(elem, 'lable')
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn (mut ad AnchorData) add_link_targets(line_number int, line string) {
 | 
				
			||||||
 | 
						if line.trim_space().starts_with('#') {
 | 
				
			||||||
 | 
							if headline_start_pos := line.index(' ') {
 | 
				
			||||||
 | 
								headline := line.substr(headline_start_pos + 1, line.len)
 | 
				
			||||||
 | 
								link := create_ref_link(headline)
 | 
				
			||||||
 | 
								ad.anchors[link] << Headline{
 | 
				
			||||||
 | 
									line: line_number
 | 
				
			||||||
 | 
									lable: headline
 | 
				
			||||||
 | 
									level: headline_start_pos
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							query := r'<a\s*id=["\'](?P<link>[a-z\-]+)["\']\s*/>'
 | 
				
			||||||
 | 
							mut re := regex.regex_opt(query) or { panic(err) }
 | 
				
			||||||
 | 
							res := re.find_all_str(line)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for elem in res {
 | 
				
			||||||
 | 
								re.match_string(elem)
 | 
				
			||||||
 | 
								link := re.get_group_by_name(elem, 'link')
 | 
				
			||||||
 | 
								ad.anchors[link] << Anchor{
 | 
				
			||||||
 | 
									line: line_number
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn (mut ad AnchorData) check_link_target_match(fpath string, mut res CheckResult) {
 | 
				
			||||||
 | 
						mut checked_headlines := []string{}
 | 
				
			||||||
 | 
						mut found_error_warning := false
 | 
				
			||||||
 | 
						for link, linkdata in ad.links {
 | 
				
			||||||
 | 
							if link in ad.anchors {
 | 
				
			||||||
 | 
								checked_headlines << link
 | 
				
			||||||
 | 
								if ad.anchors[link].len > 1 {
 | 
				
			||||||
 | 
									found_error_warning = true
 | 
				
			||||||
 | 
									res.errors++
 | 
				
			||||||
 | 
									for anchordata in ad.anchors[link] {
 | 
				
			||||||
 | 
										eprintln(eline(fpath, anchordata.line, 0, 'multiple link targets of existing link (#$link)'))
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								found_error_warning = true
 | 
				
			||||||
 | 
								res.errors++
 | 
				
			||||||
 | 
								for brokenlink in linkdata {
 | 
				
			||||||
 | 
									eprintln(eline(fpath, brokenlink.line, 0, 'no link target found for existing link [$brokenlink.lable](#$link)'))
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for link, anchor_lists in ad.anchors {
 | 
				
			||||||
 | 
							if !(link in checked_headlines) {
 | 
				
			||||||
 | 
								if anchor_lists.len > 1 {
 | 
				
			||||||
 | 
									for anchor in anchor_lists {
 | 
				
			||||||
 | 
										line := match anchor {
 | 
				
			||||||
 | 
											Headline {
 | 
				
			||||||
 | 
												anchor.line
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											Anchor {
 | 
				
			||||||
 | 
												anchor.line
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										wprintln(wline(fpath, line, 0, 'multiple link target for non existing link (#$link)'))
 | 
				
			||||||
 | 
										found_error_warning = true
 | 
				
			||||||
 | 
										res.warnings++
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if found_error_warning {
 | 
				
			||||||
 | 
							eprintln('') // fix suppressed last error output
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn create_ref_link(s string) string {
 | 
				
			||||||
 | 
						query_remove := r'[^a-z \-]'
 | 
				
			||||||
 | 
						mut re := regex.regex_opt(query_remove) or { panic(err) }
 | 
				
			||||||
 | 
						return re.replace_simple(s.to_lower(), '').replace(' ', '-')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn (mut f MDFile) debug() {
 | 
					fn (mut f MDFile) debug() {
 | 
				
			||||||
	for e in f.examples {
 | 
						for e in f.examples {
 | 
				
			||||||
		eprintln('f.path: $f.path | example: $e')
 | 
							eprintln('f.path: $f.path | example: $e')
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								doc/docs.md
								
								
								
								
							
							
						
						
									
										20
									
								
								doc/docs.md
								
								
								
								
							| 
						 | 
					@ -83,7 +83,7 @@ For more details and troubleshooting, please visit the [vab GitHub repository](h
 | 
				
			||||||
* [Structs](#structs)
 | 
					* [Structs](#structs)
 | 
				
			||||||
    * [Embedded structs](#embedded-structs)
 | 
					    * [Embedded structs](#embedded-structs)
 | 
				
			||||||
    * [Default field values](#default-field-values)
 | 
					    * [Default field values](#default-field-values)
 | 
				
			||||||
    * [Short struct literal syntax](#short-struct-initialization-syntax)
 | 
					    * [Short struct literal syntax](#short-struct-literal-syntax)
 | 
				
			||||||
    * [Access modifiers](#access-modifiers)
 | 
					    * [Access modifiers](#access-modifiers)
 | 
				
			||||||
    * [Methods](#methods)
 | 
					    * [Methods](#methods)
 | 
				
			||||||
* [Unions](#unions)
 | 
					* [Unions](#unions)
 | 
				
			||||||
| 
						 | 
					@ -2270,7 +2270,7 @@ You can also install modules already created by someone else with [VPM](https://
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
v install [module]
 | 
					v install [module]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
###### Example:
 | 
					**Example:**
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
v install ui
 | 
					v install ui
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
| 
						 | 
					@ -2280,7 +2280,7 @@ Removing a module with v:
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
v remove [module]
 | 
					v remove [module]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
###### Example:
 | 
					**Example:**
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
v remove ui
 | 
					v remove ui
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
| 
						 | 
					@ -2290,7 +2290,7 @@ Updating an installed module from [VPM](https://vpm.vlang.io/):
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
v update [module]
 | 
					v update [module]
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
###### Example:
 | 
					**Example:**
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
v update ui
 | 
					v update ui
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
| 
						 | 
					@ -2305,7 +2305,7 @@ To see all the modules you have installed, you can use:
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
v list
 | 
					v list
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
###### Example
 | 
					**Example:**
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
> v list
 | 
					> v list
 | 
				
			||||||
Installed modules:
 | 
					Installed modules:
 | 
				
			||||||
| 
						 | 
					@ -2318,7 +2318,7 @@ outdated          Show installed modules that need updates.
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
v outdated
 | 
					v outdated
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
###### Example
 | 
					**Example:**
 | 
				
			||||||
```powershell
 | 
					```powershell
 | 
				
			||||||
> v outdated
 | 
					> v outdated
 | 
				
			||||||
Modules are up to date.
 | 
					Modules are up to date.
 | 
				
			||||||
| 
						 | 
					@ -4024,7 +4024,7 @@ created by the JS Backend (flag: `-b js`).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
`$` is used as a prefix for compile-time operations.
 | 
					`$` is used as a prefix for compile-time operations.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### $if
 | 
					#### `$if` condition
 | 
				
			||||||
```v
 | 
					```v
 | 
				
			||||||
// Support for multiple conditions in one branch
 | 
					// Support for multiple conditions in one branch
 | 
				
			||||||
$if ios || android {
 | 
					$if ios || android {
 | 
				
			||||||
| 
						 | 
					@ -4076,7 +4076,7 @@ Full list of builtin options:
 | 
				
			||||||
| `gnu`, `hpux`, `haiku`, `qnx` | `cplusplus`       | `big_endian`          |
 | 
					| `gnu`, `hpux`, `haiku`, `qnx` | `cplusplus`       | `big_endian`          |
 | 
				
			||||||
| `solaris` | | | |
 | 
					| `solaris` | | | |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### $embed_file
 | 
					#### `$embed_file`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```v ignore
 | 
					```v ignore
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
| 
						 | 
					@ -4099,7 +4099,7 @@ executable, increasing your binary size, but making it more self contained
 | 
				
			||||||
and thus easier to distribute. In this case, `f.data()` will cause *no IO*,
 | 
					and thus easier to distribute. In this case, `f.data()` will cause *no IO*,
 | 
				
			||||||
and it will always return the same data.
 | 
					and it will always return the same data.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### $tmpl for embedding and parsing V template files
 | 
					#### `$tmpl` for embedding and parsing V template files
 | 
				
			||||||
 | 
					
 | 
				
			||||||
V has a simple template language for text and html templates, and they can easily
 | 
					V has a simple template language for text and html templates, and they can easily
 | 
				
			||||||
be embedded via `$tmpl('path/to/template.txt')`:
 | 
					be embedded via `$tmpl('path/to/template.txt')`:
 | 
				
			||||||
| 
						 | 
					@ -4149,7 +4149,7 @@ numbers: [1, 2, 3]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### $env
 | 
					#### `$env`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```v
 | 
					```v
 | 
				
			||||||
module main
 | 
					module main
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -74,37 +74,37 @@ different capabilities:
 | 
				
			||||||
| structured data types     |     +     |   +   |     +    |          |
 | 
					| structured data types     |     +     |   +   |     +    |          |
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Strengths
 | 
					### Strengths
 | 
				
			||||||
#### default
 | 
					**default**
 | 
				
			||||||
- very fast
 | 
					- very fast
 | 
				
			||||||
- unlimited access from different coroutines
 | 
					- unlimited access from different coroutines
 | 
				
			||||||
- easy to handle
 | 
					- easy to handle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `mut`
 | 
					**`mut`**
 | 
				
			||||||
- very fast
 | 
					- very fast
 | 
				
			||||||
- easy to handle
 | 
					- easy to handle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `shared`
 | 
					**`shared`**
 | 
				
			||||||
- concurrent access from different coroutines
 | 
					- concurrent access from different coroutines
 | 
				
			||||||
- data type may be complex structure
 | 
					- data type may be complex structure
 | 
				
			||||||
- sophisticated access possible (several statements within one `lock`
 | 
					- sophisticated access possible (several statements within one `lock`
 | 
				
			||||||
  block)
 | 
					  block)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `atomic`
 | 
					**`atomic`**
 | 
				
			||||||
- concurrent access from different coroutines
 | 
					- concurrent access from different coroutines
 | 
				
			||||||
- reasonably fast
 | 
					- reasonably fast
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Weaknesses
 | 
					### Weaknesses
 | 
				
			||||||
#### default
 | 
					**default**
 | 
				
			||||||
- read only
 | 
					- read only
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `mut`
 | 
					**`mut`**
 | 
				
			||||||
- access only from one coroutine at a time
 | 
					- access only from one coroutine at a time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `shared`
 | 
					**`shared`**
 | 
				
			||||||
- lock/unlock are slow
 | 
					- lock/unlock are slow
 | 
				
			||||||
- moderately difficult to handle (needs `lock` block)
 | 
					- moderately difficult to handle (needs `lock` block)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#### `atomic`
 | 
					**`atomic`**
 | 
				
			||||||
- limited to single (max. 64 bit) integers (and pointers)
 | 
					- limited to single (max. 64 bit) integers (and pointers)
 | 
				
			||||||
- only a small set of predefined operations possible
 | 
					- only a small set of predefined operations possible
 | 
				
			||||||
- very difficult to handle correctly
 | 
					- very difficult to handle correctly
 | 
				
			||||||
| 
						 | 
					@ -191,3 +191,5 @@ are sometimes surprising. Each statement should be seen as a single
 | 
				
			||||||
transaction that is unrelated to the previous or following
 | 
					transaction that is unrelated to the previous or following
 | 
				
			||||||
statement. Therefore - but also for performance reasons - it's often
 | 
					statement. Therefore - but also for performance reasons - it's often
 | 
				
			||||||
better to group consecutive coherent statements in an explicit `lock` block.
 | 
					better to group consecutive coherent statements in an explicit `lock` block.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Channels
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,7 +23,7 @@ provides V language support for Visual Studio Code.
 | 
				
			||||||
[install V compiler](https://github.com/vlang/v/blob/master/doc/docs.md#install-from-source)
 | 
					[install V compiler](https://github.com/vlang/v/blob/master/doc/docs.md#install-from-source)
 | 
				
			||||||
on your operating system.
 | 
					on your operating system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Setup
 | 
					### Setup Extention
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Install [V VS Code Extention](https://marketplace.visualstudio.com/items?itemName=vlanguage.vscode-vlang).
 | 
					Install [V VS Code Extention](https://marketplace.visualstudio.com/items?itemName=vlanguage.vscode-vlang).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ for Visual Studio Code provides visual conditional debugging.
 | 
				
			||||||
[DWARF](https://en.wikipedia.org/wiki/DWARF) information to show and 
 | 
					[DWARF](https://en.wikipedia.org/wiki/DWARF) information to show and 
 | 
				
			||||||
edit the variable.
 | 
					edit the variable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Setup
 | 
					### Setup Debugging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
1. Install the [C/C++ Extention](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)
 | 
					1. Install the [C/C++ Extention](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)
 | 
				
			||||||
2. Open `RUN AND DEBUG` panel (Debug Icon in left panel).
 | 
					2. Open `RUN AND DEBUG` panel (Debug Icon in left panel).
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,11 @@
 | 
				
			||||||
This package is to generate data-driven HTML output.
 | 
					V allows for easily using text templates, expanded at compile time to
 | 
				
			||||||
 | 
					V functions, that efficiently produce text output. This is especially
 | 
				
			||||||
 | 
					usefull for templated HTML views, but the mechanism is general enough
 | 
				
			||||||
 | 
					to be used for other kinds of text output also.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Directives
 | 
					# Template directives
 | 
				
			||||||
Each directive begins with an `@` sign.
 | 
					Each template directive begins with an `@` sign.
 | 
				
			||||||
Some directives begin contains a `{}` block, others only have `''` (string) parameters.
 | 
					Some directives contain a `{}` block, others only have `''` (string) parameters.
 | 
				
			||||||
More on the directives itself.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Newlines on the beginning and end are ignored in `{}` blocks,
 | 
					Newlines on the beginning and end are ignored in `{}` blocks,
 | 
				
			||||||
otherwise this (see [if](#if) for this syntax):
 | 
					otherwise this (see [if](#if) for this syntax):
 | 
				
			||||||
| 
						 | 
					@ -12,17 +14,17 @@ otherwise this (see [if](#if) for this syntax):
 | 
				
			||||||
    <span>This is shown if bool_val is true</span>
 | 
					    <span>This is shown if bool_val is true</span>
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
would result in:
 | 
					... would output:
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <span>This is shown if bool_val is true</span>
 | 
					    <span>This is shown if bool_val is true</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
which could result in unreadable output.
 | 
					... which is less readable.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## if
 | 
					## if
 | 
				
			||||||
The if directive consists of three parts, the `@if` tag, the condition (same syntax like in V)
 | 
					The if directive, consists of three parts, the `@if` tag, the condition (same syntax like in V)
 | 
				
			||||||
and the `{}` block where you can write html which will be rendered if the condition is true:
 | 
					and the `{}` block, where you can write html, which will be rendered if the condition is true:
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
@if <condition> {}
 | 
					@if <condition> {}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
| 
						 | 
					@ -42,19 +44,20 @@ The first example would result in:
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
    <span>This is shown if bool_val is true</span>
 | 
					    <span>This is shown if bool_val is true</span>
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
while the one-liner results in:
 | 
					... while the one-liner results in:
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<span>This is shown if bool_val is true</span>
 | 
					<span>This is shown if bool_val is true</span>
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## for
 | 
					## for
 | 
				
			||||||
The for directive consists of three parts, the `@for` tag, the condition (same syntax like in V)
 | 
					The for directive consists of three parts, the `@for` tag,
 | 
				
			||||||
and the `{}` block where you can write html which will be rendered for each loop:
 | 
					the condition (same syntax like in V) and the `{}` block,
 | 
				
			||||||
 | 
					where you can write text, rendered for each iteration of the loop:
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
@for <condition> {}
 | 
					@for <condition> {}
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Example
 | 
					### Example for @for
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
@for i, val in my_vals {
 | 
					@for i, val in my_vals {
 | 
				
			||||||
    <span>$i - $val</span>
 | 
					    <span>$i - $val</span>
 | 
				
			||||||
| 
						 | 
					@ -72,7 +75,7 @@ The first example would result in:
 | 
				
			||||||
    <span>2 - "Third"</span>
 | 
					    <span>2 - "Third"</span>
 | 
				
			||||||
    ...
 | 
					    ...
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
while the one-liner results in:
 | 
					... while the one-liner results in:
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
<span>0 - "First"</span>
 | 
					<span>0 - "First"</span>
 | 
				
			||||||
<span>1 - "Second"</span>
 | 
					<span>1 - "Second"</span>
 | 
				
			||||||
| 
						 | 
					@ -92,8 +95,7 @@ The include directive is for including other html files (which will be processed
 | 
				
			||||||
and consists of two parts, the `@include` tag and a following `'<path>'` string.
 | 
					and consists of two parts, the `@include` tag and a following `'<path>'` string.
 | 
				
			||||||
The path parameter is relative to the `/templates` directory in the corresponding project.
 | 
					The path parameter is relative to the `/templates` directory in the corresponding project.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Example
 | 
					### Example for the folder structure of a project using templates:
 | 
				
			||||||
Files
 | 
					 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
Project root
 | 
					Project root
 | 
				
			||||||
/templates
 | 
					/templates
 | 
				
			||||||
| 
						 | 
					@ -117,11 +119,11 @@ where you can insert your src
 | 
				
			||||||
@js '<url>'
 | 
					@js '<url>'
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### Example
 | 
					### Example for the @js directive:
 | 
				
			||||||
```html
 | 
					```html
 | 
				
			||||||
@js 'myscripts.js'
 | 
					@js 'myscripts.js'
 | 
				
			||||||
```
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Variables
 | 
					# Variables
 | 
				
			||||||
All variables which are declared before can be used through the `@{my_var}` syntax.
 | 
					All variables, which are declared before the $tmpl can be used through the `@{my_var}` syntax.
 | 
				
			||||||
It's also possible to use properties of structs here like `@{my_struct.prop}`.
 | 
					It's also possible to use properties of structs here like `@{my_struct.prop}`.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue