hypertextcpp - is a hyperfast HTML templating system for C++ applications.

hypertextcpp - is a hyperfast HTML templating system for C++ applications.
It provides a highly readable .htcpp template file format and a command line utility that transpiles it to C++ HTML rendering code. Include a generated C++ header file in your project, then setup a build system to update it when necessary, and you're all set.

A quick example:

examples/01/todolist.htcpp

<html>	
    <body>
        <h1>$(cfg.name)'s todo list:h1>
        <p> No tasks found p>?(cfg.tasks.empty())
        <ul>
            <li>$(task.name)li>@(auto task : cfg.tasks)
        ul>
    body>
html>

Now let's generate the C++ header:

[email protected]:~$ hypertextcpp todolist.htcpp

This command creates the todolist.h file in the current working directory. All that's left is to use it in our program.

examples/01/todolist_printer.cpp

#include int main() { struct PageParams{ struct Task{ std::string name; }; std::string name = "Bob"; std::vector tasks = {{"laundry"}, {"cooking"}}; } pageParams; auto page = todolist{}; page.print(pageParams); return 0; } ">
#include "todolist.h"
#include <string>
#include <vector>

int main()
{	
    struct PageParams{
        struct Task{
            std::string name;
        };
        std::string name = "Bob";
        std::vector tasks = {{"laundry"}, {"cooking"}};
    } pageParams;
    auto page = todolist{};
    page.print(pageParams);
    return 0;
}

Compile it with your preferred method, launch it, and you will get this output:

[email protected]:~$ ./todolist_printer
	
    
        

Bob's todo list:

  • laundry
  • cooking

Table of contents

Template file syntax

Expressions

$(c++ expression)
Expressions are used to add application's data to the template. It can be any valid C++ expression, with only condition, that its result must be streamable to the default output stream std::ostream. Expressions can be placed anywhere in the HTML template, besides the tag names. In our todolist example, $(cfg.name) is an expression adding template config variable name to the result page.

Statements

${c++ statement(s)}
Statements are used to add any valid C++ code to the template rendering function. For example, you can add variables, classes declarations or lambdas. Let's say that you don't like the default name cfg used for passing data to the template. You can create a reference to it with any name you like and use it later:

    ${ auto& param = cfg;}
    <h1>$(param.name)'s todo list:h1>

Note, that cfg and out are reserved names used for parameters in generated rendering function. Also, don't put anything in the htcpp namespace.

Global statements

#{c++ statement(s)}
These statements are used to add any valid C++ code outside the template rendering function. Unlike regular statements, with global ones you can add include directives or functions definitions. Global statements can only be placed in the top level of htcpp template, outside any HTML element. Please, don't put anything in the htcpp namespace.

Control flow extensions

If hypertextcpp used a common approach for control flow in HTML template engines, our todolist example would look something like this:

<html>	
    <body>
        <h1>%%cfg.name%%'s todo list:h1>
        %%if cfg.tasks.empty()%%
        <p> No tasks found p>				
        %%end%%
        %%for auto task : cfg.tasks%%
            <ul>							
                <li>$(task.name)li>
            ul>
        %%end%%
    body>
html>

In our opinion it significantly hurts readability of document tree and makes it hard to choose indentation and keep it consistent - notice how different approaches are used for if and for blocks in the example.

hypertextcpp solves this problem (and is created mainly for solving this problem) by applying control flow to the HTML elements itself without adding logic block scopes to the document. It uses just two extensions for tags to make this work:

  • Conditional extension
    ?(c++ condition)
    HTML elements with this extension are added to the document only when condition is fulfilled. Example of usage from our todolist template:

        <p> No tasks found p>?(cfg.tasks.empty())
  • Loop extension
    @(c++ init-statement; condition; iteration_expression)
    or
    @(c++ range_declaration : range_expression)
    HTML elements with this extension are added to the document multiple times, on each step of the loop, or for each element of the iterated range. Example of usage from our todolist template:

        <li>$(task.name)li>@(auto task : cfg.tasks)

    Lets add another example for other type of for loop:

        <li>Task#$(i)li>@(auto i = 0 ; i < 3; ++i)

    which evaluates to

        <li>Task#0li>
        <li>Task#1li>
        <li>Task#2li>

Both extensions can be added to the opening or closing tag, but each tag and HTML element can only have one extension.

It's recommended to add extension to the opening tag for the multiline HTML elements:

<div>?(cfg.greet)
    <p>Hello world!p>
div>

and to the closing tag for the single-line ones:

<div><p>Hello world!p>div>?(cfg.greet)

Note, that while extensions hide control flow block scopes from the template document, they're still present in the generated C++ code and implemented with regular if and for control structures. Therefore, template like this:

    <div>@(auto i = 0; i<3; ++i)
        ${ auto num = i*2;}
        <p> Item #$(num)<p>
    div>
    <p> Last num is $(num) p>

won't compile because the num variable isn't visible outside the for block scope generated by loop extension on the div tag.

Sections

[[ text, html elements, statements, expressions or other sections ]]
Sections can contain a part of template document, and it's possible to attach control flow extensions to them. Their main usage is adding attributes to HTML elements conditionally.

Let's update todolist example by adding a line-through text style to completed tasks:
examples/02/todolist.htcpp

$(task.name)@(auto task : cfg.tasks) ">
<html>	
    <body>
        <h1>$(cfg.name)'s todo list:h1>
        <p> No tasks found p>?(cfg.tasks.empty())
        <ul>
            <li [[style="text-decoration: line-through;"]]?(task.isCompleted)>$(task.name)li>@(auto task : cfg.tasks)
        ul>
    body>
html>

Don't forget to update the C++ template config structure!
examples/02/todolist_printer.cpp

tasks = {{"laundry", true}, {"cooking", false}}; } pageParams; //... ">
//...
struct PageParams{
        struct Task{
            std::string name;
            bool isCompleted = false;
        };
        std::string name = "Bob";
        std::vector tasks = {{"laundry", true}, {"cooking", false}};
    } pageParams;
//...

Tip of the day: Keep your template tidy and don't introduce sections when it's possible to attach extensions to HTML elements.

Procedures and partial rendering

#procedureName(){html elements, statements, expressions or sections}

Parts of htccp template can be placed inside procedures - parameterless functions capturing the cfg variable. They are available for call from the C++ application, so if any part of the page needs to be rendered separately from the whole template, procedures are a big help. Procedures can only be placed in the top level of htcpp template, outside any HTML element. Let's put the list of tasks from the todolist example in the procedure:
examples/03/todolist.htcpp

$(task.name)@(auto task : cfg.tasks) }

$(cfg.name)'s todo list:

No tasks found

?(cfg.tasks.empty())
    $(taskList())
">
#taskList(){
    <li [[style="text-decoration: line-through;"]]?(task.isCompleted)>$(task.name)li>@(auto task : cfg.tasks)
}
<html>	
    <body>
        <h1>$(cfg.name)'s todo list:h1>
        <p> No tasks found p>?(cfg.tasks.empty())
        <ul>
            $(taskList())
        ul>
    body>
html>

Now the tasks list can be output to stdout by itself like that:
examples/03/todolist_printer.cpp

    //...
    auto page = todolist{};
    page.print("taskList", pageParams); 
    //...

Code generation

Command line parameters

generated class name (optional) Flags: -s, --shared-lib generate result as shared library source files --class-pascalcase generate class name by using .htcpp filename in PascalCase --class-snakecase generate class name by using .htcpp filename in snake_case --class-lowercase generate class name by using .htcpp filename in lowercase --help show usage info and exit Process finished with exit code 0 ">
[email protected]:~$ hypertextcpp --help
Usage: hypertextcpp  [params] [flags] 
Arguments:
    (path)               .htcpp file to transpile
Parameters:
  -o, --output            output c++ file path
                                  (if empty, current working directory is used)
                                  (optional, default: "")
  -c, --class-name      generated class name
                                  (optional)
Flags:
  -s, --shared-lib              generate result as shared library source 
                                  files
      --class-pascalcase        generate class name by using .htcpp filename 
                                  in PascalCase
      --class-snakecase         generate class name by using .htcpp filename 
                                  in snake_case
      --class-lowercase         generate class name by using .htcpp filename 
                                  in lowercase
      --help                    show usage info and exit


Process finished with exit code 0

Single header renderer

By default, the hypertextcpp transpiler works in a single header mode and generates a C++ header file that you're supposed to simply include in your project. A generated renderer class has a name of .htcpp template file. You can override the name by using --class-name parameter, or you can specify one of the following flags --class-pascalcase, --class-snakecase or --class-lowercase to use .htcpp template's filename converted to the corresponding case as a class name. Converting template to C++ code each time you modify it is a laborious task, so it makes sense to add this step to your build process. Let's demonstrate on how to do it with CMake and at the same time rename the renderer class.

examples/04/CMakeLists.txt

cmake_minimum_required(VERSION 3.13)

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE Release)
endif()
message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")

add_custom_command(
    OUTPUT  todolist.h
    COMMAND hypertextcpp ${CMAKE_CURRENT_SOURCE_DIR}/todolist.htcpp -o ${CMAKE_CURRENT_SOURCE_DIR}/todolist.h --class-name TodoList
   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/todolist.htcpp
)

set(SRC
    main.cpp
    todolist.h)

add_executable(todolist_printer ${SRC})

Now, everytime you change the template, the corresponding header will be regenerated on the next build.

Shared library renderer

It can feel quite wasteful to rebuild your project each time the template file is changed, so hypertextcpp supports generation of C++ source file for building templates in form of shared libraries and linking them dynamically from your application. It requires to duplicate the config declaration in .htccp template, registering it with HTCPP_CONFIG macro both in template and in the application source, generate the renderer code with --shared-lib command line flag, build the library and load it using the tiny API installed from the shared_lib_api/ directory. It sounds scarier than it is, so let's quickly update the todolist example to see how it works.

First we need to copy the config structure declaration in the template:
examples/05/todolist.htcpp

tasks = {{"laundry", true}, {"cooking", false}}; } pageParams; HTCPP_CONFIG(PageParams); } #taskList(){
  • $(task.name)
  • @(auto task : cfg.tasks) }

    $(cfg.name)'s todo list:

    No tasks found

    ?(cfg.tasks.empty())
      $(taskList())
    ">
    #{
        #include <vector>
        struct PageParams{
            struct Task{
                std::string name;
                bool isCompleted = false;
            };
            std::string name = "Bob";
            std::vector<Task> tasks = {{"laundry", true}, {"cooking", false}};
        } pageParams;
        HTCPP_CONFIG(PageParams);
    }
    
    #taskList(){
        <li [[style="text-decoration: line-through;"]]?(task.isCompleted)>$(task.name)li>@(auto task : cfg.tasks)
    }
    <html>	
        <body>
            <h1>$(cfg.name)'s todo list:h1>
            <p> No tasks found p>?(cfg.tasks.empty())
            <ul>
                $(taskList())
            ul>
        body>
    html>

    Be sure to use an exact copy, any mismatch of the config structure between template and application can't be handled gracefully, so if you try to load a template library with different structure you'll definitely crash the application and maybe hurt someone as a result.

    Next, we need to build our template renderer as a library. It's not possible to bundle multiple templates file in one library, so we can easily use a generic CMake file, that builds a library from a single .htcpp file:
    shared_template/CMakeLists.txt

    cmake_minimum_required(VERSION 3.13)
    
    if(NOT CMAKE_BUILD_TYPE)
      set(CMAKE_BUILD_TYPE Release)
    endif()
    message(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
    
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED True)
    set(CMAKE_CXX_FLAGS "-Wall -Wextra -fPIC")
    set(CMAKE_CXX_FLAGS_DEBUG "-g")
    set(CMAKE_CXX_FLAGS_RELEASE "-O3")
    
    option(NAME "Template name")
    
    add_custom_command(
        OUTPUT  ${NAME}.cpp
        COMMAND hypertextcpp ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}.htcpp -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.cpp -s
        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}.htcpp
    )
    
    add_library(${NAME} SHARED ${CMAKE_CURRENT_BINARY_DIR}/${NAME}.cpp)
    

    Copy todolist.htcpp in shared_template/ and execute the following commands:

    [email protected]:~/shared_template$ mkdir build; cd build; 
    [email protected]:~/shared_template/build$ cmake -DNAME=todolist ..; make

    If everything goes right, you'll get the libtodolist.so in the build directory. That's our todolist.htcpp template compiled as the shared library.
    Next, let's modify the todolist_printer.cpp to be able to load it:
    examples/05/todolist_printer.cpp

    tasks = {{"laundry", true}, {"cooking", false}}; }; HTCPP_CONFIG(PageParams); int main() { auto pageParams = PageParams{}; auto page = htcpp::loadTemplate("libtodolist.so"); page->print(pageParams); return 0; } ">
    #include <hypertextcpp/templateloader.h>
    #include <string>
    #include <vector>
    
    struct PageParams{
    struct Task{
    std::string name;
    bool isCompleted = false;
    };
    std::string name = "Bob";
    std::vector tasks = {{"laundry", true}, {"cooking", false}};
    };
    HTCPP_CONFIG(PageParams);
    
    int main()
    {
    auto pageParams = PageParams{};
    auto page = htcpp::loadTemplate("libtodolist.so");
    page->print(pageParams);
    return 0;
    }

    Don't forget to add linking of system library dl to the build config - that allows us to link the template library dynamically.
    todolist_printer should compile and work the same as the previous example using the single header approach.

    Installation

    git clone https://github.com/kamchatka-volcano/hypertextcpp.git
    cd hypertextcpp && mkdir build && cd build
    cmake ..
    make install

    Running tests

    cd hypertextcpp/build
    cmake .. -DENABLE_TESTS=ON
    make
    ctest

    License

    hypertextcpp is licensed under the MS-PL license
    The bundled part of the GSL library is licensed under the MIT license

    Similar Resources

    DeskGap is a framework for building cross-platform desktop apps with web technologies (JavaScript, HTML and CSS).

    DeskGap is a framework for building cross-platform desktop apps with web technologies (JavaScript, HTML and CSS).

    A cross-platform desktop app framework based on Node.js and the system webview

    Nov 27, 2022

    Ultra-lightweight web browser based on Qt Ultralight webview, powered by Ultralight HTML renderer

    Ultra-lightweight web browser based on Qt Ultralight webview, powered by Ultralight HTML renderer

    Qt Ultralight Browser This is an ultra-lightweight web browser powered by the Ultralight web engine embedded in Qt 5 app as a custom webview widget -

    Nov 12, 2022

    Tau is a fast syntax highlighter capable of emitting HTML.

    tau - a reasonably fast (wip) syntax highlighter. Tau is a fast syntax highlighter capable of emitting HTML. It highlights the following languages: py

    Nov 16, 2022

    A Flutter Web Plugin to display Text Widget as Html for SEO purpose

    A Flutter Web Plugin to display Text Widget as Html for SEO purpose

    SEO Renderer A flutter plugin (under development) to render text widgets as html elements for SEO purpose. Created specifically for issue https://gith

    Nov 21, 2022

    ­čôâ Export WeChat chat histories to HTML files.

    ­čôâ Export WeChat chat histories to HTML files.

    wechat-export Export WeChat chat histories to HTML files. Preview This script generates a HTML file for each contact's chat history. Currently it supp

    Nov 21, 2022

    Embed image data directly to HTML files.

    compact_html Welcome! Embed image data directly to HTML files. Thanks: cpp-base64: Base64 encoding and decoding with c++. cpprestsdk: The C++ REST SDK

    Aug 21, 2022

    Repair UTF-8 codes and problematic HTML in Eudora mailboxes

    Eudora_fix_mbx: Repair UTF-8 character codes and problematic HTML in Eudora mailboxes

    Aug 8, 2022

    Convert LLVM coverage information into HTML reports

    llvm-coverage-to-html converter The clang compiler supports source based coverage tracking, but the default reporting options are very basic. This too

    Oct 11, 2021

    Very fast Markdown parser and HTML generator implemented in WebAssembly, based on md4c

    Very fast Markdown parser and HTML generator implemented in WebAssembly, based on md4c

    Nov 25, 2022

    Convert HTML to PDF using Webkit (QtWebKit)

    wkhtmltopdf and wkhtmltoimage wkhtmltopdf and wkhtmltoimage are command line tools to render HTML into PDF and various image formats using the QT Webk

    Nov 28, 2022

    libRocket - The HTML/CSS User Interface library

    libRocket - The HTML/CSS User Interface Library http://librocket.com (!!! malicious domain !!!, last checked 23/feb/2020) libRocket is the C++ user in

    Nov 28, 2022

    Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development

    Golang bindings of Sciter: the Embeddable HTML/CSS/script engine for modern UI development

    Go bindings for Sciter Check this page for other language bindings (Delphi / D / Go / .NET / Python / Rust). Attention The ownership of project is tra

    Nov 26, 2022

    GCC/gcov code coverage data extraction from the actual embedded system, without requiring a file system, or an operating system, or standard C libraries.

    GCC/gcov code coverage data extraction from the actual embedded system, without requiring a file system, or an operating system, or standard C libraries.

    Nov 18, 2022

    NymphCast is a audio and video casting system with support for custom applications.

    NymphCast is a audio and video casting system with support for custom applications.

    NymphCast is a software solution which turns your choice of Linux-capable hardware into an audio and video source for a television or powered speakers. It enables the streaming of audio and video over the network from a wide range of client devices, as well as the streaming of internet media to a NymphCast server, controlled by a client device.

    Nov 21, 2022

    WineFS is a file system for Persistent Memory (PM) which is aimed at maximizing the performance of memory-mapped applications.

    WineFS WineFS is a file system for Persistent Memory (PM) which is aimed at maximizing the performance of memory-mapped applications. WineFS uses a no

    Oct 2, 2022

    2D/3D Registration and system integration for image-based navigation of orthopedic robotic applications, inculding femoroplasty, osteonecrosis, etc.

    Registration and System Integration Software for Orthopedic Surgical Robotic System This repository contains software programs for image-based registr

    Sep 3, 2022

    A static C library to build applications for the Foenix retro computers, and, eventually, a single-tasking operating system and file browser that sits atop the Foenix MCP Kernel

    @mainpage Foenix A2560 Foenix Retro OS: fr/OS A2560-FoenixRetroOS This project provides 2 things: A static C library/framework that anyone can use to

    Jun 24, 2022

    Operating system project - implementing scheduling algorithms and some system calls for XV6 OS

    About XV6 xv6 is a modern reimplementation of Sixth Edition Unix in ANSI C for multiprocessor x86 and RISC-V systems.

    Oct 24, 2022
    JUCE is an open-source cross-platform C++ application framework for desktop and mobile applications, including VST, VST3, AU, AUv3, RTAS and AAX audio plug-ins.
    JUCE is an open-source cross-platform C++ application framework for desktop and mobile applications, including VST, VST3, AU, AUv3, RTAS and AAX audio plug-ins.

    JUCE is an open-source cross-platform C++ application framework used for rapidly developing high quality desktop and mobile applications, including VS

    Dec 1, 2022
    C++14 evented IO libraries for high performance networking and media based applications

    LibSourcey C++ Networking Evolved LibSourcey is a collection of cross platform C++14 modules and classes that provide developers with an arsenal for r

    Nov 22, 2022
    Quick and dirty templating and docs generation.

    Rader Quick and dirty templating and docs generation. Rader is a pre-processing (or post-processing) utility written in portable C++ 20 (only using st

    Dec 19, 2021
    International obfuscated contest: Small C program to minify HTML sources and generate a minified HTML output.
    International obfuscated contest: Small C program to minify HTML sources and generate a minified HTML output.

    HTML Minifier C International obfuscated contest: Just a small C program to minify HTML sources and generate a minified HTML output. Using $ gcc html-

    Oct 27, 2022
    Keepy is a pseudo-language / HTML preprocessor that translates special syntax into HTML

    Keepy is a pseudo-language / HTML preprocessor that translates special syntax into HTML with the peculiarity of being a "compiled pseudo-language". So after using Keepy you can edit the final output HTML file.

    Jan 1, 2022
    Electron framework lets you write cross-platform desktop applications using JavaScript, HTML and CSS.
    Electron framework lets you write cross-platform desktop applications using JavaScript, HTML and CSS.

    ?? Available Translations: ???? ???? ???? ???? ???? ???? ???? ???? . View these docs in other languages at electron/i18n. The Electron framework lets

    Dec 1, 2022
    Ultralight is an ultra-fast, ultra-light, standards-compliant HTML renderer for applications and games.
    Ultralight is an ultra-fast, ultra-light, standards-compliant HTML renderer for applications and games.

    Ultralight is an ultra-fast, ultra-light, standards-compliant HTML renderer for applications and games. It supports most modern HTML5, CSS, and JavaScript features while still remaining light in binary size and memory usage.

    Nov 27, 2022
    oneAPI DPC++ Library (oneDPL) https://software.intel.com/content/www/us/en/develop/tools/oneapi/components/dpc-library.html

    oneAPI DPC++ Library (oneDPL) The oneAPI DPC++ Library (oneDPL) aims to work with the oneAPI DPC++ Compiler to provide high-productivity APIs to devel

    Nov 16, 2022
    RmlUi - The HTML/CSS User Interface library evolved
    RmlUi - The HTML/CSS User Interface library evolved

    RmlUi - The HTML/CSS User Interface Library Evolved RmlUi - now with added boosters taking control of the rocket, targeting your games and application

    Nov 24, 2022
    The libxo library allows an application to generate text, XML, JSON, and HTML output using a common set of function calls. The application decides at run time which output style should be produced.

    libxo libxo - A Library for Generating Text, XML, JSON, and HTML Output The libxo library allows an application to generate text, XML, JSON, and HTML

    Nov 20, 2022