Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
berumuron
Boop
Commits
1d4ab7d1
Commit
1d4ab7d1
authored
Dec 11, 2018
by
berumuron
Browse files
add: Provide a very basic template system
parent
a069ecbc
Changes
3
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
1d4ab7d1
...
...
@@ -58,15 +58,72 @@ $ tree
```
Boop! basically just copied
`content`
files under a
`output`
directory. But it
can convert Markdown files in HTML too:
can convert Markdown files in HTML too. For that, you'll need a template file
for articles:
```
console
$
mkdir
theme
$
echo
'<html><body>{{ ARTICLE_CONTENT }}</body></html'
>
theme/article.html
```
Then, you can create your Markdown file as you did with the HTML one:
```
console
$
echo
'# Welcome!'
>
content/markdown-index.md
$
boop.py
$
echo
output/markdown-index.html
<h1>
Welcome!</h1>
<html>
<body>
<h1>Welcome!</h1>
</body></html>
```
You can define meta variables in the Markdown file which will be accessible
then in the template. Variables are uppercased and prepended by
`ARTICLE_`
. For
example, for the following Markdown file:
```markdown
---
title: Welcome!
author: Marien
---
This is my article.
```
And the HTML template:
```
html
<html>
<head>
<title>
{{ ARTICLE_TITLE }}
</title>
</head>
<body>
<h1>
{{ ARTICLE_TITLE }}
</h1>
<p>
By {{ ARTICLE_AUTHOR }}
</p>
{{ ARTICLE_CONTENT }}
</body>
</html>
```
It will produce the following file:
```
html
<html>
<head>
<title>
Welcome!
</title>
</head>
<body>
<h1>
Welcome!
</h1>
<p>
By Marien
</p>
<p>This is my article.</p>
</body>
</html>
```
For now, you can use any valid Python expression between `{{ }}`, you have
access to the variables defined in the meta header, the Python builtin
functions and the `datetime` module.
## Tests
There are some tests (i.e. doctests) that can be run to check that everything
...
...
boop.py
View file @
1d4ab7d1
...
...
@@ -3,9 +3,15 @@
import
os
import
sys
import
shutil
import
locale
import
markdown
import
boopsy
locale
.
setlocale
(
locale
.
LC_ALL
,
"fr_FR.utf8"
)
class
ProgramError
(
Exception
):
"""Exception raised during the program execution.
...
...
@@ -41,6 +47,20 @@ def mkdirs_for_file(filepath):
os
.
makedirs
(
path
,
exist_ok
=
True
)
def
convert_meta_to_article_vars
(
meta
):
"""Convert Markdown Meta to vars for article layout.
"""
article_vars
=
{}
for
key
,
values
in
meta
.
items
():
article_key
=
f
"ARTICLE_
{
key
.
upper
()
}
"
# The Markdown's meta extension extract all the values in arrays, even
# if there is only one value. Because there is no iteration system in
# the template system, for the moment we just get the first value of
# the array.
article_vars
[
article_key
]
=
values
[
0
]
return
article_vars
def
main
():
# Check that content directory exists on the filesystem
content_path
=
os
.
path
.
join
(
os
.
curdir
,
"content"
)
...
...
@@ -56,7 +76,7 @@ def main():
# ... but it also can be a simple file if user created it manually!
os
.
remove
(
output_path
)
md
=
markdown
.
Markdown
()
md
=
markdown
.
Markdown
(
extensions
=
[
"meta"
]
)
# And copy the files from ./content to ./output
for
filepath
in
dir_tree
(
content_path
):
...
...
@@ -74,9 +94,18 @@ def main():
with
open
(
content_filepath
,
"r"
)
as
content_file
:
html
=
md
.
convert
(
content_file
.
read
())
# And we write it as a HTML file
# We initialize the template
article_template_filepath
=
os
.
path
.
join
(
"theme"
,
"article.html"
)
template
=
boopsy
.
Template
(
article_template_filepath
)
# We get the local variables from the Markdown file (metadata)
# which will be accessible in the article template
article_vars
=
convert_meta_to_article_vars
(
md
.
Meta
)
article_vars
[
"ARTICLE_CONTENT"
]
=
html
# And we write the content in the output file
with
open
(
output_filepath
,
"w"
)
as
output_file
:
output_file
.
write
(
html
)
output_file
.
write
(
template
.
render
(
article_vars
)
)
else
:
# ... else, we simply copy the file to the output directory
shutil
.
copyfile
(
content_filepath
,
output_filepath
)
...
...
boopsy.py
0 → 100644
View file @
1d4ab7d1
import
re
from
datetime
import
datetime
class
BoopsySyntaxError
(
Exception
):
"""Exception raised if template file is invalid.
"""
pass
class
Template
:
def
__init__
(
self
,
template_name
):
"""Initialize a Boopsy template from file content.
"""
self
.
template_name
=
template_name
with
open
(
self
.
template_name
,
"r"
)
as
f
:
self
.
template
=
f
.
read
()
def
render
(
self
,
variables
):
"""Return a string corresponding to template content with vars replaced.
"""
rendering
=
[]
# The template is splitted in tokens:
# - {{ a_python_expression }}
# - or all the other strings
tokens
=
re
.
split
(
r
"(?s)({{.*?}})"
,
self
.
template
)
for
token
in
tokens
:
if
token
.
startswith
(
"{{"
):
expression
=
token
[
2
:
-
2
].
strip
()
if
len
(
expression
)
==
0
:
raise
BoopsySyntaxError
(
"an expression is expected between {{ }}"
)
# We evaluate a Python expression which can access the
# variables passed as an argument of `render` and the
# `datetime` module.
evaluated_expression
=
eval
(
expression
,
{
"datetime"
:
datetime
},
variables
)
rendering
.
append
(
evaluated_expression
)
elif
token
:
# default tokens must be added to the rendering array
rendering
.
append
(
token
)
return
""
.
join
(
rendering
)
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment