| Crates.io | prema |
| lib.rs | prema |
| version | 0.2.26 |
| created_at | 2025-04-09 01:26:43.984865+00 |
| updated_at | 2025-10-25 10:44:26.711245+00 |
| description | convert markdown to html |
| homepage | |
| repository | https://github.com/rubinsharks/pretty_mark |
| max_upload_size | |
| id | 1626179 |
| size | 343,844 |
Very simple static site generator from markdown!
Prema is short for Pretty Markdown.
It is based on Tailwind CSS and Flowbite.
You can install this package using Cargo:
cargo install prema
# generate html
# make hierarchy htmls based on selected directory
# make md files to html files in html_directory
prema html {target_directory} {html_directory}
# generate set of md
# make directory of {name} contains {name}.md, option.toml
prema new {name}
When the conversion is performed, it searches subfolders based on the target directory. If an index.toml or index.md file exists inside a folder, an index.html file is generated to create a page. If both files exist, index.toml takes precedence.
In index.toml, the first layout must always be root. Therefore, a root layout must exist, and the structure should be designed so that layouts propagate outward from the root layout.
[root]
shape = "column"
width = "100%"
height = "100%"
dark = false
Layouts have a required shape property and optional properties that can be set as needed: width, height, background, path, value, and dark.
[root.contents]
shape = "column"
width = "200px"
height = "100%"
background = "#000"
path = "#"
value = { skill_title = "1", skill_image = "duck.jpeg", skill_summary = "index.md" }
dark = false
To place a layout as a child of another layout, extend it from the parent layout key. If a sublayout is needed under the root, extend it as root.{} by inserting the desired name inside the {}. Multiple sublayouts can exist.
A sublayout is affected by the structure of its parent layout. If the parent layout is a column, it will be arranged vertically, and if it is a row, it will be arranged horizontally.
[root]
shape = "column"
width = "100%"
height = "100%"
dark = false
[root.child1]
shape = "text"
width = "100%"
height = "wrap"
text = "Title"
color = "#fff"
size = "24px"
weight = "bold"
custom_class = "pl-[20px]"
[root.child2]
shape = "markdown"
width = "100%"
height = "100%"
markdown_path = "title.md"
custom_class = "pl-[20px] pr-[20px]"
In nav, title refers to the text displayed on the left, and headers refers to the menus displayed on the right. Menu labels cannot duplicate reserved keywords in the layout (such as width, height, dark, etc.). If you want to add a submenu to a menu, you can define it like service.etc1 = "" as shown in the example below. If a submenu exists, defining a non-submenu item for the same menu (e.g., service = "") may cause conflicts.
[root.nav]
shape = "nav"
width = "100%"
height = "70px"
title = "STAR"
headers = ["home", "service", "menu", "end", "about me"]
home = "/"
end = "doc"
service.etc1 = "etc1"
service.etc2 = "etc2"
service.etc3 = "etc3"
"about me".my = "about_me/my"
Specifies a parent or current layout that is not included in the root.
This is necessary when the same layout is used across multiple views, typically for setting headers or footers.
Sublayouts can be included, and the arrangement direction is determined by the shape.
[root]
shape = "column"
width = "100%"
height = "100%"
dark = false
In the case of a list, you can specify a layout. The layout specified can receive values through values. The injected values can also be passed to the specified layout’s sublayouts using {}. A layout is generated for each value in values, and whether they are arranged vertically or horizontally is determined by whether it is list_column or list_row.
[root.contents.skills]
shape = "list_row"
width = "100%"
height = "200px"
layout = "skill_layout"
order_by = "skill_title" # title, date, author, ...
values = [
{ skill_title = "1", skill_image = "duck.jpeg", skill_summary = "index.md" },
{ skill_title = "2", skill_image = "2.png", skill_summary = "skill.md" },
{ skill_title = "3", skill_image = "3.png", skill_summary = "1.md" },
{ skill_title = "3", skill_image = "3.png", skill_summary = "1.md" },
{ skill_title = "3", skill_image = "3.png", skill_summary = "1.md" },
{ skill_title = "3", skill_image = "3.png", skill_summary = "1.md" },
{ skill_title = "3", skill_image = "3.png", skill_summary = "1.md" },
{ skill_title = "3", skill_image = "3.png", skill_summary = "1.md" },
]
background = "#0ff"
[skill_layout]
shape = "column"
width = "100px"
height = "250px"
background = "#00f"
[skill_layout.skill_title]
shape = "text"
width = "100%"
height = "wrap"
size = "24px"
text = "{skill_title}"
color = "#fff"
family = "montserrat"
[skill_layout.skill_summary]
shape = "markdown"
width = "100%"
height = "wrap"
markdown_path = "{skill_summary}"
[skill_layout.skill_image]
shape = "image"
width = "200px"
height = "200px"
image_path = "{skill_image}"
content_size = "cover" # cover, contain, fill
Creates a list of Markdown files located in the specified directory.
When the user taps an item in the list, it navigates to the corresponding Markdown file.
The frontmatter and filename of each Markdown file can be accessed and used in the form of {}.
[root]
shape = "column"
width = "100%"
height = "100%"
dark = true
[root.nav]
shape = "embed"
layout = "nav"
[root.contents]
shape = "mdlist_column"
width = "100%"
height = "wrap"
layout = "markdown_row"
files = "*.md"
custom_class = "pl-[20px] pr-[20px]"
[root.footer]
shape = "embed"
layout = "footer"
[markdown_row]
shape = "row"
width = "wrap"
height = "wrap"
[markdown_row.title]
shape = "text"
width = "wrap"
height = "wrap"
size = "16px"
text = "{title}"
path = "{filename}"
color = "#fff"
Text properties such as content, size, font, and alignment can be set. Sublayouts cannot be included.
[root.contents.title]
shape = "text"
width = "wrap"
height = "wrap"
size = "24px"
text = "Jumbotron!"
color = "#000"
family = "montserrat"
weight = "bold"
path = "#"
vertical_align = "center" # top, center, bottom
horizontal_align = "center" # left, center, right
Displays an image and allows setting image_path and content_size. Sublayouts cannot be included.
[skill_layout.skill_image]
shape = "image"
width = "200px"
height = "200px"
image_path = "image.jpeg" # jpeg, jpg, png, svg
content_size = "cover" # cover, contain, fill
A Markdown file can be applied, and markdown_path can be set. Sublayouts cannot be included.
[skill_layout.skill_summary]
shape = "markdown"
width = "100%"
height = "wrap"
markdown_path = "info.md"
If a folder does not have an index.toml configured, index.md is converted instead, and its content is treated as Markdown.
If you want to link to the rust folder, you can do it like this,
[Link](rust "")
If there's a rust folder inside the language directory, you can link to it like this,
[Link](language/rust "")
You can link to it like above.
After adding the image file,

As shown above, simply add an exclamation mark (!), followed by the alt text, and then the file name, such as image.jpeg. The Title section supports Tailwind attributes, allowing you to modify the size and properties of the image.
The following Markdown attributes are supported.
Heading
# Heading Text
## Heading Text
### Heading Text
#### Heading Text
##### Heading Text
###### Heading Text
List
- ItemText
* ItemText
Line
***
---
Link
[Text](MdLink "Title")
[Text](HttpLink "Title")

TextStyle
**Strong**
*Emphasis*
BlockQuote
> Text
Code
⠀``` rust
fn main() {
}
⠀```
Table
| Month | Savings |
| -------- | ------ |
| January | $250 |
| February | $80 |
| March | $420 |
To complement the limitations of Markdown, Frontmatter is supported. The following are the reserved keywords that can be used. For header and footer, a layout must be specified in the parent layout, and the designated names should be targeted.
When custom_class is added to the parent <div> of the Markdown HTML, Tailwind class attributes are supported.
---
title: "Python Minus"
created: 25-10-01
header: nav
footer: footer
dark: false
publish: false
tags: [python, math]
custom_class: mx-auto max-w-screen-xl
---
You can place the Tailwind image attributes in the Title section as shown below. The actual Title itself is not used.
