[Web] Manually generate HTML from MD ast (h1)
This commit is contained in:
parent
ab5c38003a
commit
fc4e3a93f1
26
doc-generator/markdown/en/stdlib/latest/prelude/Console.md
Normal file
26
doc-generator/markdown/en/stdlib/latest/prelude/Console.md
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# Console
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The console module contains functions useful for debugging.
|
||||||
|
|
||||||
|
## Functions
|
||||||
|
|
||||||
|
### `fun log(Any ...objects)`
|
||||||
|
|
||||||
|
Outputs a message to the console of the system, with a new line.
|
||||||
|
|
||||||
|
When called without parameters, it prints just the new line.
|
||||||
|
|
||||||
|
```
|
||||||
|
Console.log() // Prints: `\n`
|
||||||
|
```
|
||||||
|
|
||||||
|
When called with one or more parameters, it first converts those
|
||||||
|
parameters to strings, joins them with white space, then prints them.
|
||||||
|
|
||||||
|
```
|
||||||
|
Console.log("message") // Prints: `message\n`
|
||||||
|
|
||||||
|
Console.log("message", "value") // Prints: `message value\n`
|
||||||
|
```
|
294
doc-generator/markdown/en/stdlib/latest/prelude/String.md
Normal file
294
doc-generator/markdown/en/stdlib/latest/prelude/String.md
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
# String
|
||||||
|
|
||||||
|
A collection of UTF-16 characters.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
Strings are a primitive datatype that contain a series of UTF-16 encoded characters.
|
||||||
|
|
||||||
|
To create a string use double quotes:
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val greeting = "Hello there!"
|
||||||
|
|
||||||
|
// With type annotation
|
||||||
|
Str greeting = "Hello there!"
|
||||||
|
```
|
||||||
|
|
||||||
|
```md-warning
|
||||||
|
Misti doesn't allow string creation with single quotes <code>''</code>.
|
||||||
|
```
|
||||||
|
|
||||||
|
Strings can be concatenated with the plus `+` operator:
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val name = "John"
|
||||||
|
val greeting = "Hello"
|
||||||
|
|
||||||
|
val fullGreeting = greeting + " " + name + "!"
|
||||||
|
// fullGreeting = "Hello John!"
|
||||||
|
```
|
||||||
|
|
||||||
|
In the future, the language will support string concatenation and multi-line strings.
|
||||||
|
|
||||||
|
## String comparison
|
||||||
|
|
||||||
|
To check if two strings are the same use the equal-to `==` operator.
|
||||||
|
|
||||||
|
```misti
|
||||||
|
"Hello" == "Hello" //: true
|
||||||
|
"Hello" == "hello" //: false
|
||||||
|
```
|
||||||
|
|
||||||
|
To check if two strings are different use the not-equal-to `!=` operator.
|
||||||
|
|
||||||
|
```misti
|
||||||
|
"abc" != "123" //: true
|
||||||
|
"xyz" != "xyz" //: false
|
||||||
|
```
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
Comparing strings with `<`, `<=`, `>` & `>=` will compare each character of the string,
|
||||||
|
based on the UTF-16 value.
|
||||||
|
|
||||||
|
```misti
|
||||||
|
"a" < "b" //: true
|
||||||
|
"a" < "A" //: false
|
||||||
|
|
||||||
|
"aab" > "aac" //: false
|
||||||
|
"aab" < "aac" //: true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Automatic String conversion
|
||||||
|
|
||||||
|
Misti __does not__ automatically convert other datatypes to String.
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val sentence = "My age is: " + 20 // This will throw an error
|
||||||
|
// ^
|
||||||
|
// Cannot concatenate a String and a Number.
|
||||||
|
```
|
||||||
|
|
||||||
|
To do so use the method `.toStr()` to explicitly convert to String.
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val sentence = "My age is: " + 20.toStr() // ok
|
||||||
|
```
|
||||||
|
|
||||||
|
In the future, string interpolation will coerce datatypes into strings.
|
||||||
|
|
||||||
|
|
||||||
|
## Escape characters
|
||||||
|
|
||||||
|
Misti supports the following escape characters:
|
||||||
|
|
||||||
|
- `\"`
|
||||||
|
|
||||||
|
- `\\`
|
||||||
|
- `\n`
|
||||||
|
- `\r`
|
||||||
|
- `\t`
|
||||||
|
- `\b`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
Prelude's `Str` contains methods and functions created for their usage within Misti.
|
||||||
|
|
||||||
|
To access the underlying JavaScript methods, use the `js.String` module.
|
||||||
|
|
||||||
|
|
||||||
|
### Constructor
|
||||||
|
|
||||||
|
```misti
|
||||||
|
class String[T](T value)
|
||||||
|
where T -> Printable
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a string from `value`, by calling its `toStr` method.
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `T value`: Any value that implements `Printable`, and therefore has a `toStr` method.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val age = String(20) //: "20"
|
||||||
|
val condition = String(false) //: "false"
|
||||||
|
val numbers = Array(1, 2, 3) |> String //: "1,2,3"
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Properties
|
||||||
|
|
||||||
|
### length
|
||||||
|
|
||||||
|
```misti
|
||||||
|
Num length
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the number of UTF-16 code units in the string.
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val name = "John"
|
||||||
|
name.length //: 4
|
||||||
|
```
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Methods
|
||||||
|
|
||||||
|
### charAt
|
||||||
|
|
||||||
|
```misti
|
||||||
|
fun charAt(Num position) -> Str?
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns the UTF-16 code unit located at `position`.
|
||||||
|
|
||||||
|
<div class="padded">
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `Num position`: An integer between `0` and the string's `length - 1`.
|
||||||
|
|
||||||
|
#### Return
|
||||||
|
|
||||||
|
- `Str?`: The character at `position`, or `None` if it's invalid
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
In a string with `length` characters, this method returns the character (UTF-16 code point)
|
||||||
|
located at `position`, if it is true that `0 <= position < length`.
|
||||||
|
|
||||||
|
If `position` is out of range, this method will return `None`.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val name = "John Doe"
|
||||||
|
|
||||||
|
name.charAt(0) //: Some("J")
|
||||||
|
name.charAt(1) //: Some("o")
|
||||||
|
name.charAt(7) //: Some("e")
|
||||||
|
|
||||||
|
name.charAt(-1) //: None
|
||||||
|
name.charAt(8) //: None
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are sure that the position is valid, you can use the `!!` operator to get
|
||||||
|
the value directly, instead of a `Maybe`.
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val greeting = "Hello!"
|
||||||
|
|
||||||
|
name.charAt(4)!! //: "o"
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
### concat
|
||||||
|
|
||||||
|
```misti
|
||||||
|
fun concat[any T](T... values) -> Str
|
||||||
|
where T -> Printable
|
||||||
|
```
|
||||||
|
|
||||||
|
Concatenates the calling string and `values`, and returns the result
|
||||||
|
as a new `Str`
|
||||||
|
|
||||||
|
<div class="padded">
|
||||||
|
|
||||||
|
#### Type parameters
|
||||||
|
|
||||||
|
- `any T`: Any datatype that implements `Printable`
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `T... values`: Zero or more values of type `T`
|
||||||
|
|
||||||
|
#### Return
|
||||||
|
|
||||||
|
- `Str`: A new string with the values concatenated
|
||||||
|
|
||||||
|
#### Description
|
||||||
|
|
||||||
|
`concat` concatenates the callee, and any arguments passed to it in
|
||||||
|
a new string. The callee is not modified.
|
||||||
|
|
||||||
|
If the arguments don't have type `Str`, they are converted with their
|
||||||
|
`toStr` method.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val greeting = "Hello "
|
||||||
|
|
||||||
|
greeting.concat("world", "!") //: "Hello world!"
|
||||||
|
greeting.concat(123) //: "Hello 123"
|
||||||
|
greeting.concat(3, 2, 2) //: "Hello 322"
|
||||||
|
```
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### includes
|
||||||
|
|
||||||
|
```misti
|
||||||
|
fun includes(Str searchString, Num pos = 0) -> Bool
|
||||||
|
```
|
||||||
|
|
||||||
|
Returns whether the current string contains `searchString`,
|
||||||
|
searching from position `pos`
|
||||||
|
|
||||||
|
<div class="padded">
|
||||||
|
|
||||||
|
#### Parameters
|
||||||
|
|
||||||
|
- `Str searchString`: The string to search for
|
||||||
|
- `Num pos = 0`: The position from where to start searching.
|
||||||
|
|
||||||
|
#### Return
|
||||||
|
|
||||||
|
`Bool`: `true` if searchString is found, `false` otherwise
|
||||||
|
|
||||||
|
#### Additional
|
||||||
|
|
||||||
|
If `searchString` is the empty string `""` this method returns `true`.
|
||||||
|
|
||||||
|
If `pos` is negative, the search starts from the first character.
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
```misti
|
||||||
|
val loremIpsum = "Lorem ipsum dolor sit amet"
|
||||||
|
|
||||||
|
loremIpsum.includes("ipsum") //: true
|
||||||
|
loremIpsum.includes("ipsum", 10) //: false
|
||||||
|
loremIpsum.includes("ipsum", -5) //: true
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
21
doc-generator/src/generator/heading.rs
Normal file
21
doc-generator/src/generator/heading.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use std::fmt::format;
|
||||||
|
|
||||||
|
use markdown::mdast::Heading;
|
||||||
|
|
||||||
|
use super::Printable;
|
||||||
|
|
||||||
|
|
||||||
|
impl Printable for Heading {
|
||||||
|
fn to_html(&self) -> String {
|
||||||
|
let mut result = Vec::<String>::new();
|
||||||
|
|
||||||
|
for node in &self.children {
|
||||||
|
result.push(node.to_html())
|
||||||
|
}
|
||||||
|
|
||||||
|
let text: String = result.into_iter().collect();
|
||||||
|
|
||||||
|
format!("<h{}>{}</h{}>", self.depth, text, self.depth)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
19
doc-generator/src/generator/mod.rs
Normal file
19
doc-generator/src/generator/mod.rs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
use markdown::mdast::Node;
|
||||||
|
|
||||||
|
mod root;
|
||||||
|
mod heading;
|
||||||
|
|
||||||
|
pub trait Printable {
|
||||||
|
fn to_html(&self) -> String;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Printable for Node {
|
||||||
|
fn to_html(&self) -> String {
|
||||||
|
match self {
|
||||||
|
Node::Root(root) => root.to_html(),
|
||||||
|
Node::Heading(heading) => heading.to_html(),
|
||||||
|
_ => format!("Not implemented<br>{:?}", self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
16
doc-generator/src/generator/root.rs
Normal file
16
doc-generator/src/generator/root.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
use markdown::mdast;
|
||||||
|
|
||||||
|
use super::Printable;
|
||||||
|
|
||||||
|
|
||||||
|
impl Printable for mdast::Root {
|
||||||
|
fn to_html(&self) -> String {
|
||||||
|
let mut result = Vec::<String>::new();
|
||||||
|
|
||||||
|
for node in &self.children {
|
||||||
|
result.push(node.to_html())
|
||||||
|
}
|
||||||
|
|
||||||
|
result.into_iter().collect()
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use generator::Printable;
|
||||||
use markdown::to_html;
|
use markdown::to_html;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
@ -7,6 +8,8 @@ use std::{
|
|||||||
path::Path,
|
path::Path,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod generator;
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(author, version, about, long_about = None)]
|
#[command(author, version, about, long_about = None)]
|
||||||
struct Args {
|
struct Args {
|
||||||
@ -67,18 +70,18 @@ fn ensure_folder_exists(folder: &Path, input_folder: &Path, output_folder: &Path
|
|||||||
let mut full_output_folder = output_folder.clone();
|
let mut full_output_folder = output_folder.clone();
|
||||||
full_output_folder.push(relative_new_folder);
|
full_output_folder.push(relative_new_folder);
|
||||||
|
|
||||||
println!("Ensuring that folder exists:\n{:?}", full_output_folder);
|
// println!("Ensuring that folder exists:\n{:?}", full_output_folder);
|
||||||
|
|
||||||
// If this is a "top-level" folder, remove all its contents, if it exists
|
// If this is a "top-level" folder, remove all its contents, if it exists
|
||||||
if full_output_folder.is_dir() {
|
if full_output_folder.is_dir() {
|
||||||
println!("| Removing...");
|
// println!("| Removing...");
|
||||||
let _ = fs::remove_dir_all(&full_output_folder);
|
let _ = fs::remove_dir_all(&full_output_folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create folder
|
// Create folder
|
||||||
match fs::create_dir(&full_output_folder) {
|
match fs::create_dir(&full_output_folder) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
println!("| done\n\n");
|
// println!("| done\n\n");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Err(_) => Err(format!("Error creating folder {:?}", full_output_folder)),
|
Err(_) => Err(format!("Error creating folder {:?}", full_output_folder)),
|
||||||
@ -102,15 +105,16 @@ fn process_markdown(file: &Path, input_folder: &Path, output_folder: &Path) -> R
|
|||||||
output_file.push(relative_input_file);
|
output_file.push(relative_input_file);
|
||||||
output_file.set_extension("html");
|
output_file.set_extension("html");
|
||||||
|
|
||||||
|
//
|
||||||
|
// Compilation
|
||||||
|
//
|
||||||
let file_content_bytes = fs::read(&input_file).unwrap();
|
let file_content_bytes = fs::read(&input_file).unwrap();
|
||||||
let markdown_text = String::from_utf8(file_content_bytes).unwrap();
|
let markdown_text = String::from_utf8(file_content_bytes).unwrap();
|
||||||
|
|
||||||
let html_text = to_html(markdown_text.as_str());
|
// let html_text = to_html(markdown_text.as_str());
|
||||||
|
let md_ast = markdown::to_mdast(&markdown_text, &markdown::ParseOptions::gfm()).unwrap();
|
||||||
|
let html_text = md_ast.to_html();
|
||||||
|
|
||||||
// Write the HTML to disk
|
|
||||||
|
|
||||||
println!("Compiling: from -> to\n{:?}\n{:?}\n", input_file, output_file);
|
|
||||||
|
|
||||||
// Read template.html
|
// Read template.html
|
||||||
let mut template_path = output_folder.clone();
|
let mut template_path = output_folder.clone();
|
||||||
@ -121,6 +125,7 @@ fn process_markdown(file: &Path, input_folder: &Path, output_folder: &Path) -> R
|
|||||||
|
|
||||||
let final_output = template_contents.replace("{{markdown}}", &html_text);
|
let final_output = template_contents.replace("{{markdown}}", &html_text);
|
||||||
|
|
||||||
|
// Write to disk
|
||||||
let _ = File::create(&output_file)
|
let _ = File::create(&output_file)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.write_all(final_output.as_bytes())
|
.write_all(final_output.as_bytes())
|
||||||
|
@ -98,8 +98,6 @@ html {
|
|||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide-on-small {}
|
|
||||||
|
|
||||||
.padded {
|
.padded {
|
||||||
padding-left: 2rem;
|
padding-left: 2rem;
|
||||||
border-left: solid 1px var(--border-color);
|
border-left: solid 1px var(--border-color);
|
||||||
@ -109,10 +107,6 @@ html {
|
|||||||
html {
|
html {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.hide-on-small {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@ -158,25 +152,6 @@ g.terminal text {
|
|||||||
transform: scale(1.5);
|
transform: scale(1.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.main-container {
|
|
||||||
margin: 0 auto;
|
|
||||||
max-width: 1400px;
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rainbow-separator {
|
|
||||||
background-color: var(--js-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
code {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
pre {
|
pre {
|
||||||
border: solid 1px rgba(150, 150, 150, 0.5);
|
border: solid 1px rgba(150, 150, 150, 0.5);
|
||||||
}
|
}
|
||||||
@ -193,17 +168,19 @@ code, pre {
|
|||||||
.marked p {
|
.marked p {
|
||||||
line-height: 1.5rem;
|
line-height: 1.5rem;
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
|
margin: 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.marked h1 {
|
.marked h1 {
|
||||||
font-weight: 600;
|
font-weight: 900;
|
||||||
margin-top: 3rem;
|
margin-top: 3rem;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
|
font-size: 2.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.marked h2 {
|
.marked h2 {
|
||||||
font-size: 1.75rem;
|
font-size: 2rem;
|
||||||
font-weight: 500;
|
font-weight: bold;
|
||||||
margin-top: 3rem;
|
margin-top: 3rem;
|
||||||
margin-bottom: 1.5rem;
|
margin-bottom: 1.5rem;
|
||||||
}
|
}
|
||||||
@ -213,9 +190,23 @@ code, pre {
|
|||||||
text-decoration-color: var(--c5);
|
text-decoration-color: var(--c5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.marked h3, .marked h4, .marked h5 {
|
.marked h3 {
|
||||||
font-size: 1.5rem;
|
font-size: 1.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-top: 2.5rem;
|
||||||
|
margin-bottom: 1.25rem;
|
||||||
|
text-decoration: underline;
|
||||||
|
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.marked h4 {
|
||||||
|
font-size: 1.25rem;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
|
margin-top: 2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.marked table {
|
.marked table {
|
||||||
@ -302,11 +293,6 @@ code, pre {
|
|||||||
margin-bottom: 0.75rem;
|
margin-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.marked h2 {
|
|
||||||
margin-top: 2rem;
|
|
||||||
margin-bottom: 1.25rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
pre[class*="language-"].line-numbers {
|
pre[class*="language-"].line-numbers {
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,9 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
{{markdown}}
|
<div class="marked p-4">
|
||||||
|
{{markdown}}
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Inter - Google fonts - load here as to not interrupt the page
|
// Inter - Google fonts - load here as to not interrupt the page
|
||||||
|
Loading…
Reference in New Issue
Block a user