All Projects → sebbekarlsson → gpp

sebbekarlsson / gpp

Licence: GPL-3.0 license
General PreProcessor

Programming Languages

c
50402 projects - #5 most used programming language
CMake
9771 projects

Projects that are alternatives of or similar to gpp

yaproq
A templating language in Swift
Stars: ✭ 57 (+128%)
Mutual labels:  templating, templating-language, templating-engine
voldemort
A simple static site generator using Jinja2 and Markdown templates.
Stars: ✭ 48 (+92%)
Mutual labels:  static-site-generator, jinja2
leven
😋 Make your own blog!
Stars: ✭ 54 (+116%)
Mutual labels:  static-site-generator, templating
graphql-ssg
GraphQL data based Static Site Generator.
Stars: ✭ 30 (+20%)
Mutual labels:  static-site-generator, static-site-generation
Dotdrop
Save your dotfiles once, deploy them everywhere
Stars: ✭ 813 (+3152%)
Mutual labels:  jinja2, templating
Askama
Type-safe, compiled Jinja-like templates for Rust
Stars: ✭ 1,255 (+4920%)
Mutual labels:  jinja2, templating
stacy
Website generator that combines content from Contentful CMS with Handlebars templates and publishes the website in Amazon S3.
Stars: ✭ 24 (-4%)
Mutual labels:  static-site-generator, static-site-generation
markyp-bootstrap4
Create Bootstrap 4 web pages using purely Python.
Stars: ✭ 19 (-24%)
Mutual labels:  templating, templating-engine
Grow
A declarative website generator designed for high-quality websites, with a focus on easy maintenance and localization.
Stars: ✭ 360 (+1340%)
Mutual labels:  static-site-generator, jinja2
Jmmasw
Just make me a static website
Stars: ✭ 13 (-48%)
Mutual labels:  static-site-generator, templating
Metalsmith React Templates
A metalsmith plugin to render files using React / Preact / JSX based templates.
Stars: ✭ 90 (+260%)
Mutual labels:  static-site-generator, templating
Prinder
Free Pull Request reminder for Github. Has configurations to post reminders to Slack and email along with jinja templating
Stars: ✭ 21 (-16%)
Mutual labels:  jinja2, templating
Plot
A DSL for writing type-safe HTML, XML and RSS in Swift.
Stars: ✭ 1,722 (+6788%)
Mutual labels:  templating, static-site-generation
nene
Nēnē: A no-frills static site generator
Stars: ✭ 22 (-12%)
Mutual labels:  static-site-generator, jinja2
Statik
Multi-purpose static web site generator aimed at developers.
Stars: ✭ 249 (+896%)
Mutual labels:  static-site-generator, jinja2
logya
Logya is a static site generator written in Python designed to be easy to use and flexible.
Stars: ✭ 16 (-36%)
Mutual labels:  static-site-generator, jinja2
Docpad
Empower your website frontends with layouts, meta-data, pre-processors (markdown, jade, coffeescript, etc.), partials, skeletons, file watching, querying, and an amazing plugin system. DocPad will streamline your web development process allowing you to craft powerful static sites quicker than ever before.
Stars: ✭ 3,035 (+12040%)
Mutual labels:  static-site-generator, preprocessor
Staticjinja
Minimalist Python library for building static websites with Jinja
Stars: ✭ 218 (+772%)
Mutual labels:  static-site-generator, jinja2
hypertag
HTML templates with Python-like concise syntax, code reuse & modularity. The Pythonic way to web templating.
Stars: ✭ 27 (+8%)
Mutual labels:  templating, templating-language
SOMns
SOMns: A Newspeak for Concurrency Research
Stars: ✭ 62 (+148%)
Mutual labels:  interpreter

GPP

General PreProcessor
not just for HTML, it can be used anywhere

<!--
    {{ }} = ** Compute Block ** 
          - A block that is interpreted as templating logic

    (@ @) = ** Virtual File Block **
          - Anything in here is just treated as if it was a completely new file.
            This block is also used to tell the pre-processor that something
            should be evaluated "lazy".

    ( ) = ** List **
          - A list of elements, separated by comma.
          - Aliases: [ ]

    map = ** Built-in function **
          - It does what you expect, just like the map function in for example
            Javascript, it takes in an iterable as the first argument and a
            yield / function as the second argument. 

    join = ** Built-in function **
          - Join a list with some value.
            First argument is an iterable, second argument is anything you want. 

    cat = ** Built-in function **
          - This function simply reads an infinite list of files, concatenates
            the contents and dumps it out as it is.
            The contents of the files are just treated as text and not evaluated.
            This function takes in an infinite list of strings as an argument.

    cate = ** Built-in function **
          - Just like `cat` but it also evaluates the content of the files
            before concatenating them and dumping it out.

    floor = ** Built-in function **
          - Floors a number. For example, the input 60.6 would return 60.
		  
	load = ** Built-in function **
          - Loads a JSON file.
			The signature is:
			load (string filename)

    key = ** Built-in function **
          - Extract a key by index from an object.
            The signature is:
            key (object index)

    value = ** Built-in function **
          - Extract a value by index from an object.
            The signature is:
            value (object index)

    get = ** Built-in function **
          - Extract a value by index or key from an object or list.
            The signature is:
            value ((object || list) (index || key))
            
    range = ** Built-in function **
          - Generate a list from 0 to -> N
            {{ map (range(100), (@<li>{{ $0 }}</li>@)) }}


    $ = ** Positional parameter constant **
          - This is heavily inspired by the shell, it allows you to access
            the positional arguments within a function body.
            For example, to access the first argument you would use `$0`,
            to access the second one you would use `$1`, and then `$2`...
            and so on and so forth. 
!-->
<html>
    <body>
        <h1>{{ "Welcome" }}</h1>
        <h2>The basics</h2>
        <section>
            <h3>Virtual file blocks and compute blocks</h3>
            <span>
                (@
                    Here is some text that will be completely ignored.   
                    This: <b>{{ "Is not ignored however" }}</b>.
                @)
            </span>

            <h3>Mapping a list to HTML</h3>
            <ul>
               {{ map (["apple", "banana", "pear","orange"], (@<li>{{ $0 }}</li>@)) }}
            </ul>

            <h3>Dumping out file contents</h3>
            <pre>{{ cat ("src/main.c") }}</pre>

            <h3>Below will be evaluated</h3>
            <p>{{ cate ("examples/hello.html") }}</p>
        </section>
        <h2>Integrating other languages</h2>
        <section>
            <h3>I really want this list to be rendered using Python!</h3>
            <ul>
            (@#!/usr/bin/python
            for name in ["john", "sarah", "anna"]:
                x = """(@
                    <li>
                        {}     
                    </li>
                @)""".format(name)
                print(x)
            @)
            </ul>
            <h3>I do want this list to be rendered in Node.js though</h3>
            <ul>
            (@#!node
            console.log(["john", "sarah", "anna"]
              .map(name => (@ "<li>" + name + "</li>" @)).join('\n'));
            @)
            </ul>
        </section>
    </body>
</html>

Templating

The basics

There are a few important tokens in the templating language, and we will go through them in this section.

{{ , }}

The {{ and the }} tokens are used to indicate the start {{ and the end }} of a block of templating logic.

(@ , @)

The (@ and the @) tokens are used to indicate the start (@ and the end @) of a virtual file block. A virtual file block is something that is just treated as text by the preprocessor. In other words, nothing within these tokens will be interpreted. The entire document is by default wrapped in a virtual file block.
There is one exception to the (@ @) (virtual file block) however, if you specify a path to an interpreter, the rest of the content will be interpreted. (There is an example further down in this document)

If you still do not understand

The following:

<p>{{ "hello" }}</p>

Will be rendered as:

<p>hello</p>

The following:

<p>(@ "hello" @)</p>

Will be rendered as:

<p> "hello" </p>

Arrow functions

You can also define functions to render data,
Here is an example of creating a function to render a <ul> list:

{{
    itemList = (items) => map (items, (@
        <li>{{ $0 }}</li>
    @))
}}

{{  itemList (["hello", "world"]) }}

This will render as:

<ul>
    <li>hello</li>
    <li>world</li>
</ul>

Extending / Inheritance

You can make templates inherit / extend other templates.
Here is how a parent template could look like: (parent.hml)

<html>
    <head>
        <title>(@#%block title @)</title>
    </head>
    <body>
        (@#%block body @)
    </body>
</html>

Notise the % at the start of the comment.
And then you can write a child template that inherits from this one
Like this: (child.html)

#%extends "parent.html"

(@#%block title
    My Title
@)

(@#%block body
    Welcome to my website
@)

Also, notice here the % at the start of each comment.
If you run gpp over child.html now, the output will be:

<html>
    <head>
        <title>My Title</title>
    </head>
    <body>Welcome to my website</body>
</html>

Loading data

What is a templating engine without any data to work with?
To access data in your templates, simply put a context.json file within the root of your project.
Example (context.json):

{
    "title": "My Title",
    "favouriteFruits": ["apple", "pear", "banana"]
}

Now you can access these variables in your templates,
Example:

<html>
    <title>{{ title }}</title>
    <body>
        {{ map (favouriteFruits, (@<li>{{ $0 }}</li>@)) }}
    </body>
</html>

You can also use the load function. Like this:

{{
	mydata = load("somedata.json")
}}

<h1>{{ mydata.firstname }}</h1>

Any interpreter you want

If you do not want to use the default language, you can use any language you want to interpret the templates. Here is an example where we are rendering a <ul> list using Python.

<html>
    <body>
        <ul>
(@#!/usr/bin/python
for i in range(100):
    x = """(@
        <li>
            {}     
        </li>
    @)""".format(i)
    print(x)
 @)
        </ul>
    </body>
</html>

To make this work, we simply put a comment inside our (@ @) block. This comment should start with a #! and then the path to the program that should be interpreting the rest of the content inside of the (@ @) block.

Installation

Ready to use this piece of software?

1. Clone it (or download it)

Go and get the source code, if you are reading this on Github,
then just copy the clone URL and clone it down.

git clone <url> --recurse-submodules

Do NOT forget the --recurse-submodules flag.

2. Compile it

Make sure you have a compiler on your system, preferably gcc. You can read more about gcc here: https://gcc.gnu.org/
You also need to make sure you have make on your system.
You can read more about make here: https://www.gnu.org/software/make/.
Alright! time to compile this thing.

Go to the root directory - Open up a shell and go to the root directory of this project:

cd gpp/

Execute Make - Run the make command

make

!!!Abrakadabra!!!

3. Run it

You are now ready to use this, Here is how you do that:

./a.out index.html

Yes... I know a.out is not really a production ready name for a binary.
But this software is still in the work in progress stage.
Anyways, so you execute the a.out file and you give it a filename as the first argument and then it will just print out the transpiled / compiled content to stdout.

Plans

Here are some plans / thoughts.
If you feel like you could help implement some of them, feel free to make a pull-request.

  • Write better documentation
  • Implement a step-by-step debugger
  • Create a shared library to allow the use of this in other languages
  • Implement bindings for NodeJS
  • Implement bindings for Python

Now, these are not tasks / issues.
This is just some ideas and I am just thinking out loud.
Bugs, Todos, and tasks will be seen in Github's issues section.

FAQ

If I define a variable in my Python code,
how can I later access it in my NodeJS block
below?

That is unfortunately not possible.
If you want to share data between languages, you need to use the built-in templating language to unserialize the data into your code blocks.

Isn't it unsafe to call the binary specified in the "!#" comment?

Well, just don't put an unsafe binary there?
This couldn't care less about what logic you write or which binaries you use to interpret the code blocks. This is just a templating language.

Does it work on Windows?

I dont know, I haven't tried it there.
But I assume it would be tricky to get it to work there, since this software was developed on a Linux machine and the source code has dependencies on C implementations on Linux... you know header files and stuff.

How do I send data into the template context?

Put a context.json file in the root of your project, you can later access all data in this file inside your templates.

Status

Compile and test


Not Made with Coffee and Love in San Francisco

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].