Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update variables documentation #1203

Merged
merged 1 commit into from
Jun 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/userGuide/siteConfiguration.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ To turn off the option, add the following to `site.json` -

#### **`timeZone`**

**Time zone of the [time stamp](reusingContents.html#built-in-variable-timestamp).** Default: `"UTC"`.
**Time zone of the [time stamp](reusingContents.html#built-in-global-variables).** Default: `"UTC"`.

<panel type="minimal" header="Time Zone Options">
<include src="pages/timeZones.md" />
Expand All @@ -226,7 +226,7 @@ To turn off the option, add the following to `site.json` -

#### **`locale`**

**Language by locale used for the [time stamp](reusingContents.html#built-in-variable-timestamp).** Default: `"en-GB"` (`English (United Kingdom)`). <br>
**Language by locale used for the [time stamp](reusingContents.html#built-in-global-variables).** Default: `"en-GB"` (`English (United Kingdom)`). <br>
The date format is thus - <br>
`<Day>, <Date> <Month> <Year>, <24-hour Time> <Time Zone Code>`.

Expand Down
234 changes: 112 additions & 122 deletions docs/userGuide/syntax/variables.mbdf
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@

**Global variables are to be defined in the `_markbind/variables.md` file.** Each variable must have an `name` and the value can be any MarkBind-compliant code fragment. The `name` should not contain `-` and `.`. For example, `search-option` and `search.options` are not allowed.

The variables declared here are available from anywhere in the code base.

<div class="indented">

{{ icon_example }} Here's how you can define two variables `year` and `options`:

```html
```html {.no-line-numbers}
<variable name="year">2018</variable>

<variable name="options">
Expand All @@ -32,63 +34,30 @@ To include a variable value in your code, give the variable id enclosed in doubl

<div class="indented">

{{ icon_example }} Here's how you can use the variable `year`:

<code>The year was {<span></span>{ year }}.</code> {{ icon_arrow_right }} The year was 2018.
{{ icon_example }} `The year was {% raw %}{{ year }}{% endraw %}.` {{ icon_arrow_right }} The year was 2018.

</div>

==MarkBind variables are _global_==; they are available from anywhere in the code base.

**MarkBind provides a number of built-in variables.**


### Built-in Global Variables

##### Built-in Variable: `baseUrl`

Represents the root directory of the project. Used for specifying intra-site links.

<panel type="seamless" header="User Guide: MarkBind Syntax → Intra-Site Links">
<include src="links.mbdf#intraSiteLinks" />
</panel>


##### Built-in Variable: `timestamp`
#### Default values for variables

<code>{<span></span>{ timestamp }}</code> is the time stamp that indicates when the page was generated.

The default values of `"timeZone"` and `"locale"` are `"UTC"` and `"en-GB"` respectively. The following example showcases the use of the `"Asia/Singapore"` time zone.
You can also specify a default value for a variable, which is displayed when the variable is not specified in `variables.md` and by any of the [includes]({{ baseUrl }}/userGuide/reusingContents.html#the-include-tag) of the page. This is done by adding `or defaultValue` within the curly braces.

<div class="indented">

{{ icon_example }} <code>Page generated at: {<span></span>{ timestamp }}</code> {{ icon_arrow_right }} Page generated at: {{ timestamp }}
{{ icon_example }} `My name is {% raw %}{{ name or "Anonymous" }}{% endraw %}.` {{ icon_arrow_right }} My name is Anonymous.
</div>

<p/>


##### Built-in Variable: `MarkBind`

<code>{<span></span>{MarkBind}}</code> represents a code snippet that specifies the MarkBind version in use and is linked to the MarkBind website.

<div class="indented">

{{ icon_example }} <code>Page generated by: {<span></span>{ MarkBind }}</code> {{ icon_arrow_right }} Page generated by: {{ MarkBind }}
</div>

<p/>
#### Built-in Global Variables

MarkBind also provides a number of built-in variables.

##### Variables: Defaults

You can specify a default value for a variable, which is displayed when the variable is not specified in `variables.md` and by any of the [includes]({{ baseUrl }}/userGuide/reusingContents.html#the-include-tag) of the page. This is done by adding `or defaultValue` within the curly braces.

<div class="indented">

{{ icon_example }} If `name` is not declared in `variables.md`:<br>
<code>My name is {<span></span>{ name or "Anonymous" }}.</code> {{ icon_arrow_right }} My name is Anonymous.
</div>
Variable | Notes | {{ icon_example }} | Output
--- | --- | --- | ---
`baseUrl` | Represents the root directory of the site on the server, as configured in your [site configuration]({{baseUrl}}/userGuide/siteConfiguration.html#baseurl) file. <br> Used for specifying [intra-site links](links.mbdf#intraSiteLinks"). | If `baseUrl` is specified as `userGuide/`:<br><br> `<img src="{% raw %}{{baseUrl}}{% endraw %}/images/logo.png" />` | `<img src="userGuide/images/logo.png" />`
`timestamp` | The time stamp that indicates when the page was generated. <br><br> The [default]({{baseUrl}}/userGuide/siteConfiguration.html#timezone) values of `"timeZone"` and `"locale"` are `"UTC"` and `"en-GB"` respectively. | The following example showcases the use of the `"Asia/Singapore"` time zone.<br><br> `Page generated at: {% raw %}{{timestamp}}{% endraw %}` | `Page generated at: {{ timestamp }}`
`MarkBind` | The MarkBind version in use, linked to the MarkBind website. | `Page generated by: {% raw %}{{MarkBind}}{% endraw %}` | `Page generated by:` {{ MarkBind | safe }}


### Page Variables
Expand All @@ -97,78 +66,96 @@ You can specify a default value for a variable, which is displayed when the vari

<div class="indented">

{{ icon_example }} Declaring page variables:<br>
{{ icon_example }} Declaring page variables: `<variable name="full_name">John Doe</variable>`<br>

`<variable name="full_name">John Doe</variable>`<br>
<code>My name is {<span></span>{ full_name }}. This is {<span></span>{ full_name }}'s site.</code>
{{ icon_example }} Using page variables: `My name is {% raw %}{{ full_name }}. This is {{ full_name }}{% endraw %}'s site.`
</div>

Note: These variables will not be applied to [`<include>` files]({{ baseUrl }}/userGuide/reusingContents.html#the-include-tag). Additionally, global variables (`_markbind/variables.md`) will take precedence over any page variables. *See also: [Specifying Variables in an `<include>`]({{ baseUrl }}/userGuide/reusingContents.html#specifying-variables-in-an-include)*.
<box type="warning">

These variables will not be applied to [`<include>` files]({{ baseUrl }}/userGuide/reusingContents.html#the-include-tag). Additionally, global variables (`_markbind/variables.md`) will take precedence over any page variables. *See also: [Specifying Variables in an `<include>`]({{ baseUrl }}/userGuide/reusingContents.html#specifying-variables-in-an-include)*.
</box>


### Importing Variables

**You can access [page variables](#page-variables) from another page by importing them.**

<div class="indented">

{{ icon_example }} Importing specific variables from `person.md` into `coverpage.md`:
`person.md`:
```html

In `person.md`,
```html {.no-line-numbers}
<variable name="address">123 Sun Avenue</variable>
<variable name="name">Mark</variable>
<variable name="phone">123456789</variable>
```

`coverpage.md`:
and in `coverpage.md`,

```html
```html {.no-line-numbers}
<import address name from="person.md"/>
```

will allow you to access the variables as per normal: <code>{<span></span>{address}}</code>, <code>{<span></span>{name}}</code>, <code>{<span></span>{phone}}</code>.
{% raw %}will allow you to access the variables as per normal: `{{address}}`, `{{name}}`, `{{phone}}`.{% endraw %}

---
</div>

**When importing all variables, you should attach a _namespace_** to the imported variables using an `as` attributes.

<div class="indented">

{{ icon_example }} Importing all variables with namespaces:

{{ icon_example }}:
`coverpage.md`:
```html
In `coverpage.md`,
```html {.no-line-numbers}
<import from="page.md" as="details"/>
```

{% raw %}

| Detail | How to access
| :------------- |:-------------
| address | <code>{<span></span>{details.address}}</code>
| name | <code>{<span></span>{details.<span></span>name}}</code>
| phone | <code>{<span></span>{details.phone}}</code>

This way, ***all*** variables in `page.md` are accessible via <code>{<span></span>{details.&lt;variable_name&gt;}}</code>.

Note that in this case, `details` is treated as the variable name and so is subject to the same rules as other variables, such as global variables taking precedence, and multiple imports to the same namespace being impossible:
| address | `{{details.address}}`
| name | `{{details.name}}`
| phone | `{{details.phone}}`

```html
<import from="title.md" as="book"/>
<import from="index.md" as="book"/>
```
This way, ***all*** variables in `page.md` are accessible via `{{details.<variable_name>}}`.
{% endraw %}

In this case, all the variables in `title.md` are not accessible, as they are overwritten with the variables from `index.md`.

<box type="important">
</div>

Note that global variables (`_markbind/variables.md`) and [page variables](#page-variables) will take precedence over any imported variables.
<box type="warning" header="Mixing namespaces with variable names">

While you can mix the two syntaxes for importing page variables, it may get confusing:
```html
You can also mix the two syntaxes for importing page variables, though it is not recommended:
```html {.no-line-numbers}
<import address name from="page.md" as="details"/>
```

This may seem like it will import *only* `address` and `name` from `page.md` and storing them in the namespace `details`.

However, this is a combination of *both* syntaxes above, and thus this will allow you to:

- access `address` and `name` (but NOT `phone`) with <code>{<span></span>{address}}</code> and <code>{<span></span>{name}}</code>
- access `address`, `name`, and `phone` with <code>{<span></span>{details.address}}</code>, <code>{<span></span>{details.<span></span>name}}</code>, and <code>{<span></span>{details.phone}}</code>
{% raw %}
- access `address` and `name` (but NOT `phone`) with `{{address}}` and `{{name}}`
- access `address`, `name`, and `phone` with `{{details.address}}`, `{{details.name}}`, and `{{details.phone}}`
{% endraw %}

</box>

<box type="important" header="Precedence of imported variables">

Note that global variables (`_markbind/variables.md`) and [page variables](#page-variables) will take precedence over any imported variables.

This also applies for namespaces {{ icon_arrow_right }} for instance, in the earlier example, `details` is treated as the variable name and is subject to the same rules as other variables, such as global variables taking precedence, and later declarations overriding previous ones:

```html {.no-line-numbers}
<import from="title.md" as="book"/>
<import from="index.md" as="book"/>
```

In this case, all the variables in `title.md` are not accessible, as they are overwritten with the variables from `index.md`.

</box>

Expand All @@ -178,12 +165,12 @@ You could also have your variables defined in a JSON file to define multiple var

{{ icon_example }}
`variables.md`:
```html
```html {.no-line-numbers}
<variable from="variables.json" />
```

`variables.json`:
```json
```json {.no-line-numbers}
{
"variable1": "This is the first variable",
"variable2": "This is the second variable"
Expand All @@ -192,70 +179,73 @@ You could also have your variables defined in a JSON file to define multiple var

Variables defined in JSON file will be scoped according to where it is being referenced.

### Variables: Tips and Tricks

**Variables can refer to other variables** that are declared earlier, including built-in variables.
### Tips and Tricks for variables

<div class="indented">
<br>
<box type="success" seamless header="##### Referring to other variables in variables">

{{ icon_example }} This variable uses a built-in variable:<br>
`<variable name="time">`<code>{<span></span>{ timestamp }}</code>`</variable>`
{% raw %}
This variable uses a built-in variable:<br>
`<variable name="time">{{ timestamp }}</variable>`

Here, the second variable will be assigned the contents of the first variable.<br>
`<variable name="first">`<code>This is the first variable.</code>`</variable>`<br>
`<variable name="second">`<code>{<span></span>{ first }}</code>`</variable>`<br>
`<variable name="first">This is the first variable.</variable>`<br>
`<variable name="second">{{ first }}</variable>`<br>

This will not work, as the `fourth` variable is declared _below_ the line that refers to it.<br>
`<variable name="third">`<code>{<span></span>{ fourth }}</code>`</variable>` :x:<br>
`<variable name="fourth">`<code>This is the fourth variable.</code>`</variable>`
</div>
`<variable name="third">{{ fourth }}</variable>` :x:<br>
`<variable name="fourth">This is the fourth variable.</variable>`
{% endraw %}

</box>
<br>
<box type="success" seamless header="##### Variables can contain malformed html">

Note that if the variable being referenced contains HTML tags, MarkBind may escape the tags and render it literally.
MarkBind uses a patched version of the excellent [htmlparser2](https://github.com/fb55/htmlparser2) that allows `<variable>` tags
to contain any content - even incomplete or malformed html!

<div class="indented">
{{ icon_example }} You can use this to build html from incomplete html code snippets:

{{ icon_example }} If we declare the variables as follows,<br>
```html {.no-line-numbers}
<variable name="front_center"><div style="text-align: center;"></variable>
<variable name="front_right"><div style="text-align: right;"></variable>
<variable name="back"></div></variable>
```

`<variable name="note">`<code>\<span style="color: blue">Note: \</span></code>`</variable>`<br>
`<variable name="note_2">`<code>{<span></span>{ note }}</code>`</variable>`<br>
`<variable name="const_note">`<code>{<span></span>{ note_2 }} This is a constant.</code>`</variable>`
And to use it:

the result will be,<br>
<variable name="front_center"><div style="text-align: center;"></variable>
<variable name="front_right"><div style="text-align: right;"></variable>

<code>{<span></span>{ const_note }}</code> :fas-arrow-right: \<span style="color: blue">Note: \</span> This is a constant.
</div>
<variable name="back"></div></variable>

You must use the `safe` filter when using such variables:
{{ icon_example }}
{% raw %}`{{ front_center | safe }} centered {{ back | safe }}`{% endraw %} {{icon_arrow_right}} {.my-2}

<div class="indented">
<box border-left-color="grey" background-color="white">
{{ front_center | safe }} centered {{ back | safe }}
</box>
</div>

{{ icon_example }} If we use the safe filter for the second variable:<br>

`<variable name="note">`<code>\<span style="color: blue">Note: \</span></code>`</variable>`<br>
`<variable name="note_2">`<code>{<span></span>{ note | safe }}</code>`</variable>`<br>
`<variable name="const_note">`<code>{<span></span>{ note_2 }} This is a constant.</code>`</variable>`
{{ icon_example }}
{% raw %}`{{ front_right | safe }} right aligned {{ back | safe }}`{% endraw %} {{icon_arrow_right}} {.my-2}

<code>{<span></span>{ const_note }}</code> :fas-arrow-right: <span style="color: blue">Note: </span> This is a constant.
<div class="indented">
<box border-left-color="grey" background-color="white">
{{ front_right | safe }} right aligned {{ back | safe }}
</box>
</div>

When defining variables with incomplete HTML fragments, we can define variables as a separate JSON file.
<box type="warning">

{{ icon_example }} variables containing HTML fragments:<br>

`index.md`:
```html
<variable from="variableFileName.json" />
```

`variableFileName.json`:
```json
{
"back_fragment": "Back</div>",
"front_fragment": "<div>Front"
}
```
Remember to also use the `safe` nunjucks filter when rendering your variables as raw html!
</box>
</box>

<code>{<span></span>{ front_fragment }}</code> and <code>{<span></span>{ back_fragment }}</code> :fas-arrow-right: Front and Back
</span>

<span id="short" class="d-none">

Expand All @@ -266,12 +256,12 @@ Global variables:
<variable name="year">2018</span>
```

<code>The year was {<span></span>{ year }}.</code>
`The year was {% raw %}{{ year }}{% endraw %}.`

Page variables:<br>
`<variable name="full_name">John Doe</variable>`{.html}

<code>The name was {<span></span>{ full_name }}.</code>
`The name was {% raw %}{{ full_name }}{% endraw %}.`


</span>