├── .gitignore ├── Cargo.toml ├── src ├── parse.rs ├── main.rs ├── args.rs └── convert.rs ├── LICENSE ├── README.md ├── examples ├── test.md ├── README.md ├── test.html └── README.html ├── Cargo.lock └── styles └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | debug/ 2 | target/ 3 | **/*.rs.bk 4 | *.pdb 5 | /.vscode -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "makurust" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | pulldown-cmark = "0.9.2" 10 | -------------------------------------------------------------------------------- /src/parse.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | use std::fs::File; 3 | use std::io::prelude::*; 4 | 5 | pub fn parse_file(input_filename: &str) -> Result> { 6 | let mut input_file = File::open(input_filename)?; 7 | let mut input_contents = String::new(); 8 | input_file.read_to_string(&mut input_contents)?; 9 | Ok(input_contents) 10 | } 11 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | mod args; 4 | mod convert; 5 | mod parse; 6 | 7 | fn main() -> Result<(), Box> { 8 | let args = args::parse_args()?; 9 | let input_contents = parse::parse_file(&args.input_filename)?; 10 | let html_output = convert::markdown_to_html(&input_contents); 11 | let output_filename = args.input_filename.replace(".md", ".html"); 12 | convert::write_to_file(html_output, &output_filename)?; 13 | println!("Successfully converted!"); 14 | Ok(()) 15 | } 16 | -------------------------------------------------------------------------------- /src/args.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | pub struct Args { 4 | pub input_filename: String, 5 | } 6 | 7 | pub fn parse_args() -> Result { 8 | let args: Vec = env::args().collect(); 9 | let mut input_filename: Option<&String> = None; 10 | for arg in args.iter().skip(1) { 11 | match arg.as_str() { 12 | "-h" => { 13 | println!("USAGE: makurust filename.md"); 14 | return Err("help"); 15 | } 16 | "-v" => { 17 | println!("Makurust V 0.2beta"); 18 | return Err("version"); 19 | } 20 | _ => input_filename = Some(arg), 21 | } 22 | } 23 | let input_filename = match input_filename { 24 | Some(filename) => filename.to_string(), 25 | None => { 26 | println!("No input file provided!"); 27 | return Err("input file not provided"); 28 | } 29 | }; 30 | Ok(Args { input_filename }) 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Said (Fromgodd) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

Makurust

2 | 3 |

4 | 5 |

6 |

Makurust is a powerful tool written in Rust that allows you to effortlessly convert your Markdown files into static HTML pages. Inspired by Typescript based Makudaun tool that was originially written by Yuri Katsuki. Makurust is designed to make the conversion process as fast and efficient as possible.

7 |

8 | 9 | 10 | ## Usage 11 | To use Makurust, simply run the following command: 12 | ```bash 13 | makurust filename.md 14 | ``` 15 | As a result, an HTML page will be created from the given Markdown file. If the output file already exists, it will be overwritten.
16 | 17 | Makurust was build using third party library - `pulldown-cmark = "0.9.2"` 18 | 19 | ## Installation from git 20 | ```bash 21 | cargo install --locked --git https://github.com/fromgodd/makurust makurust 22 | ``` 23 | 24 | ### What is working 25 | - [X] Basic Markdown Support 26 | - [x] GitHub-like Markdown Style 27 | - [x] Aligning 28 | - [x] Images 29 | - [x] Code snippets 30 | - [x] Checkboxes 31 | 32 | ### Under development 33 | - [ ] Table 34 | - [ ] Syntax highlighting for snippets 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /examples/test.md: -------------------------------------------------------------------------------- 1 |

Makurust Experimental Markdown Page (HTML)

2 | 3 | Markdown to HTML converter written in Rust. Inspired by [Katsuki Yuri's Makudaun Tool](https://github.com/katsuki-yuri/makudaun) 4 |

5 | Special thanks to Yuri Katsuki for providing help in the project

6 | 7 | ## Hello World 8 | "Lorem ipsum" is a placeholder text commonly used in the design and publishing industries as a temporary filler for content that is not yet available. It is typically used to demonstrate the visual effects of different fonts, layouts, and designs without using actual content. 9 | The text itself is derived from a passage in a treatise by the ancient Roman philosopher Cicero, and consists of scrambled Latin words that do not form coherent sentences. Despite its lack of meaning, "Lorem ipsum" has become a standard placeholder text in the design industry and is widely recognized by designers, publishers, and typesetters. 10 | ```rust 11 | use std::io(); 12 | 13 | fn main() { 14 | println!("Sample Rust code"); 15 | let mut userInput = String::new() 16 | io::stdin().read_line(&mut userInput); 17 | ``` 18 | 19 | ## Don't forget to star the project! 20 | 21 |

Dependency used 'pulldown-cmark = "0.9.2'

22 | 23 | ### What is working 24 | - [x] GitHub-like Markdown Style 25 | - [x] Images 26 | - [x] Aligning 27 | - [ ] Checkboxes 28 | - [ ] Table 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 |

Makurust

2 | 3 |

4 | 5 |

6 | Markdown to HTML converter written in Rust. Inspired by Katsuki Yuri's Makudaun Tool 7 |

8 | Special thanks to Yuri Katsuki for providing help in the project

9 | 10 | ## Usage 11 | To use Makurust, simply run the following command: 12 | ```bash 13 | chmod a+x ./makurust 14 | ./makurust filename.md 15 | ``` 16 | As a result, an HTML page will be created from the given Markdown file. If the output file already exists, it will be overwritten. 17 | 18 | ## Building from source 19 | 1. Clone the Makurust repository using Git: 20 | 21 | ```bash 22 | git clone https://github.com/saidofficial/makurust 23 | ``` 24 | 25 | 2. Navigate to the Makurust directory 26 | ```bash 27 | cd makurust 28 | ``` 29 | 30 | 3. Use Cargo to compile the program with optional '--release' flag 31 | ```bash 32 | cargo build --release 33 | ``` 34 | 35 | 4. Run using Cargo run or immediately use binary 36 | - Cargo run 37 | ```bash 38 | cargo run 39 | ``` 40 | 41 | - Using binary after build 42 | ```bash 43 | cd target/release/ 44 | ./makurust 45 | ``` 46 |

Dependency used 'pulldown-cmark = "0.9.2'

47 | 48 | ### What is working 49 | - [x] GitHub-like Markdown Style 50 | - [x] Images 51 | - [x] Aligning 52 | - [ ] Table 53 | 54 | 55 | ### TODO: Implement Table support, ~~Implement panics~~, OS System Err and etc. 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/convert.rs: -------------------------------------------------------------------------------- 1 | use pulldown_cmark::{html, Options, Parser}; 2 | use std::error::Error; 3 | use std::fs; 4 | use std::fs::File; 5 | use std::io::prelude::*; 6 | use std::path::Path; 7 | 8 | pub fn markdown_to_html(input_contents: &str) -> String { 9 | let options = Options::empty(); 10 | let parser = Parser::new_ext(input_contents, options); 11 | let mut html_output = String::new(); 12 | html::push_html(&mut html_output, parser); 13 | html_output 14 | } 15 | 16 | pub fn write_to_file(html_output: String, output_filename: &str) -> Result<(), Box> { 17 | // If we are in the git repo or someone has provided a css file near their working directory we can use that. 18 | // Otherwise use the one included at compile time. 19 | let css = if Path::new("styles/style.css").exists() { 20 | fs::read_to_string("styles/style.css")? 21 | } else { 22 | DEFAULT_CSS.to_string() 23 | }; 24 | 25 | let precontent = format!( 26 | r#" 27 | 28 | {} 29 | 30 | 33 | 34 | 35 |
"#, 36 | output_filename.replace(".md", ""), 37 | css, 38 | ); 39 | let postcontent = r#" 40 |
41 | 42 | "#; 43 | let mut output_file = File::create(output_filename)?; 44 | write!(output_file, "{}{}{}", precontent, html_output, postcontent)?; 45 | Ok(()) 46 | } 47 | 48 | // Include the default css at compile time so it doesn't matter where the binary ends up it will always be able to find 49 | // this file. 50 | const DEFAULT_CSS: &str = include_str!("../styles/style.css"); 51 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "bitflags" 7 | version = "1.3.2" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 10 | 11 | [[package]] 12 | name = "getopts" 13 | version = "0.2.21" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" 16 | dependencies = [ 17 | "unicode-width", 18 | ] 19 | 20 | [[package]] 21 | name = "makurust" 22 | version = "0.1.0" 23 | dependencies = [ 24 | "pulldown-cmark", 25 | ] 26 | 27 | [[package]] 28 | name = "memchr" 29 | version = "2.5.0" 30 | source = "registry+https://github.com/rust-lang/crates.io-index" 31 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 32 | 33 | [[package]] 34 | name = "pulldown-cmark" 35 | version = "0.9.2" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63" 38 | dependencies = [ 39 | "bitflags", 40 | "getopts", 41 | "memchr", 42 | "unicase", 43 | ] 44 | 45 | [[package]] 46 | name = "unicase" 47 | version = "2.6.0" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" 50 | dependencies = [ 51 | "version_check", 52 | ] 53 | 54 | [[package]] 55 | name = "unicode-width" 56 | version = "0.1.10" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 59 | 60 | [[package]] 61 | name = "version_check" 62 | version = "0.9.4" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 65 | -------------------------------------------------------------------------------- /styles/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | font: 400 16px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; 3 | color: #111; 4 | background-color: #fdfdfd; 5 | -webkit-text-size-adjust: 100%; 6 | -webkit-font-feature-settings: "kern" 1; 7 | -moz-font-feature-settings: "kern" 1; 8 | -o-font-feature-settings: "kern" 1; 9 | font-feature-settings: "kern" 1; 10 | font-kerning: normal; 11 | padding: 30px; 12 | } 13 | 14 | @media only screen and (max-width: 600px) { 15 | body { 16 | padding: 5px; 17 | } 18 | 19 | body > #content { 20 | padding: 0px 20px 20px 20px !important; 21 | } 22 | } 23 | 24 | body > #content { 25 | margin: 0px; 26 | max-width: 900px; 27 | border: 1px solid #e1e4e8; 28 | padding: 10px 40px; 29 | padding-bottom: 20px; 30 | border-radius: 15px; 31 | margin-left: auto; 32 | margin-right: auto; 33 | } 34 | 35 | hr { 36 | color: #bbb; 37 | background-color: #bbb; 38 | height: 1px; 39 | flex: 0 1 auto; 40 | margin: 1em 0; 41 | padding: 0; 42 | border: none; 43 | } 44 | 45 | a { 46 | color: #0366d6; 47 | text-decoration: none; 48 | } 49 | 50 | a:visited { 51 | color: #0366d6; 52 | } 53 | 54 | a:hover { 55 | color: #0366d6; 56 | text-decoration: underline; 57 | } 58 | 59 | pre { 60 | background-color: #f6f8fa; 61 | border-radius: 3px; 62 | font-size: 85%; 63 | line-height: 1.45; 64 | overflow: auto; 65 | padding: 16px; 66 | } 67 | 68 | code { 69 | background-color: rgba(27,31,35,.05); 70 | border-radius: 3px; 71 | font-size: 85%; 72 | margin: 0; 73 | word-wrap: break-word; 74 | padding: .2em .4em; 75 | font-family: SFMono-Regular,Consolas,Liberation Mono,Menlo,Courier,monospace; 76 | } 77 | 78 | pre > code { 79 | background-color: transparent; 80 | border: 0; 81 | display: inline; 82 | line-height: inherit; 83 | margin: 0; 84 | overflow: visible; 85 | padding: 0; 86 | word-wrap: normal; 87 | font-size: 100%; 88 | } 89 | 90 | blockquote { 91 | margin-left: 30px; 92 | margin-top: 0px; 93 | margin-bottom: 16px; 94 | border-left-width: 3px; 95 | padding: 0 1em; 96 | color: #828282; 97 | border-left: 4px solid #e8e8e8; 98 | padding-left: 15px; 99 | font-size: 18px; 100 | letter-spacing: -1px; 101 | font-style: italic; 102 | } 103 | 104 | blockquote * { 105 | font-style: normal !important; 106 | letter-spacing: 0; 107 | color: #6a737d !important; 108 | } 109 | 110 | table { 111 | border-spacing: 2px; 112 | display: block; 113 | font-size: 14px; 114 | overflow: auto; 115 | width: 100%; 116 | margin-bottom: 16px; 117 | border-spacing: 0; 118 | border-collapse: collapse; 119 | } 120 | 121 | td { 122 | padding: 6px 13px; 123 | border: 1px solid #dfe2e5; 124 | } 125 | 126 | th { 127 | font-weight: 600; 128 | padding: 6px 13px; 129 | border: 1px solid #dfe2e5; 130 | } 131 | 132 | tr { 133 | background-color: #fff; 134 | border-top: 1px solid #c6cbd1; 135 | } 136 | 137 | table tr:nth-child(2n) { 138 | background-color: #f6f8fa; 139 | } 140 | 141 | img { 142 | max-width: 100%; 143 | } 144 | 145 | p { 146 | line-height: 24px; 147 | font-weight: 400; 148 | font-size: 16px; 149 | color: #24292e; 150 | } 151 | 152 | ul { 153 | margin-top: 0; 154 | } 155 | 156 | li { 157 | color: #24292e; 158 | font-size: 16px; 159 | font-weight: 400; 160 | line-height: 1.5; 161 | } 162 | 163 | li + li { 164 | margin-top: 0.25em; 165 | } 166 | 167 | * { 168 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; 169 | color: #24292e; 170 | } 171 | 172 | a:visited { 173 | color: #0366d6; 174 | } 175 | 176 | h1, h2, h3 { 177 | border-bottom: 1px solid #eaecef; 178 | color: #111; 179 | } -------------------------------------------------------------------------------- /examples/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | test 4 | 5 | 6 | 7 |

Makurust Experimental Markdown Page (HTML)

8 |

Markdown to HTML converter written in Rust. Inspired by Katsuki Yuri's Makudaun Tool

9 |

10 | Special thanks to Yuri Katsuki for providing help in the project

11 |

Hello World

12 |

"Lorem ipsum" is a placeholder text commonly used in the design and publishing industries as a temporary filler for content that is not yet available. It is typically used to demonstrate the visual effects of different fonts, layouts, and designs without using actual content. 13 | The text itself is derived from a passage in a treatise by the ancient Roman philosopher Cicero, and consists of scrambled Latin words that do not form coherent sentences. Despite its lack of meaning, "Lorem ipsum" has become a standard placeholder text in the design industry and is widely recognized by designers, publishers, and typesetters.

14 |
use std::io();
 15 | 
 16 | fn main() {
 17 | 	println!("Sample Rust code");
 18 | 	let mut userInput = String::new()
 19 | 	io::stdin().read_line(&mut userInput);
 20 | 
21 |

Don't forget to star the project!

22 |

Dependency used 'pulldown-cmark = "0.9.2'

23 |

What is working

24 |
    25 |
  • [x] GitHub-like Markdown Style
  • 26 |
  • [x] Images
  • 27 |
  • [x] Aligning
  • 28 |
  • [ ] Checkboxes
  • 29 |
  • [ ] Table
  • 30 |
31 | 32 |
33 | 214 | 215 | -------------------------------------------------------------------------------- /examples/README.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | README 4 | 5 | 6 | 7 |

Makurust

8 |

9 | 10 |

11 | Markdown to HTML converter written in Rust. Inspired by Katsuki Yuri's Makudaun Tool 12 |

13 | Special thanks to Yuri Katsuki for providing help in the project

14 |

Usage

15 |

To use Makurust, simply run the following command:

16 |
chmod a+x ./makurust
 17 | ./makurust filename.md
 18 | 
19 |

As a result, an HTML page will be created from the given Markdown file. If the output file already exists, it will be overwritten.

20 |

Building from source

21 |
    22 |
  1. Clone the Makurust repository using Git:
  2. 23 |
24 |
git clone https://github.com/saidofficial/makurust
 25 | 
26 |
    27 |
  1. Navigate to the Makurust directory
  2. 28 |
29 |
cd makurust
 30 | 
31 |
    32 |
  1. Use Cargo to compile the program with optional '--release' flag
  2. 33 |
34 |
cargo build --release
 35 | 
36 |
    37 |
  1. Run using Cargo run or immediately use binary
  2. 38 |
39 |
    40 |
  • Cargo run
  • 41 |
42 |
cargo run
 43 | 
44 |
    45 |
  • Using binary after build
  • 46 |
47 |
cd target/release/
 48 | ./makurust
 49 | 
50 |

Dependency used 'pulldown-cmark = "0.9.2'

51 |

What is working

52 |
    53 |
  • [x] GitHub-like Markdown Style
  • 54 |
  • [x] Images
  • 55 |
  • [x] Aligning
  • 56 |
  • [ ] Table
  • 57 |
58 |

TODO: Implement Table support, ~~Implement panics~~, OS System Err and etc.

59 | 60 |
61 | 242 | 243 | --------------------------------------------------------------------------------