├── .gitignore
├── .gitmodules
├── .vscode
└── settings.json
├── Cargo.toml
├── LICENSE
├── README.md
├── assets
└── logo.png
├── clippy.toml
├── crates
├── kurit-js
│ ├── Cargo.toml
│ └── src
│ │ ├── cli.js
│ │ └── lib.rs
├── kurit-ops
│ ├── Cargo.toml
│ └── src
│ │ ├── fs.rs
│ │ └── lib.rs
├── kurit-runtime
│ ├── Cargo.toml
│ └── src
│ │ ├── lib.kurit.d.ts
│ │ ├── lib.rs
│ │ └── runtime.js
├── kurit-template
│ ├── Cargo.toml
│ └── src
│ │ └── lib.rs
└── kurit
│ ├── Cargo.toml
│ └── src
│ └── main.rs
├── deny.toml
├── docs
├── CNAME
├── README.md
├── _config.yml
├── _includes
│ └── head.html
├── _layouts
│ └── default.html
├── assets
│ ├── android-icon-144x144.png
│ ├── android-icon-192x192.png
│ ├── android-icon-36x36.png
│ ├── android-icon-48x48.png
│ ├── android-icon-72x72.png
│ ├── android-icon-96x96.png
│ ├── apple-icon-114x114.png
│ ├── apple-icon-120x120.png
│ ├── apple-icon-144x144.png
│ ├── apple-icon-152x152.png
│ ├── apple-icon-180x180.png
│ ├── apple-icon-57x57.png
│ ├── apple-icon-60x60.png
│ ├── apple-icon-72x72.png
│ ├── apple-icon-76x76.png
│ ├── apple-icon-precomposed.png
│ ├── apple-icon.png
│ ├── browserconfig.xml
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── favicon-96x96.png
│ ├── favicon.ico
│ ├── manifest.json
│ ├── mermaid-chart.png
│ ├── ms-icon-144x144.png
│ ├── ms-icon-150x150.png
│ ├── ms-icon-310x310.png
│ └── ms-icon-70x70.png
└── robots.txt
├── rust-toolchain.toml
└── tests
├── profile.html
└── profile.md
/.gitignore:
--------------------------------------------------------------------------------
1 | # Generated by Cargo
2 | # will have compiled files and executables
3 | debug/
4 | target/
5 |
6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
8 | Cargo.lock
9 |
10 | # These are backup files generated by rustfmt
11 | **/*.rs.bk
12 |
13 | # MSVC Windows builds of rustc generate these, which store debugging information
14 | *.pdb
15 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "crates/kurit-template/src/deps/normailze.css"]
2 | path = crates/kurit-template/src/deps/normailze.css
3 | url = https://github.com/necolas/normalize.css.git
4 | [submodule "crates/kurit-devserver"]
5 | path = crates/kurit-devserver
6 | url = https://github.com/AkiaCode/kurit-devserver.git
7 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | // Rust
3 | "rust-analyzer.linkedProjects": [
4 | "./crates/kurit/Cargo.toml",
5 | "./crates/kurit-js/Cargo.toml",
6 | "./crates/kurit-ops/Cargo.toml",
7 | "./crates/kurit-runtime/Cargo.toml",
8 | "./crates/kurit-template/Cargo.toml",
9 | "./crates/kurit-devserver/Cargo.toml",
10 | ],
11 | "rust-analyzer.showUnlinkedFileNotification": false,
12 | // Deno
13 | "deno.enablePaths": ["./crates/kurit-runtime/src/runtime.js"],
14 | "deno.lint": true,
15 | "deno.path" : "/opt/homebrew/bin/deno"
16 | }
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [workspace]
2 | resolver = "2"
3 | members = ["crates/*"]
4 | exclude = ["docs/*", "tests/*", "assets/*", ".vscode/*"]
5 |
6 | [workspace.dependencies]
7 | deno_core = { version = "0.222.0", default-features = false }
8 | tokio = { version = "1.32.0", default-features = false }
9 |
10 | kurit-js = { path = "./crates/kurit-js" }
11 | kurit-ops = { path = "./crates/kurit-ops" }
12 | kurit-runtime = { path = "./crates/kurit-runtime"}
13 | kurit-template = { path = "./crates/kurit-template"}
14 | kurit-devserver = { path = "./crates/kurit-devserver" }
15 |
16 | # ref: https://github.com/johnthagen/min-sized-rust
17 | [profile.release]
18 | strip = true
19 | opt-level = "z"
20 | lto = true
21 | codegen-units = 1
22 | panic = "abort"
23 | debug = false
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2023 AkiaCode
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Kurit
2 |
3 |
4 |
Static website generator :rocket:
5 |
6 |
7 | > [!WARNING]
8 | > **WIP**: It is still under development, so some of the features may not be developed.
9 |
10 | ## Project Structures
11 | ```mermaid
12 | graph TD;
13 | kurit-runtime-->kurit;
14 | kurit-ops-->kurit-runtime;
15 | kurit-js-->kurit-runtime;
16 | lib.kurit.d.ts-->kurit-js;
17 | runtime.js-->kurit-js;
18 | kurit-filesystem-->kurit-ops;
19 | kurit-devserver-->kurit-ops;
20 | ```
21 |
22 | ## Installation
23 | ```sh
24 | cargo install kurit
25 | ```
26 |
27 | ## Clone
28 | ```sh
29 | ~/$ git clone --recursive https://github.com/AkiaCode/kurit && cd ./kurit
30 | ```
31 |
32 | ## Build
33 | ```sh
34 | ~/kurit$ cargo run --release -- build ./tests/profile.md
35 | Compiling kurit-ops v0.1.0 (/Volumes/Seritka/github/kurit/crates/kurit-ops)
36 | Compiling kurit-runtime v0.1.0 (/Volumes/Seritka/github/kurit/crates/kurit-runtime)
37 | Compiling kurit v0.1.0 (/Volumes/Seritka/github/kurit/crates/kurit)
38 | Finished release [optimized] target(s) in 9.78s
39 | Running `target/release/kurit build ./tests/profile.md`
40 | Finish...🚀
41 | ```
42 |
43 | ## Serve
44 | ```sh
45 | ~/kurit$ cargo run --release -- serve ./tests/profile.html
46 | Compiling kurit-js v0.1.0 (/Volumes/Seritka/github/kurit/crates/kurit-js)
47 | Compiling kurit-runtime v0.1.0 (/Volumes/Seritka/github/kurit/crates/kurit-runtime)
48 | Compiling kurit v0.1.0 (/Volumes/Seritka/github/kurit/crates/kurit)
49 | Finished release [optimized] target(s) in 8.77s
50 | Running `target/release/kurit serve ./tests/profile.html`
51 | [kurit-log]: Serving ./tests/profile.html at http://localhost:4101/profile.html
52 | ```
53 |
54 | ## Run
55 | ```sh
56 | ~/kurit$ cargo run --release
57 | ```
58 | ## Features (not yet)
59 |
60 | ### Single executable
61 | ```sh
62 | ~/kurit$ ldd ./target/debug/kurit
63 | linux-vdso.so.1 (0x00007ffddadfe000)
64 | libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fe2123e0000)
65 | libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fe2122f9000)
66 | libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe212000000)
67 | /lib64/ld-linux-x86-64.so.2 (0x00007fe2146df000)
68 | ```
69 |
70 | ### Small File
71 | ```sh
72 | ~/kurit$ cargo bloat --release --crates -n 10
73 | Compiling kurit-ops v0.1.0 (/Volumes/Seritka/github/kurit/crates/kurit-ops)
74 | Compiling kurit-runtime v0.1.0 (/Volumes/Seritka/github/kurit/crates/kurit-runtime)
75 | Compiling kurit v0.1.0 (/Volumes/Seritka/github/kurit/crates/kurit)
76 | Finished release [optimized] target(s) in 15.91s
77 | Analyzing target/release/kurit
78 |
79 | File .text Size Crate
80 | 56.3% 100.1% 17.0MiB [Unknown]
81 | 56.3% 100.0% 17.0MiB .text section size, the file size is 30.2MiB
82 |
83 | Note: numbers above are a result of guesswork. They are not 100% correct and never will be.
84 | ```
85 |
86 | ### Zero-config
87 |
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AkiaCode/kurit/84c5116403d6f25910d8e72c6ee0efd51318a7c3/assets/logo.png
--------------------------------------------------------------------------------
/clippy.toml:
--------------------------------------------------------------------------------
1 | cognitive-complexity-threshold = 50
2 | disallowed-names = [
3 | "bool",
4 | "char",
5 | "str",
6 | "f32",
7 | "f64",
8 | "i8",
9 | "i16",
10 | "i32",
11 | "i64",
12 | "u8",
13 | "u16",
14 | "u32",
15 | "u64",
16 | "isize",
17 | "usize",
18 | ]
19 | msrv = "1.58"
20 | type-complexity-threshold = 25000
--------------------------------------------------------------------------------
/crates/kurit-js/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "kurit-js"
3 | version = "0.1.0"
4 | edition = "2021"
5 | description = "Kurit.js"
6 | license = "Apache-2.0"
7 | repository = "https://github.com/AkiaCode/kurit/tree/main/crates/kurit-js"
8 |
9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
10 |
11 | [dependencies]
12 |
--------------------------------------------------------------------------------
/crates/kurit-js/src/cli.js:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | const args = Kurit.args.slice(1) // kurit [subcommand] [...args]
4 |
5 | switch (args[0]) { // SubCommands
6 | case 'build':
7 | {
8 | const path = args[1]
9 | const filename = path.substring(path.lastIndexOf('/')+1).replace('.md', '')
10 | const contents = Kurit.md_to_html(filename, await Kurit.fs.readFile(path))
11 | await Kurit.fs.writeFile(path.replace('.md', '.html'), contents)
12 | console.log('Finish...🚀')
13 | }
14 | break
15 | case 'serve':
16 | if (!(args.length === 2)) { // args not found
17 | console.error('File Not Found')
18 | break
19 | }
20 | { // scope
21 | const path = args[1]
22 | Kurit.log(`Serving ${path} at http://localhost:4101/${path.substring(path.lastIndexOf('/')+1)}`)
23 | Kurit.devserver(path)
24 | }
25 | break
26 | case 'version':
27 | console.log(Kurit.version)
28 | break
29 | case 'about':
30 | console.log(Kurit.about)
31 | break
32 | case 'help': // Help Command
33 | default:
34 | console.log(`Kurit ${Kurit.version}
35 |
36 | Commands:
37 | build [path] - Markdown to HTML
38 | serve [path] - Display HTML on the devserver
39 | version - Kurit Version
40 | about - Kurit About
41 | `)
42 | }
43 |
--------------------------------------------------------------------------------
/crates/kurit-js/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub const CLI_CODE: &str = include_str!("cli.js");
2 |
--------------------------------------------------------------------------------
/crates/kurit-ops/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "kurit-ops"
3 | version = "0.1.0"
4 | edition = "2021"
5 | description = "Kurit Ops"
6 | license = "Apache-2.0"
7 | repository = "https://github.com/AkiaCode/kurit/tree/main/crates/kurit-ops"
8 |
9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
10 |
11 | [dependencies]
12 | deno_core.workspace = true
13 | tokio.workspace = true
14 | kurit-template.workspace = true
15 | kurit-devserver.workspace = true
16 |
17 | markdown = "1.0.0-alpha.14"
18 |
--------------------------------------------------------------------------------
/crates/kurit-ops/src/fs.rs:
--------------------------------------------------------------------------------
1 | use deno_core::{error::AnyError, op2};
2 |
3 | #[op2]
4 | #[string]
5 | pub fn op_fs_version() -> String {
6 | "0.0.1-alpha".into()
7 | }
8 |
9 | #[op2(async)]
10 | #[string]
11 | pub async fn op_read_file(#[string] path: String) -> Result {
12 | let contents = tokio::fs::read_to_string(path).await?;
13 | Ok(contents)
14 | }
15 |
16 | #[op2(async)]
17 | #[string]
18 | pub async fn op_write_file(
19 | #[string] path: String,
20 | #[string] contents: String,
21 | ) -> Result<(), AnyError> {
22 | tokio::fs::write(path, contents).await?;
23 | Ok(())
24 | }
25 |
26 | #[op2(async)]
27 | #[string]
28 | pub async fn op_remove_file(#[string] path: String) -> Result<(), AnyError> {
29 | tokio::fs::remove_file(path).await?;
30 | Ok(())
31 | }
32 |
--------------------------------------------------------------------------------
/crates/kurit-ops/src/lib.rs:
--------------------------------------------------------------------------------
1 | use std::path::Path;
2 |
3 | use deno_core::{
4 | error::{bad_resource_id, generic_error, AnyError},
5 | op2, Extension, Op, OpState,
6 | };
7 | use kurit_template::{KuritDefault, Template, Templates};
8 | use markdown::Options;
9 | mod fs;
10 |
11 | pub fn ops_extension() -> Extension {
12 | Extension {
13 | name: "kuritjs",
14 | ops: vec![
15 | op_version::DECL,
16 | op_args::DECL,
17 | op_md_to_html::DECL,
18 | op_template::DECL,
19 | op_devserver::DECL,
20 | crate::fs::op_fs_version::DECL,
21 | crate::fs::op_read_file::DECL,
22 | crate::fs::op_write_file::DECL,
23 | crate::fs::op_remove_file::DECL,
24 | ]
25 | .into(),
26 | ..Default::default()
27 | }
28 | }
29 |
30 | #[op2]
31 | #[string]
32 | fn op_version() -> String {
33 | "0.1.0-beta".into()
34 | }
35 |
36 | #[op2]
37 | #[string]
38 | fn op_args(_state: &mut OpState) -> String {
39 | let args = std::env::args();
40 | args.collect::>().join(" ")
41 | }
42 |
43 | #[op2]
44 | #[string]
45 | fn op_md_to_html(
46 | _state: &mut OpState,
47 | #[string] name: String,
48 | #[string] contents: &str,
49 | ) -> Result {
50 | let html = markdown::to_html_with_options(
51 | contents,
52 | &Options {
53 | compile: markdown::CompileOptions {
54 | allow_dangerous_html: true,
55 | allow_dangerous_protocol: true,
56 | ..markdown::CompileOptions::default()
57 | },
58 | ..Options::default()
59 | },
60 | )
61 | .map_err(generic_error)?;
62 | // TODO: Change Template API
63 | //if let Some(tmpl) = state.try_take::() {
64 | // Templates::to_tmpl(tmpl).html(name, html);
65 | //}
66 | Ok(KuritDefault::new().html(name, html))
67 | }
68 |
69 | #[op2(fast)]
70 | fn op_template(state: &mut OpState, #[string] name: String) -> Result<(), AnyError> {
71 | if let Some(name) = kurit_template::Templates::check(name) {
72 | state.put::(name);
73 | Ok(())
74 | } else {
75 | Err(bad_resource_id())
76 | }
77 | }
78 |
79 | #[op2(fast)]
80 | fn op_devserver(#[string] path: String) -> Result<(), AnyError> {
81 | let path = if let Some(path) = Path::new(&path).parent() {
82 | path.to_string_lossy()
83 | } else {
84 | std::borrow::Cow::Borrowed("./")
85 | };
86 | kurit_devserver::run("localhost", 4101, &path, false, "\n\rServer: Kurit");
87 | Ok(())
88 | }
89 |
--------------------------------------------------------------------------------
/crates/kurit-runtime/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "kurit-runtime"
3 | version = "0.1.0"
4 | edition = "2021"
5 | description = "Kurit Runtime"
6 | license = "Apache-2.0"
7 | repository = "https://github.com/AkiaCode/kurit/tree/main/crates/kurit-runtime"
8 |
9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
10 |
11 | [dependencies]
12 | deno_core.workspace = true
13 | tokio.workspace = true
14 | kurit-js.workspace = true
15 | kurit-ops.workspace = true
16 |
--------------------------------------------------------------------------------
/crates/kurit-runtime/src/lib.kurit.d.ts:
--------------------------------------------------------------------------------
1 | declare namespace Kurit {
2 | /**
3 | * Kurit Args
4 | */
5 | export const args: String[]
6 | /**
7 | * Kurit Version
8 | */
9 | export const version: String
10 | /**
11 | * Kurit About
12 | */
13 | export const about: String
14 | /**
15 | * Kurit Console API
16 | * @param args
17 | */
18 | export function log(...args: any): void
19 | export function warn(...args: any): void
20 | export function error(...args: any): void
21 | /**
22 | * Kurit DevServer
23 | * @param path Path with .html extension
24 | */
25 | export function devserver(path: String): void
26 | /**
27 | * Markdown to HTML
28 | * @param name WebSite Name
29 | * @param contents Markdown File Contents
30 | * @returns {(String|Error)}
31 | */
32 | export function md_to_html(name: String, contents: String): String | Error
33 | /**
34 | * Kurit File System API
35 | */
36 | export module fs {
37 | export function readFile(path: String): Promise
38 | export function writeFile(path: String, contents: String): Promise
39 | export function removeFile(path: String): Promise
40 | /**
41 | * KuritFS Version
42 | */
43 | export const version: String
44 | }
45 | /**
46 | * (Private) Kurit Ops API
47 | */
48 | module ops {
49 | /**
50 | * KuritOps Version
51 | */
52 | const version: String
53 | }
54 | }
--------------------------------------------------------------------------------
/crates/kurit-runtime/src/lib.rs:
--------------------------------------------------------------------------------
1 | use std::{path::Path, rc::Rc};
2 |
3 | use deno_core::error::AnyError;
4 |
5 | pub struct Runtime {}
6 |
7 | impl Default for Runtime {
8 | fn default() -> Self {
9 | Self::new()
10 | }
11 | }
12 |
13 | impl Runtime {
14 | pub fn new() -> Self {
15 | Self {}
16 | }
17 |
18 | async fn run_js(self, file_path: &str, current_dir: &Path) -> Result<(), AnyError> {
19 | let main_module = deno_core::resolve_path(file_path, current_dir)?;
20 | let mut js_runtime = deno_core::JsRuntime::new(deno_core::RuntimeOptions {
21 | module_loader: Some(Rc::new(deno_core::FsModuleLoader)),
22 | extensions: vec![kurit_ops::ops_extension()],
23 | ..Default::default()
24 | });
25 | js_runtime
26 | .execute_script(
27 | "[kurit:runtime.js]",
28 | include_str!("./runtime.js").to_owned().into(),
29 | )
30 | .unwrap();
31 | let mod_id = js_runtime
32 | .load_main_module(&main_module, Some(kurit_js::CLI_CODE.to_owned().into()))
33 | .await?;
34 | let result = js_runtime.mod_evaluate(mod_id);
35 | js_runtime.run_event_loop(false).await?;
36 | result.await?
37 | }
38 |
39 | pub fn run(self, current_dir: &Path) {
40 | let runtime = tokio::runtime::Builder::new_current_thread()
41 | .enable_all()
42 | .build()
43 | .unwrap();
44 | if let Err(error) = runtime.block_on(self.run_js("src/cli.js", current_dir)) {
45 | eprintln!("{}", error);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/crates/kurit-runtime/src/runtime.js:
--------------------------------------------------------------------------------
1 | ((globalThis) => {
2 | const core = Deno.core;
3 | const { ops } = core;
4 |
5 | globalThis.console = {
6 | log: (...args) => {
7 | core.print(`${args}\n`, false)
8 | },
9 | error: (...args) => {
10 | core.print(`KuritError: ${args}\n`, true)
11 | },
12 | }
13 |
14 | globalThis.Kurit = {
15 | fs: { // Kurit File System
16 | readFile: (path) => {
17 | return ops.op_read_file(path)
18 | },
19 | writeFile: (path, contents) => {
20 | return ops.op_write_file(path, contents)
21 | },
22 | removeFile: (path) => {
23 | return ops.op_remove_file(path)
24 | },
25 | get version() { // Kurit FS Version
26 | return ops.op_fs_version()
27 | },
28 | },
29 | ops: { // Kurit Ops
30 | get version() { // Kurit Ops Version
31 | return ops.op_version()
32 | }
33 | },
34 | // Kurit Console
35 | log: (...args) => {
36 | core.print(`[kurit-log]: ${args}\n`, false)
37 | },
38 | warn: (...args) => {
39 | core.print(`[kurit-warn]: ${args}\n`, false)
40 | },
41 | error: (...args) => {
42 | core.print(`[kurit-error]: ${args}\n`, true)
43 | },
44 | // Kurit HTML
45 | md_to_html: (name, contents) => {
46 | return ops.op_md_to_html(name, contents)
47 | },
48 | devserver: (path) => {
49 | return ops.op_devserver(path)
50 | },
51 | // Kurit Utils
52 | get version() { // Kurit Runtime Version
53 | return "0.1.0"
54 | },
55 | get args() {
56 | const args = ops.op_args()
57 | return args.split(' ') // String to Array
58 | },
59 | get about() {
60 | return `Kurit Version\n\nKuritFS: ${Kurit.fs.version}\nKuritOps: ${Kurit.ops.version}\nKuritRuntime: ${Kurit.version}`
61 | }
62 | }
63 |
64 | delete Deno.core // We Love Deno!
65 | })(globalThis)
--------------------------------------------------------------------------------
/crates/kurit-template/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "kurit-template"
3 | version = "0.1.0"
4 | edition = "2021"
5 | description = "Kurit Template"
6 | license = "Apache-2.0"
7 | repository = "https://github.com/AkiaCode/kurit/tree/main/crates/kurit-template"
8 |
9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
10 |
11 | [dependencies]
12 |
--------------------------------------------------------------------------------
/crates/kurit-template/src/lib.rs:
--------------------------------------------------------------------------------
1 | pub trait Template {
2 | fn new() -> Self
3 | where
4 | Self: Sized;
5 | fn css(&self) -> String;
6 | fn html(&self, title: String, body: String) -> String;
7 | }
8 |
9 | // TODO: Make Template System
10 | pub enum Templates {
11 | Default,
12 | Kafu,
13 | }
14 |
15 | impl Templates {
16 | pub fn check(name: String) -> Option {
17 | match name.to_lowercase().as_str() {
18 | "default" => Some(Templates::Default),
19 | "kafu" => Some(Templates::Kafu),
20 | _ => None,
21 | }
22 | }
23 |
24 | pub fn to_tmpl(tmpl: Templates) -> Box {
25 | match tmpl {
26 | Templates::Default => Box::new(KuritDefault::new()),
27 | Templates::Kafu => Box::new(Kafu::new()),
28 | }
29 | }
30 | }
31 |
32 | pub struct Kafu {}
33 |
34 | impl Template for Kafu {
35 | fn new() -> Self {
36 | Kafu {}
37 | }
38 | fn css(&self) -> String {
39 | include_str!("deps/normailze.css/normalize.css").into()
40 | }
41 |
42 | fn html(&self, title: String, body: String) -> String {
43 | format!(
44 | "
45 |
46 |
49 | {title}
50 |
51 |
52 | {body}
53 |
54 | ",
55 | css = self.css()
56 | )
57 | }
58 | }
59 |
60 | pub struct KuritDefault {}
61 |
62 | impl Template for KuritDefault {
63 | fn new() -> Self {
64 | KuritDefault {}
65 | }
66 | fn css(&self) -> String {
67 | "".into()
68 | }
69 | fn html(&self, title: String, body: String) -> String {
70 | format!(
71 | "
72 |
73 |
76 | {title}
77 |
78 |
79 | {body}
80 |
81 | ",
82 | css = self.css()
83 | )
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/crates/kurit/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "kurit"
3 | version = "0.1.0"
4 | edition = "2021"
5 | description = "Static website generator"
6 | license = "Apache-2.0"
7 | repository = "https://github.com/AkiaCode/kurit/tree/main/crates/kurit"
8 |
9 | [[bin]]
10 | name = "kurit"
11 | path = "src/main.rs"
12 |
13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
14 |
15 | [dependencies]
16 | kurit-runtime.workspace = true
--------------------------------------------------------------------------------
/crates/kurit/src/main.rs:
--------------------------------------------------------------------------------
1 | fn main() -> Result<(), std::io::Error> {
2 | let kurit = kurit_runtime::Runtime::new();
3 | kurit.run(std::env::current_dir()?.join("crates/kurit-js").as_path());
4 |
5 | Ok(())
6 | }
7 |
--------------------------------------------------------------------------------
/deny.toml:
--------------------------------------------------------------------------------
1 | # This template contains all of the possible sections and their default values
2 |
3 | # Note that all fields that take a lint level have these possible values:
4 | # * deny - An error will be produced and the check will fail
5 | # * warn - A warning will be produced, but the check will not fail
6 | # * allow - No warning or error will be produced, though in some cases a note
7 | # will be
8 |
9 | # The values provided in this template are the default values that will be used
10 | # when any section or field is not specified in your own configuration
11 |
12 | # If 1 or more target triples (and optionally, target_features) are specified,
13 | # only the specified targets will be checked when running `cargo deny check`.
14 | # This means, if a particular package is only ever used as a target specific
15 | # dependency, such as, for example, the `nix` crate only being used via the
16 | # `target_family = "unix"` configuration, that only having windows targets in
17 | # this list would mean the nix crate, as well as any of its exclusive
18 | # dependencies not shared by any other crates, would be ignored, as the target
19 | # list here is effectively saying which targets you are building for.
20 | targets = []
21 |
22 | # This section is considered when running `cargo deny check advisories`
23 | # More documentation for the advisories section can be found here:
24 | # https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
25 | [advisories]
26 | # The path where the advisory database is cloned/fetched into
27 | db-path = "~/.cargo/advisory-db"
28 | # The url(s) of the advisory databases to use
29 | db-urls = ["https://github.com/rustsec/advisory-db"]
30 | # The lint level for security vulnerabilities
31 | vulnerability = "deny"
32 | # The lint level for unmaintained crates
33 | unmaintained = "warn"
34 | # The lint level for crates that have been yanked from their source registry
35 | yanked = "warn"
36 | # The lint level for crates with security notices. Note that as of
37 | # 2019-12-17 there are no security notice advisories in
38 | # https://github.com/rustsec/advisory-db
39 | notice = "warn"
40 | # A list of advisory IDs to ignore. Note that ignored advisories will still
41 | # output a note when they are encountered.
42 | ignore = [
43 | #"RUSTSEC-0000-0000",
44 | "RUSTSEC-2020-0071",
45 | "RUSTSEC-2020-0159",
46 | ]
47 | # Threshold for security vulnerabilities, any vulnerability with a CVSS score
48 | # lower than the range specified will be ignored. Note that ignored advisories
49 | # will still output a note when they are encountered.
50 | # * None - CVSS Score 0.0
51 | # * Low - CVSS Score 0.1 - 3.9
52 | # * Medium - CVSS Score 4.0 - 6.9
53 | # * High - CVSS Score 7.0 - 8.9
54 | # * Critical - CVSS Score 9.0 - 10.0
55 | #severity-threshold =
56 |
57 | # This section is considered when running `cargo deny check licenses`
58 | # More documentation for the licenses section can be found here:
59 | # https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
60 | [licenses]
61 | # The lint level for crates which do not have a detectable license
62 | unlicensed = "deny"
63 | # List of explictly allowed licenses
64 | # See https://spdx.org/licenses/ for list of possible licenses
65 | # [possible values: any SPDX 3.11 short identifier (+ optional exception)].
66 | allow = [
67 | "MIT",
68 | "Apache-2.0",
69 | "Apache-2.0 WITH LLVM-exception",
70 | "BSD-2-Clause",
71 | "BSD-2-Clause-Patent",
72 | "BSD-3-Clause",
73 | "CC0-1.0",
74 | "ISC",
75 | "Zlib",
76 | "MPL-2.0",
77 | "0BSD",
78 | "LicenseRef-ring", #ring
79 | "Unicode-DFS-2016", #unicode-ident
80 | ]
81 | # List of explictly disallowed licenses
82 | # See https://spdx.org/licenses/ for list of possible licenses
83 | # [possible values: any SPDX 3.11 short identifier (+ optional exception)].
84 | deny = []
85 | # Lint level for licenses considered copyleft
86 | copyleft = "deny"
87 | # Blanket approval or denial for OSI-approved or FSF Free/Libre licenses
88 | # * both - The license will be approved if it is both OSI-approved *AND* FSF
89 | # * either - The license will be approved if it is either OSI-approved *OR* FSF
90 | # * osi-only - The license will be approved if is OSI-approved *AND NOT* FSF
91 | # * fsf-only - The license will be approved if is FSF *AND NOT* OSI-approved
92 | # * neither - This predicate is ignored and the default lint level is used
93 | allow-osi-fsf-free = "neither"
94 | # Lint level used when no other predicates are matched
95 | # 1. License isn't in the allow or deny lists
96 | # 2. License isn't copyleft
97 | # 3. License isn't OSI/FSF, or allow-osi-fsf-free = "neither"
98 | default = "deny"
99 | # The confidence threshold for detecting a license from license text.
100 | # The higher the value, the more closely the license text must be to the
101 | # canonical license text of a valid SPDX license file.
102 | # [possible values: any between 0.0 and 1.0].
103 | confidence-threshold = 0.8
104 | # Allow 1 or more licenses on a per-crate basis, so that particular licenses
105 | # aren't accepted for every possible crate as with the normal allow list
106 | exceptions = [{ allow = ["BUSL-1.1"], name = "webc" }]
107 |
108 | [[licenses.clarify]]
109 | # The name of the crate the clarification applies to
110 | name = "encoding_rs"
111 | # The optional version constraint for the crate
112 | version = "0.8.30"
113 | # The SPDX expression for the license requirements of the crate
114 | expression = "Apache-2.0 AND BSD-3-Clause"
115 | # One or more files in the crate's source used as the "source of truth" for
116 | # the license expression. If the contents match, the clarification will be used
117 | # when running the license check, otherwise the clarification will be ignored
118 | # and the crate will be checked normally, which may produce warnings or errors
119 | # depending on the rest of your configuration
120 | license-files = [{ path = "COPYRIGHT", hash = 972598577 }]
121 |
122 | [[licenses.clarify]]
123 | expression = "LicenseRef-ring"
124 | license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }]
125 | name = "ring"
126 |
127 | # Some crates don't have (easily) machine readable licensing information,
128 | # adding a clarification entry for it allows you to manually specify the
129 | # licensing information
130 | #[[licenses.clarify]]
131 | # The name of the crate the clarification applies to
132 | #name = "ring"
133 | # The optional version constraint for the crate
134 | #version = "*"
135 | # The SPDX expression for the license requirements of the crate
136 | #expression = "MIT AND ISC AND OpenSSL"
137 | # One or more files in the crate's source used as the "source of truth" for
138 | # the license expression. If the contents match, the clarification will be used
139 | # when running the license check, otherwise the clarification will be ignored
140 | # and the crate will be checked normally, which may produce warnings or errors
141 | # depending on the rest of your configuration
142 | #license-files = [
143 | # Each entry is a crate relative path, and the (opaque) hash of its contents
144 | #{ path = "LICENSE", hash = 0xbd0eed23 }
145 | #]
146 |
147 | [licenses.private]
148 | # If true, ignores workspace crates that aren't published, or are only
149 | # published to private registries
150 | ignore = false
151 | # One or more private registries that you might publish crates to, if a crate
152 | # is only published to private registries, and ignore is true, the crate will
153 | # not have its license(s) checked
154 | registries = []
155 |
156 | # This section is considered when running `cargo deny check bans`.
157 | # More documentation about the 'bans' section can be found here:
158 | # https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
159 | [bans]
160 | # Lint level for when multiple versions of the same crate are detected
161 | multiple-versions = "allow"
162 | # Lint level for when a crate version requirement is `*`
163 | wildcards = "allow"
164 | # The graph highlighting used when creating dotgraphs for crates
165 | # with multiple versions
166 | # * lowest-version - The path to the lowest versioned duplicate is highlighted
167 | # * simplest-path - The path to the version with the fewest edges is highlighted
168 | # * all - Both lowest-version and simplest-path are used
169 | highlight = "all"
170 | # List of crates that are allowed. Use with care!
171 | allow = []
172 | # List of crates to deny
173 | deny = []
174 | # Certain crates/versions that will be skipped when doing duplicate detection.
175 | skip = []
176 | # Similarly to `skip` allows you to skip certain crates during duplicate
177 | # detection. Unlike skip, it also includes the entire tree of transitive
178 | # dependencies starting at the specified crate, up to a certain depth, which is
179 | # by default infinite
180 | skip-tree = []
181 |
182 | # This section is considered when running `cargo deny check sources`.
183 | # More documentation about the 'sources' section can be found here:
184 | # https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
185 | [sources]
186 | # Lint level for what to happen when a crate from a crate registry that is not
187 | # in the allow list is encountered
188 | unknown-registry = "warn"
189 | # Lint level for what to happen when a crate from a git repository that is not
190 | # in the allow list is encountered
191 | unknown-git = "warn"
192 | # List of URLs for allowed crate registries. Defaults to the crates.io index
193 | # if not specified. If it is specified but empty, no registries are allowed.
194 | allow-registry = ["https://github.com/rust-lang/crates.io-index"]
195 | # List of URLs for allowed Git repositories
196 | allow-git = []
197 |
198 | [sources.allow-org]
199 | # 1 or more github.com organizations to allow git sources for
200 | github = []
201 | # 1 or more gitlab.com organizations to allow git sources for
202 | gitlab = []
203 | # 1 or more bitbucket.org organizations to allow git sources for
204 | bitbucket = []
--------------------------------------------------------------------------------
/docs/CNAME:
--------------------------------------------------------------------------------
1 | kurit.kafu.dev
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 |
2 |
Kurit
3 |
4 |
Static website generator 🚀
5 |
6 |
WIP: It is still under development, so some of the features may not be developed.