• HOME
  • USER GUIDE
  • SHOWCASE
  • ABOUT
  • User Guide → Reusing Contents

    Reusing Contents

    MarkBind is highly-optimized for content reuse. It offers several mechanisms to provide readers with many variations of the content while minimizing duplication at source file level. As a result, instead of creating a one-size-fits-all site, MarkBind can create a site in which readers can chart their own path of reading.

    User Guide → Reusing Contents → Variables

    Variables

    MarkBind variables are ideal for reusing small bits of code in multiple places; you can define a variable to represent the code bit in question and reuse it anywhere in the site by referring the variable instead of duplicating the code bit.

    Global Variables

    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.

    Example Here's how you can define two variables year and options:

    <variable name="year">2018</variable>
    
    <variable name="options">
    * yes
    * no
    * maybe
    </variable>
    

    To include a variable value in your code, give the variable id enclosed in double curly braces.

    Example The year was {{ year }}. The year was 2018.

    Default values for variables

    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 of the page. This is done by adding or defaultValue within the curly braces.

    Example My name is {{ name or "Anonymous" }}. My name is Anonymous.

    Built-in Global Variables

    MarkBind also provides a number of built-in variables.

    Variable Notes Example Output
    baseUrl Represents the root directory of the site on the server, as configured in your site configuration file.
    Used for specifying intra-site links.
    If baseUrl is specified as userGuide/:

    <img src="{{baseUrl}}/images/logo.png" />
    <img src="userGuide/images/logo.png" />
    timestamp 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.

    Page generated at: {{timestamp}}
    Page generated at: Fri, Mar 19, 2021, 2:24:17 PM UTC
    MarkBind The MarkBind version in use, linked to the MarkBind website. Page generated by: {{MarkBind}} Page generated by: MarkBind 2.18.1

    Page Variables

    You can also declare variables for use within a single page. These variables work exactly the same as regular variables, except that their values only apply to the page they are declared in. This can be done by using the <variable> tag.

    Example Declaring page variables: <variable name="full_name">John Doe</variable>

    Example Using page variables: My name is {{ full_name }}. This is {{ full_name }}'s site.

    These variables will not be applied to <include> files. Additionally, global variables (_markbind/variables.md) will take precedence over any page variables. See also: Specifying Variables in an <include>.

    Importing Variables

    You can access page variables from another page by importing them.

    Example Importing specific variables from person.md into coverpage.md:

    In person.md,

    <variable name="address">123 Sun Avenue</variable>
    <variable name="name">Mark</variable>
    <variable name="phone">123456789</variable>
    

    and in coverpage.md,

    <import address name from="person.md"/>
    

    will allow you to access the variables as per normal: {{address}}, {{name}}, {{phone}}.

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

    Example Importing all variables with namespaces:

    In coverpage.md,

    <import from="page.md" as="details"/>
    
    Detail How to access
    address {{details.address}}
    name {{details.name}}
    phone {{details.phone}}

    This way, all variables in page.md are accessible via {{details.<variable_name>}}.

    You can also mix the two syntaxes for importing page variables, though it is not recommended:

    <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 {{address}} and {{name}}
    • access address, name, and phone with {{details.address}}, {{details.name}}, and {{details.phone}}

    Note that global variables (_markbind/variables.md) and page variables will take precedence over any imported variables.

    This also applies for namespaces 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:

    <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.

    Importing variables from other external file formats

    You can also source variables from external files using MarkBind's {% ext varName = "filepathToFile" %} Nunjucks extension. This is useful if you have external datasets you want to display in your site!

    To do so, assign a root variable name (varName) to the file path from the similar to how you assign filepaths for other Nunjucks tagsroot directory of the site. You may then access the file's variables using dot varName.xx or array varName[i] syntax, depending on the file's contents.

    Example

    CODE:

    Displaying a student scoreboard stored as JSON
    {% ext studentScoreboard = "userGuide/syntax/extra/scoreboard.json" %}
    
    Student Number | Score | Rank
    :----- | :-------: | ----
    {% for student in studentScoreboard.students -%}
    {{ student.number }} | {{ student.score }} | {{ student.rank }}
    {% endfor %}
    
    <small>Last updated at {{ studentScoreboard.lastUpdated }}</small>
    
    Json File
    {
      "lastUpdated": "21 November, 2020",
      "students": [
        {
          "number": "A1234567X",
          "score": 87,
          "rank": 1
        },
        {
          "number": "A1234123U",
          "score": 60,
          "rank": 3
        },
        {
          "number": "A9876543L",
          "score": 76,
          "rank": 2
        }
      ]
    }
    

    OUTPUT:

    Student Number Score Rank
    A1234567X 87 / 100 1
    A1234123U 60 / 100 3
    A9876543L 76 / 100 2

    Last updated at 21 November, 2020

    Only .json files are supported for now.

    You could also have your variables defined in a JSON file to define multiple variables in a more concise manner.

    Example globally scoped variables variables.md:

    <variable from="PATH_TO_VARIABLE.json" />
    

    variables.json:

    {
      "variable1": "This is the first variable",
      "variable2": "This is the second variable"
    }
    

    Variables defined in a .json file will be scoped according to where it is being referenced. Json variables referenced in variables.md would be globally scoped like other global variables in that file.

    Example locally scoped variables in index.md:

    <variable from="PATH_TO_VARIABLE.json" />
    

    In this case, json variables referenced within index.md would be a page variable accessible within the page index.md.

    Tips and Tricks for variables


    This variable uses a built-in variable:
    <variable name="time">{{ timestamp }}</variable>

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

    This will not work, as the fourth variable is declared below the line that refers to it.
    <variable name="third">{{ fourth }}</variable>
    <variable name="fourth">This is the fourth variable.</variable>


    MarkBind uses a patched version of the excellent htmlparser2 that allows <variable> tags to contain any content - even incomplete or malformed html!

    Example You can use this to build html from incomplete html code snippets:

    <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>
    

    And to use it:

    Example {{ front_center | safe }} centered {{ back | safe }}

    centered

    Example {{ front_right | safe }} right aligned {{ back | safe }}

    right aligned

    Remember to also use the safe nunjucks filter when rendering your variables as raw html!

    Global variables:

    _markbind/variables.md:

    <variable name="year">2018</span>
    

    The year was {{ year }}.

    Page variables:
    <variable name="full_name">John Doe</variable>

    The name was {{ full_name }}.


    User Guide → Reusing Contents → Includes

    Includes

    MarkBind has a powerful <include> mechanism which allows you to create documents by combining other content fragments.

    You can use <include> tag to include another markdown or HTML document into the current document.

    Example Including text from a tip2.md in another file.

    Tip 1. ...
    <include src="tips/tip2.md" />
    Tip 3. ...
    

    You can <include> a fragment of a file by specifying the #fragment-id at the end of the src attribute value, provided the fragment is wrapped in a <div>/<span>/<seg> tag with the matching id.

    Example Including a fragment from a file:

    Some text
    <include src="docs/tips.md#tip-1" />
    Some other text
    

    docs/tips.md:

    ...
    <div id="tip-1" />
      Tip 1. ...
      ...
    </div>
    Tip 2. ...
    

    When setting the id of a fragment, be careful not to clash with heading anchor IDs auto-generated by MarkBind. For example, if you have a heading ## Some Useful Tips, MarkBind will auto-generate an ID some-useful-tips for that heading.

    The <include> tag works for any MarBind source file including the font matter section but it may not work in some special files such as the _markbind/variables.md.

    Attributes:

    • src: specify the source file path.
    • inline (optional): make the included result an inline element. (wrapped in <span> tag). e.g.,
      The title is <include src="../docs/summary.md#title" inline /> while ...
      
    • optional (optional): include the file/fragment only if it exists i.e., there will be no error message if the file/fragment does not exist. e.g.,
      <include src="UserStories.md" optional />
      
    • trim (optional): remove leading and trailing whitespace and newlines from the document before including.
      <include src="UserStories.md#epic" trim />
      

    The <include> mechanism can be used inside any MarkBind source file (even inside the front matter section) but it will not work inside some special files such as the _markbind/variables.md.

    <include> Inside an Included File

    Although the src attribute of an <include> is given relative to the current directory, it is converted to an absolute value before the i.e., the file containing the <include>host file is included from another file.

    Example Suppose you have a MarkBind project with the following file structure.

    c:/mySite/
      ├── bookFiles/
      |      ├── book.md
      |      ├── chapter1.md
      |      └── chapter2.md
      └── reviewFiles/
             └── review.md
    

    The book.md:

    # My Book
    <include src="chapter1.md" />
    <include src="chapter2.md" />
    

    The review.md:

    # My Review
    <include src="../bookFiles/book.md" />
    ...
    

    The content of the chapter1.md and chapter2.md will be included in the review.md (via <include src="../bookFiles/book.md" />) although chapter1.md and chapter2.md are not in reviewFiles directory. i.e., <include src="chapter1.md" /> will be interpreted as <include src="c:/mySite/bookFiles/chapter1.md" />

    In other words, <include> interprets the reused code relative to the original location of the file, not the location in which it is reused.


    Specifying Variables in an <include>

    It is possible to include variables in an <include>.

    Example Specifying title and author variables in an <include> tag:

    <include src="article.md">
      <variable name="title">My Title</variable>
      <variable name="author">John Doe</variable>
    </include>
    

    In article.md:

    # {{ title }}<br>
    Author: {{ author }}
    

    These variables work the same way as variables in _markbind/variables.md, except that they only apply to the included file. They allow the included file to be reused as a template, for different source files using different variable values.

    You can also specify include variables within the <include> tag itself by adding a var- prefix.

    Example Specifying title and author variables inline:

    <include src="article.md" var-title="My Title" var-author="John Doe" />
    

    If the same variable is defined in a chain of <include>s (e.g. a.md includes b.md includes c.md...), variables defined in the top-most <include> will take precedence. Global variables (_markbind/variables.md) will take precedence over any <include> variables.

    Using Boilerplate Files

    If you find duplicating a code that needs to stay relative to the directory in which it usedboilerplate code fragment in multiple places of your code base, you can use a boilerplate file to avoid such duplication. Note that you cannot use a normal <include> in this case because the code included using a normal <include> stays relative to the original location while boilerplate code needs to be interpreted relative to the location it is being used.

    Example Suppose you have a MarkBind project with the following file structure.

    c:/mySite/
      ├── chapter1/
      |      ├── chapter.md
      |      ├── text.md
      |      └── exercises.md
      ├── chapter2/
      |      ├── chapter.md
      |      ├── text.md
      |      └── exercises.md
      └── book.md
    

    The book.md:

    # My Book
    <include src="chapter1/chapter.md" />
    <include src="chapter2/chapter.md" />
    

    The chapter1/chapter.md:

    ## Text
    <include src="text.md" />
    ## Exercises
    <include src="exercises.md" />
    

    The chapter2/chapter.md:

    ## Text
    <include src="text.md" />
    ## Exercises
    <include src="exercises.md" />
    

    As you can see, both chapter.md files are exactly the same. If we were to use only one of the chapter.md files and <include> it twice in the book.md, we'll end up with the same chapter content duplicated twice, which is not what we want. In other words, chapter.md contains boilerplate code that needs to be interpreted relative to where it is applied, once relative to chapter1 directory and once relative to chapter2 directory.

    To use a code fragment as a boilerplate file,

    1. Put the code in a file inside the _markbind/boilerplates directory.
    2. <include> the file as if a copy of it exists in any directory you want it to applied, but add the boilerplate attribute to the <include> tag.

    Example Here's how you can use a boilerplate file to avoid duplicating the chapter.md:

    c:/mySite/
      ├── _markbind/boilerplates/
      |      └── chapter.md
      ├── chapter1/
      |      ├── text.md
      |      └── exercises.md
      ├── chapter2/
      |      ├── text.md
      |      └── exercises.md
      └── book.md
    

    The book.md:

    # My Book
    <include src="chapter1/chapter.md" boilerplate />
    <include src="chapter2/chapter.md" boilerplate />
    

    The _markbind/boilerplates/chapter.md:

    ## Text
    <include src="text.md" />
    ## Exercises
    <include src="exercises.md" />
    

    Consider the line <include src="chapter1/chapter.md" boilerplate />. Note how you can use src="chapter1/chapter.md" there is no such file. MarkBind will use the chapter.md file /_markbind/boilerplates/ but interpret it as if the file exist in chapter1 directory (i.e., interpret the chapter1.md code relative to the chapter1 directory.

    Similarly, <include src="chapter2/chapter.md" boilerplate /> interprets the chapter.md relative to the chapter2 directory.

    If you have many boilerplate files, you can organize them into directories inside the _markbind directory. When using such boilerplate files, you need to replace boilerplate attribute with boilerplate="<path to file relative to _markbind/boilerplates>".

    Example Suppose the chapter.md is places in a book directory:

    c:/mySite/
      └── _markbind/boilerplates/
             └── book/
                   └── chapter.md
    
    

    It needs to be used as follows:

    <include src="chapter1/chapter.md" boilerplate="book/chapter.md" />
    <include src="chapter2/chapter.md" boilerplate="book/chapter.md" />
    
    <include src="foo.md#bar" boilerplate inline trim>
      <variable name="x">5</variable>
    </include>
    

    Reusing Contents Across Sites

    MarkBind supports reusing across sites. It allows you to include the pages you want from a sub-site in another main-site without having to change anything in the source files of the sub-site as long as the sub-site source files are inside the directory of the main site.

    Example Suppose you have a site textbook and you want to include some pages from it in another site course. Given below is how you can locate the sub-site textbook inside the root directory of the main-site course so that files from textbook can be reused in the course site.

    c:/course/
      ├── textbook/
      |      ├── index.md
      |      ├── overview.md
      |      └── site.json
      ├── index.md
      ├── reading.md
      └── site.json
    

    reading.md (note how it reuses content from the sub-site textbook):

    # Week 1 Reading:
    <include src="textbook/overview.md" />
    

    If you are using Git for version control, you can set up the sub-site repository as a Git sub-module of the main site repository.


    Creating Content Variations

    MarkBind can create sites that give more control to the reader. Given below are some mechanisms authors can use to create variations of content that gives more control to the reader in charting their own path through the content.

    Allowing users to remove some contents

    When the readers can remove an item from a page, they can create their own version of the page by removing items they don't want to see. This is especially useful when printing a page.

    To make an element closeable, use v-closeable.

    <div v-closeable>
    
    Optional video:
    
    @[youtube](v40b3ExbM0c)
    
    </div>
    

    This is how the content will appear. Note how you can hover over the content to access the ❌ button that can collapse the content.

    Optional video:

    Giving alternative contents

    You can use a Tabs component to give alternative versions of content, for example, giving a code snippet in different programming languages.

    Giving access to additional contents

    You can use following components to give readers an option to access additional content at their discretion.

    Organizing contents in alternative ways

    You can take advantage of MarkBinds feature for content reuse, you can organize content in alternative ways to cater for different readers, without having to duplicate content. For example, you can have different pages that organizes the same information alphabetically, chronologically, by difficulty, group information by topic, etc.

    Optimizing the Print View

    To hide minimized panels in the print view, add the following code to a CSS file used in your site.

    @media print {
        .card-container > .morph {
            display: none;
        }
    }
    

    Hiding some info in the generated content

    To permanently hide a fragment from the reader:

    <span class="d-none">
      content to hide ...
    </span>
    
    <panel header="..." add-class="d-none">
      content to hide ...
    <panel>
    

    To hide a fragment in one specific page, 'mark' the elements using a class:

    <span class="extra">
      content to hide ...
    </span>
    

    Then, in a page-specific CSS file,

    .extra {
      display: none; /* 'block' or 'inline-block' if you want it to show */
    }
    

    Creating slight variations of content

    Tags are a good way to create multiple variations of a page within the same source file, such as to filter content for creating multiple different versions of the same page. See User Guide: Tweaking the Page Structure → Tags section for more information.