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

chore: add render_template with jinja-like syntax #129

Closed
Closed
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
108 changes: 107 additions & 1 deletion Manifest.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# This file is machine-generated - editing it directly is not advised

[[ArgTools]]
uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f"

[[Artifacts]]
uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"

Expand All @@ -17,16 +20,37 @@ git-tree-sha1 = "9c209fb7536406834aa938fb149964b985de6c83"
uuid = "944b1d66-785c-5afd-91f1-9de20f533193"
version = "0.7.1"

[[CompilerSupportLibraries_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae"

[[ConcurrentUtilities]]
deps = ["Serialization", "Sockets"]
git-tree-sha1 = "b306df2650947e9eb100ec125ff8c65ca2053d30"
uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb"
version = "2.1.1"

[[DataAPI]]
git-tree-sha1 = "8da84edb865b0b5b0100c0666a9bc9a0b71c553c"
uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a"
version = "1.15.0"

[[DataValueInterfaces]]
git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6"
uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464"
version = "1.0.0"

[[Dates]]
deps = ["Printf"]
uuid = "ade2ca70-3891-5945-98fb-dc099432e06a"

[[Downloads]]
deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"]
uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6"

[[FileWatching]]
uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee"

[[HTTP]]
deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"]
git-tree-sha1 = "69182f9a2d6add3736b7a06ab6416aafdeec2196"
Expand All @@ -37,6 +61,11 @@ version = "1.8.0"
deps = ["Markdown"]
uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240"

[[IteratorInterfaceExtensions]]
git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856"
uuid = "82899510-4779-5014-852e-03e436cf321d"
version = "1.0.0"

[[JLLWrappers]]
deps = ["Preferences"]
git-tree-sha1 = "abc9885a7ca2052a736a600f7fa66209f96506e1"
Expand All @@ -49,9 +78,29 @@ git-tree-sha1 = "84b10656a41ef564c39d2d477d7236966d2b5683"
uuid = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
version = "1.12.0"

[[LibCURL]]
deps = ["LibCURL_jll", "MozillaCACerts_jll"]
uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21"

[[LibCURL_jll]]
deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"]
uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0"

[[LibGit2]]
deps = ["Base64", "NetworkOptions", "Printf", "SHA"]
uuid = "76f85450-5226-5b5a-8eaa-529ad045b433"

[[LibSSH2_jll]]
deps = ["Artifacts", "Libdl", "MbedTLS_jll"]
uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8"

[[Libdl]]
uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb"

[[LinearAlgebra]]
deps = ["Libdl", "libblastrampoline_jll"]
uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[[Logging]]
uuid = "56ddb016-857b-54e1-b83d-db4d58db5568"

Expand Down Expand Up @@ -86,9 +135,19 @@ uuid = "a63ad114-7e13-5084-954f-fe012c677804"
[[MozillaCACerts_jll]]
uuid = "14a3606d-f60d-562e-9121-12d972cd8159"

[[Mustache]]
deps = ["Printf", "Tables"]
git-tree-sha1 = "821e918c170ead5298ff84bffee41dd28929a681"
uuid = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
version = "1.0.17"

[[NetworkOptions]]
uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908"

[[OpenBLAS_jll]]
deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"]
uuid = "4536629a-c528-5b80-bd46-f80d51c5b363"

[[OpenSSL]]
deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"]
git-tree-sha1 = "7fb975217aea8f1bb360cf1dde70bad2530622d2"
Expand All @@ -101,12 +160,27 @@ git-tree-sha1 = "6cc6366a14dbe47e5fc8f3cbe2816b1185ef5fc4"
uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95"
version = "3.0.8+0"

[[OrderedCollections]]
git-tree-sha1 = "2e73fe17cac3c62ad1aebe70d44c963c3cfdc3e3"
uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
version = "1.6.2"

[[OteraEngine]]
deps = ["Pkg", "TOML"]
git-tree-sha1 = "aba81eddd54cc8de55d88341e1ee852e914c2db3"
uuid = "b2d7f28f-acd6-4007-8b26-bc27716e5513"
version = "0.2.4"

[[Parsers]]
deps = ["Dates", "SnoopPrecompile"]
git-tree-sha1 = "478ac6c952fddd4399e71d4779797c538d0ff2bf"
uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0"
version = "2.5.8"

[[Pkg]]
deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"]
uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"

[[Preferences]]
deps = ["TOML"]
git-tree-sha1 = "47e5f437cc0e7ef2ce8406ce1e7e24d44915f88d"
Expand All @@ -117,8 +191,12 @@ version = "1.3.0"
deps = ["Unicode"]
uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7"

[[REPL]]
deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"]
uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"

[[Random]]
deps = ["Serialization"]
deps = ["SHA", "Serialization"]
uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[[RelocatableFolders]]
Expand Down Expand Up @@ -163,6 +241,22 @@ version = "1.10.0"
deps = ["Dates"]
uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76"

[[TableTraits]]
deps = ["IteratorInterfaceExtensions"]
git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39"
uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c"
version = "1.0.1"

[[Tables]]
deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "OrderedCollections", "TableTraits"]
git-tree-sha1 = "a1f34829d5ac0ef499f6d84428bd6b4c71f02ead"
uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c"
version = "1.11.0"

[[Tar]]
deps = ["ArgTools", "SHA"]
uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"

[[Test]]
deps = ["InteractiveUtils", "Logging", "Random", "Serialization"]
uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand All @@ -188,3 +282,15 @@ uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5"
[[Zlib_jll]]
deps = ["Libdl"]
uuid = "83775a58-1f1d-513f-b197-d71354ab007a"

[[libblastrampoline_jll]]
deps = ["Artifacts", "Libdl", "OpenBLAS_jll"]
uuid = "8e850b90-86db-534c-a0d3-1478176c7d93"

[[nghttp2_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d"

[[p7zip_jll]]
deps = ["Artifacts", "Libdl"]
uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0"
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
name = "Oxygen"
uuid = "df9a0d86-3283-4920-82dc-4555fc0d1d8b"
authors = ["Nathan Ortega <[email protected]>"]
version = "1.2"
version = "1.2.0"

[deps]
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
JSON3 = "0f8b85d8-7281-11e9-16c2-39a750bddbf1"
MIMEs = "6c6e2e6c-3030-632d-7369-2d6c69616d65"
Mustache = "ffc61752-8dc7-55ee-8c37-f3e9cdd09e70"
OteraEngine = "b2d7f28f-acd6-4007-8b26-bc27716e5513"
RelocatableFolders = "05181044-ff0b-4ac5-8273-598c1e38db00"
Sockets = "6462fe0b-24de-5631-8697-dd941f90decc"

Expand Down
38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -767,3 +767,41 @@ Returns the body of a request as a binary file (returns a vector of `UInt8`s)
| `classtype` | `struct` | A struct to deserialize a JSON object into |

Deserialize the body of a request into a julia struct


### Working with Basic Templating
This section only gives a very quick introduction into how to use Jinja2-Like syntax with Oxygen.jl.
Our templating engine of choice can either be Mustache.jl via `render_html()` or OteraEngine.jl via `render_template()`. This is a very basic implementation and hopefully will be improved with more features.

With these we can pass data from the backend to our frontend html files as below

```julia
using Oxygen
using HTTP

@get "/blog/{title}" function(req::HTTP.Request,title::String)
mylist = [3,5,1]
context = Dict("title" => uppercase(title),"mylist" => mylist)
return render_template("blog.html", context, status=200)
end

serve()

```
This provides the option of using `{{}}` or `{% %}` to render variables from our context or Julia code.

```html
<body>
<div>
<h2>Blog List</h2>
<p>{{ title }}</p>
<div>
{% for i in mylist %}
<ul>
<li> Hello {{i}} {{ title }}</li>
</ul>
{% end %}
</div>
</div>
</body>
```
2 changes: 1 addition & 1 deletion src/Oxygen.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ export @get, @post, @put, @patch, @delete, @route, @cron,
redirect, queryparams, binary, text, json, html, file,
configdocs, mergeschema, setschema, getschema, router,
enabledocs, disabledocs, isdocsenabled, starttasks, stoptasks,
resetstate, startcronjobs, stopcronjobs
resetstate, startcronjobs, stopcronjobs, render_html, render_template
end
55 changes: 55 additions & 0 deletions src/util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module Util
using HTTP
using JSON3
using Dates
using OteraEngine
using Mustache

export countargs, recursive_merge, parseparam, queryparams, html, redirect

Expand Down Expand Up @@ -116,5 +118,58 @@ function redirect(path::String; code = 307) :: HTTP.Response
return HTTP.Response(code, ["Location" => path])
end

"""
render_html(html_file::String,context::Dict)

render html files with or without context data using '{{}}' in the html file
"""
function render_html(html_file::String ,context::Dict = Dict(); status=200, headers = ["Content-Type" => "text/html; charset=utf-8"]) :: HTTP.Response
is_context_empty = isempty(context) === true
# Return the raw HTML content as the response body without context
if is_context_empty
io = open(html_file, "r") do file
read(file, String)
end
template = io |> String
else
# Render the Mustache template with the provided context
io = open(html_file, "r") do file
read(file, String)
end
template = String(Mustache.render(io, context))
end

return HTTP.Response(status, headers, body= template)
end


"""
render_template(html_file::String,context::Dict)

render html files with or without context data using Jinja Like syntax such as
'{{}}'or {% %} in the html file. Allows support for variables and Julia code in html
"""
function render_template(html_file::String ,context::Dict = Dict(); status=200, headers = ["Content-Type" => "text/html; charset=utf-8"]) :: HTTP.Response
is_context_empty = isempty(context) === true
# Return the raw HTML content as the response body without context
if is_context_empty
io = open(html_file, "r") do file
read(file, String)
end
template = io |> String
else
# Render using OteraEngine template with the provided context
io = open(html_file, "r") do file
read(file, String)
end
txt = io |> String
tmp = Template(txt, path = false)
template = tmp(tmp_init = context)
end

return HTTP.Response(status, headers, body= template)
end



end