mirror of
https://github.com/adoyle0/thaw.git
synced 2025-02-02 08:34:15 -05:00
Demo/markdown (#61)
* demo: init demo-markdown * demo: add include_md macro * demo: improve include_md macro * demo: improve include_md macro * demo: improve include_md macro * demo: improve code block * demo: add syntect css * demo: improve include_md macro * demo: include_md handle table
This commit is contained in:
parent
2cd308fadf
commit
3df65a4e26
13 changed files with 437 additions and 4 deletions
|
@ -51,4 +51,4 @@ ssr = ["leptos/ssr", "leptos_meta/ssr"]
|
||||||
hydrate = ["leptos/hydrate"]
|
hydrate = ["leptos/hydrate"]
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["demo", "examples/*"]
|
members = ["demo", "demo_markdown", "examples/*"]
|
||||||
|
|
|
@ -20,6 +20,7 @@ icondata = { version = "0.1.0", features = [
|
||||||
"AiSearchOutlined",
|
"AiSearchOutlined",
|
||||||
] }
|
] }
|
||||||
prisms = { git = "https://github.com/luoxiaozero/prisms", rev = "16d4d34b93fc20578ebf03137d54ecc7eafa4d4b" }
|
prisms = { git = "https://github.com/luoxiaozero/prisms", rev = "16d4d34b93fc20578ebf03137d54ecc7eafa4d4b" }
|
||||||
|
demo_markdown = { path = "../demo_markdown" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["csr"]
|
default = ["csr"]
|
||||||
|
|
|
@ -5,7 +5,7 @@ public_url = "/thaw/"
|
||||||
filehash = false
|
filehash = false
|
||||||
|
|
||||||
[watch]
|
[watch]
|
||||||
watch = ["../src", "./src"]
|
watch = ["../src", "./src", "../demo_markdown"]
|
||||||
|
|
||||||
[serve]
|
[serve]
|
||||||
address = "127.0.0.1"
|
address = "127.0.0.1"
|
||||||
|
|
|
@ -72,6 +72,7 @@ fn TheRouter(is_routing: RwSignal<bool>) -> impl IntoView {
|
||||||
<Route path="/switch" view=SwitchPage/>
|
<Route path="/switch" view=SwitchPage/>
|
||||||
<Route path="/tag" view=TagPage/>
|
<Route path="/tag" view=TagPage/>
|
||||||
<Route path="/upload" view=UploadPage/>
|
<Route path="/upload" view=UploadPage/>
|
||||||
|
<Route path="/upload-md" view=UploadMdPage/>
|
||||||
<Route path="/loading-bar" view=LoadingBarPage/>
|
<Route path="/loading-bar" view=LoadingBarPage/>
|
||||||
<Route path="/breadcrumb" view=BreadcrumbPage/>
|
<Route path="/breadcrumb" view=BreadcrumbPage/>
|
||||||
<Route path="/layout" view=LayoutPage/>
|
<Route path="/layout" view=LayoutPage/>
|
||||||
|
|
|
@ -4,6 +4,8 @@ use thaw::*;
|
||||||
|
|
||||||
#[slot]
|
#[slot]
|
||||||
pub struct DemoCode {
|
pub struct DemoCode {
|
||||||
|
#[prop(default = true)]
|
||||||
|
is_highlight: bool,
|
||||||
children: Children,
|
children: Children,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +39,16 @@ pub fn Demo(demo_code: DemoCode, children: Children) -> impl IntoView {
|
||||||
});
|
});
|
||||||
style
|
style
|
||||||
});
|
});
|
||||||
|
let content_class = create_memo(move |_| {
|
||||||
|
theme.with(|theme| {
|
||||||
|
format!(
|
||||||
|
"thaw-demo__content color-scheme--{}",
|
||||||
|
theme.common.color_scheme
|
||||||
|
)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
let is_highlight = demo_code.is_highlight;
|
||||||
let frag = (demo_code.children)();
|
let frag = (demo_code.children)();
|
||||||
let mut html = String::new();
|
let mut html = String::new();
|
||||||
for node in frag.nodes {
|
for node in frag.nodes {
|
||||||
|
@ -51,15 +62,30 @@ pub fn Demo(demo_code: DemoCode, children: Children) -> impl IntoView {
|
||||||
|
|
||||||
view! {
|
view! {
|
||||||
<Style id="leptos-thaw-prism-css">{prisms::prism_css!()}</Style>
|
<Style id="leptos-thaw-prism-css">{prisms::prism_css!()}</Style>
|
||||||
|
<Style id="leptos-thaw-syntect-css">
|
||||||
|
{include_str!("./syntect-css.css")}
|
||||||
|
</Style>
|
||||||
<Style id="leptos-thaw-prism-css-fix">
|
<Style id="leptos-thaw-prism-css-fix">
|
||||||
".token.operator {
|
".token.operator {
|
||||||
background: hsla(0, 0%, 100%, 0) !important;
|
background: hsla(0, 0%, 100%, 0) !important;
|
||||||
}"
|
}"
|
||||||
</Style>
|
</Style>
|
||||||
<div style=move || style.get()>{children()}</div>
|
<div style=move || style.get()>{children()}</div>
|
||||||
<div style=move || code_style.get()>
|
<div style=move || code_style.get() class=move || content_class.get()>
|
||||||
<Code>
|
<Code>
|
||||||
|
{
|
||||||
|
if is_highlight {
|
||||||
|
view! {
|
||||||
<pre style="margin: 0" inner_html=html></pre>
|
<pre style="margin: 0" inner_html=html></pre>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
view! {
|
||||||
|
<pre style="margin: 0">
|
||||||
|
{html}
|
||||||
|
</pre>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</Code>
|
</Code>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
60
demo/src/components/syntect-css.css
Normal file
60
demo/src/components/syntect-css.css
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
.thaw-demo__content pre {
|
||||||
|
font-family: ui-monospace, SFMono-Regular, SF Mono, Menlo, Consolas,
|
||||||
|
Liberation Mono, monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** https://github.com/AmjadHD/sublime_one_theme */
|
||||||
|
|
||||||
|
/** light */
|
||||||
|
|
||||||
|
.color-scheme--light .syntect-storage {
|
||||||
|
color: hsl(301, 63%, 40%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--light .syntect-keyword.syntect-operator {
|
||||||
|
color: hsl(335, 95%, 62%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--light .syntect-function,
|
||||||
|
.color-scheme--light .syntect-macro {
|
||||||
|
color: hsl(221, 87%, 60%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--light .syntect-support.syntect-type {
|
||||||
|
color: hsl(198, 99%, 37%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--light .syntect-string {
|
||||||
|
color: hsl(119, 34%, 47%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--light .syntect-placeholder {
|
||||||
|
color: hsl(41, 99%, 30%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** dark */
|
||||||
|
|
||||||
|
.color-scheme--dark .syntect-storage {
|
||||||
|
color: hsl(286, 60%, 67%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--dark .syntect-keyword.syntect-operator {
|
||||||
|
color: hsl(335, 95%, 62%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--dark .syntect-function,
|
||||||
|
.color-scheme--dark .syntect-macro {
|
||||||
|
color: hsl(207, 82%, 66%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--dark .syntect-support.syntect-type {
|
||||||
|
color: hsl(187, 47%, 55%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--dark .syntect-string {
|
||||||
|
color: hsl(95, 38%, 62%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-scheme--dark .syntect-placeholder {
|
||||||
|
color: hsl(29, 54%, 61%);
|
||||||
|
}
|
5
demo/src/pages/markdown.rs
Normal file
5
demo/src/pages/markdown.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
use crate::components::{Demo, DemoCode};
|
||||||
|
use leptos::*;
|
||||||
|
use thaw::*;
|
||||||
|
|
||||||
|
demo_markdown::include_md! {}
|
|
@ -20,6 +20,7 @@ mod input;
|
||||||
mod input_number;
|
mod input_number;
|
||||||
mod layout;
|
mod layout;
|
||||||
mod loading_bar;
|
mod loading_bar;
|
||||||
|
mod markdown;
|
||||||
mod menu;
|
mod menu;
|
||||||
mod message;
|
mod message;
|
||||||
mod mobile;
|
mod mobile;
|
||||||
|
@ -66,6 +67,7 @@ pub use input::*;
|
||||||
pub use input_number::*;
|
pub use input_number::*;
|
||||||
pub use layout::*;
|
pub use layout::*;
|
||||||
pub use loading_bar::*;
|
pub use loading_bar::*;
|
||||||
|
pub use markdown::*;
|
||||||
pub use menu::*;
|
pub use menu::*;
|
||||||
pub use message::*;
|
pub use message::*;
|
||||||
pub use mobile::*;
|
pub use mobile::*;
|
||||||
|
|
17
demo_markdown/Cargo.toml
Normal file
17
demo_markdown/Cargo.toml
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[package]
|
||||||
|
publish = false
|
||||||
|
name = "demo_markdown"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
quote = "1.0.33"
|
||||||
|
comrak = "0.20.0"
|
||||||
|
proc-macro2 = "1.0.71"
|
||||||
|
syn = "2.0.43"
|
||||||
|
syntect = "5.1.0"
|
54
demo_markdown/docs/upload/mod.md
Normal file
54
demo_markdown/docs/upload/mod.md
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
# Upload
|
||||||
|
|
||||||
|
```rust demo
|
||||||
|
let message = use_message();
|
||||||
|
let custom_request = move |file_list: FileList| {
|
||||||
|
message.create(
|
||||||
|
format!("Number of uploaded files: {}", file_list.length()),
|
||||||
|
MessageVariant::Success,
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
view!{
|
||||||
|
<Upload>
|
||||||
|
<Button>
|
||||||
|
"upload"
|
||||||
|
</Button>
|
||||||
|
</Upload>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Drag to upload
|
||||||
|
|
||||||
|
```rust demo
|
||||||
|
let message = use_message();
|
||||||
|
let custom_request = move |file_list: FileList| {
|
||||||
|
message.create(
|
||||||
|
format!("Number of uploaded files: {}", file_list.length()),
|
||||||
|
MessageVariant::Success,
|
||||||
|
Default::default(),
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<Upload custom_request>
|
||||||
|
<UploadDragger>"Click or drag a file to this area to upload"</UploadDragger>
|
||||||
|
</Upload>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upload Props
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
| -------------- | -------------------------------- | -------------------- | ------------------------------------ |
|
||||||
|
| accept | `MaybeSignal<String>` | `Default::default()` | The accept type of upload. |
|
||||||
|
| multiple | `MaybeSignal<bool>` | `false` | Allow multiple files to be selected. |
|
||||||
|
| custom_request | `Option<Callback<FileList, ()>>` | `Default::default()` | Customize upload request. |
|
||||||
|
| children | `Children` | | Upload's content. |
|
||||||
|
|
||||||
|
### UploadDragger Props
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
| -------- | ---------- | ------- | ------------------------ |
|
||||||
|
| children | `Children` | | UploadDragger's content. |
|
55
demo_markdown/src/lib.rs
Normal file
55
demo_markdown/src/lib.rs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
mod markdown;
|
||||||
|
|
||||||
|
use crate::markdown::parse_markdown;
|
||||||
|
use proc_macro2::{Ident, Span};
|
||||||
|
use quote::quote;
|
||||||
|
use syn::ItemFn;
|
||||||
|
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn include_md(_token_stream: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let file_list = vec![("UploadMdPage", include_str!("../docs/upload/mod.md"))];
|
||||||
|
|
||||||
|
let mut fn_list = vec![];
|
||||||
|
|
||||||
|
for (fn_name, file_str) in file_list {
|
||||||
|
let fn_name = Ident::new(fn_name, Span::call_site());
|
||||||
|
|
||||||
|
let (body, demos) = match parse_markdown(file_str) {
|
||||||
|
Ok(body) => body,
|
||||||
|
Err(err) => {
|
||||||
|
return quote!(compile_error!(#err)).into();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let demos: Vec<ItemFn> = demos
|
||||||
|
.into_iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(index, demo)| {
|
||||||
|
format!(
|
||||||
|
"#[component] fn Demo{}() -> impl IntoView {{ {} }}",
|
||||||
|
index + 1,
|
||||||
|
demo
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.map(|demo| syn::parse_str::<ItemFn>(&demo).unwrap())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
fn_list.push(quote! {
|
||||||
|
#[component]
|
||||||
|
pub fn #fn_name() -> impl IntoView {
|
||||||
|
#(#demos)*
|
||||||
|
|
||||||
|
view! {
|
||||||
|
<div style="width: 896px; margin: 0 auto;">
|
||||||
|
#body
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#(#fn_list)*
|
||||||
|
}
|
||||||
|
.into()
|
||||||
|
}
|
78
demo_markdown/src/markdown/code_block.rs
Normal file
78
demo_markdown/src/markdown/code_block.rs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
use comrak::nodes::NodeCodeBlock;
|
||||||
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
|
use quote::quote;
|
||||||
|
use std::sync::OnceLock;
|
||||||
|
use syntect::{
|
||||||
|
html::{ClassStyle, ClassedHTMLGenerator},
|
||||||
|
parsing::SyntaxSet,
|
||||||
|
util::LinesWithEndings,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn to_tokens(code_block: &NodeCodeBlock, demos: &mut Vec<String>) -> TokenStream {
|
||||||
|
let langs: Vec<&str> = code_block.info.split_ascii_whitespace().collect();
|
||||||
|
if langs.iter().any(|lang| lang == &"demo") {
|
||||||
|
demos.push(code_block.literal.clone());
|
||||||
|
|
||||||
|
let demo = Ident::new(&format!("Demo{}", demos.len()), Span::call_site());
|
||||||
|
let mut is_highlight = true;
|
||||||
|
let literal = langs
|
||||||
|
.iter()
|
||||||
|
.find(|lang| lang != &&"demo")
|
||||||
|
.map(|lang| highlight_to_html(&code_block.literal, lang))
|
||||||
|
.flatten()
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
is_highlight = false;
|
||||||
|
code_block.literal.clone()
|
||||||
|
});
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
<Demo>
|
||||||
|
<#demo />
|
||||||
|
<DemoCode slot is_highlight=#is_highlight>
|
||||||
|
#literal
|
||||||
|
</DemoCode>
|
||||||
|
</Demo>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut is_highlight = true;
|
||||||
|
let literal = langs
|
||||||
|
.first()
|
||||||
|
.map(|lang| highlight_to_html(&code_block.literal, lang))
|
||||||
|
.flatten()
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
is_highlight = false;
|
||||||
|
code_block.literal.clone()
|
||||||
|
});
|
||||||
|
quote! {
|
||||||
|
<Demo>
|
||||||
|
""
|
||||||
|
<DemoCode slot is_highlight=#is_highlight>
|
||||||
|
#literal
|
||||||
|
</DemoCode>
|
||||||
|
</Demo>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static SYNTAX_SET: OnceLock<SyntaxSet> = OnceLock::new();
|
||||||
|
|
||||||
|
fn highlight_to_html(text: &str, syntax: &str) -> Option<String> {
|
||||||
|
let syntax_set = SYNTAX_SET.get_or_init(|| SyntaxSet::load_defaults_newlines());
|
||||||
|
let Some(syntax) = syntax_set.find_syntax_by_token(syntax) else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut html_generator = ClassedHTMLGenerator::new_with_class_style(
|
||||||
|
syntax,
|
||||||
|
syntax_set,
|
||||||
|
ClassStyle::SpacedPrefixed { prefix: "syntect-" },
|
||||||
|
);
|
||||||
|
|
||||||
|
for line in LinesWithEndings::from(text) {
|
||||||
|
html_generator
|
||||||
|
.parse_html_for_line_which_includes_newline(line)
|
||||||
|
.expect(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(html_generator.finalize())
|
||||||
|
}
|
134
demo_markdown/src/markdown/mod.rs
Normal file
134
demo_markdown/src/markdown/mod.rs
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
mod code_block;
|
||||||
|
|
||||||
|
use comrak::{
|
||||||
|
nodes::{AstNode, NodeValue},
|
||||||
|
parse_document, Arena,
|
||||||
|
};
|
||||||
|
use proc_macro2::{Ident, Span, TokenStream};
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
pub fn parse_markdown(md_text: &str) -> Result<(TokenStream, Vec<String>), String> {
|
||||||
|
let mut demos: Vec<String> = vec![];
|
||||||
|
|
||||||
|
let arena = Arena::new();
|
||||||
|
let mut options = comrak::Options::default();
|
||||||
|
options.extension.table = true;
|
||||||
|
|
||||||
|
let root = parse_document(&arena, &md_text, &options);
|
||||||
|
let body = iter_nodes(root, &mut demos);
|
||||||
|
Ok((body, demos))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter_nodes<'a>(node: &'a AstNode<'a>, demos: &mut Vec<String>) -> TokenStream {
|
||||||
|
let mut children = vec![];
|
||||||
|
for c in node.children() {
|
||||||
|
children.push(iter_nodes(c, demos));
|
||||||
|
}
|
||||||
|
match &node.data.borrow().value {
|
||||||
|
NodeValue::Document => quote!(#(#children)*),
|
||||||
|
NodeValue::FrontMatter(_) => quote!("FrontMatter todo!!!"),
|
||||||
|
NodeValue::BlockQuote => quote!("BlockQuote todo!!!"),
|
||||||
|
NodeValue::List(_) => quote!("List todo!!!"),
|
||||||
|
NodeValue::Item(_) => quote!("Item todo!!!"),
|
||||||
|
NodeValue::DescriptionList => quote!("DescriptionList todo!!!"),
|
||||||
|
NodeValue::DescriptionItem(_) => quote!("DescriptionItem todo!!!"),
|
||||||
|
NodeValue::DescriptionTerm => quote!("DescriptionTerm todo!!!"),
|
||||||
|
NodeValue::DescriptionDetails => quote!("DescriptionDetails todo!!!"),
|
||||||
|
NodeValue::CodeBlock(node_code_block) => code_block::to_tokens(node_code_block, demos),
|
||||||
|
NodeValue::HtmlBlock(_) => quote!("HtmlBlock todo!!!"),
|
||||||
|
NodeValue::Paragraph => quote!(
|
||||||
|
<p>
|
||||||
|
#(#children)*
|
||||||
|
</p >
|
||||||
|
),
|
||||||
|
NodeValue::Heading(node_h) => {
|
||||||
|
let h = Ident::new(&format!("h{}", node_h.level), Span::call_site());
|
||||||
|
quote!(
|
||||||
|
<#h>
|
||||||
|
#(#children)*
|
||||||
|
</#h>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
NodeValue::ThematicBreak => quote!("ThematicBreak todo!!!"),
|
||||||
|
NodeValue::FootnoteDefinition(_) => quote!("FootnoteDefinition todo!!!"),
|
||||||
|
NodeValue::Table(_) => {
|
||||||
|
let header_index = {
|
||||||
|
let mut header_index = 0;
|
||||||
|
for (index, c) in node.children().enumerate() {
|
||||||
|
let row = &c.data.borrow().value;
|
||||||
|
let is_header = match *row {
|
||||||
|
NodeValue::TableRow(header) => header,
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
if !is_header {
|
||||||
|
header_index = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
header_index
|
||||||
|
};
|
||||||
|
let header_children: Vec<TokenStream> = children.drain(0..header_index).collect();
|
||||||
|
|
||||||
|
quote!(
|
||||||
|
<Table single_column=true>
|
||||||
|
<thead>
|
||||||
|
#(#header_children)*
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
#(#children)*
|
||||||
|
</tbody>
|
||||||
|
</Table>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
NodeValue::TableRow(_) => {
|
||||||
|
quote!(
|
||||||
|
<tr>
|
||||||
|
#(#children)*
|
||||||
|
</tr>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
NodeValue::TableCell => {
|
||||||
|
let row = &node.parent().unwrap().data.borrow().value;
|
||||||
|
let is_header = match *row {
|
||||||
|
NodeValue::TableRow(header) => header,
|
||||||
|
_ => panic!(),
|
||||||
|
};
|
||||||
|
if is_header {
|
||||||
|
quote!(
|
||||||
|
<th>
|
||||||
|
#(#children)*
|
||||||
|
</th>
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
quote!(
|
||||||
|
<td>
|
||||||
|
#(#children)*
|
||||||
|
</td>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NodeValue::Text(text) => {
|
||||||
|
let text = text.clone();
|
||||||
|
quote!(#text)
|
||||||
|
}
|
||||||
|
NodeValue::TaskItem(_) => quote!("TaskItem todo!!!"),
|
||||||
|
NodeValue::SoftBreak => quote!("\n"),
|
||||||
|
NodeValue::LineBreak => quote!(<br />),
|
||||||
|
NodeValue::Code(node_code) => {
|
||||||
|
let code = node_code.literal.clone();
|
||||||
|
quote!(
|
||||||
|
<Text code=true>
|
||||||
|
#code
|
||||||
|
</Text>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
NodeValue::HtmlInline(_) => quote!("HtmlInline todo!!!"),
|
||||||
|
NodeValue::Emph => quote!("Emph todo!!!"),
|
||||||
|
NodeValue::Strong => quote!("Strong todo!!!"),
|
||||||
|
NodeValue::Strikethrough => quote!("Strikethrough todo!!!"),
|
||||||
|
NodeValue::Superscript => quote!("Superscript todo!!!"),
|
||||||
|
NodeValue::Link(_) => quote!("Link todo!!!"),
|
||||||
|
NodeValue::Image(_) => quote!("Image todo!!!"),
|
||||||
|
NodeValue::FootnoteReference(_) => quote!("FootnoteReference todo!!!"),
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue