Integrate Bibliographix

Signed-off-by: trivernis <trivernis@protonmail.com>
feature/epub-rendering
trivernis 4 years ago
parent 077394149b
commit ee822738b4
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

9
Cargo.lock generated

@ -54,11 +54,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bibliographix"
version = "0.3.1"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono-english 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -1141,11 +1142,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "snekdown"
version = "0.23.0"
version = "0.24.0"
dependencies = [
"asciimath-rs 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
"base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
"bibliographix 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bibliographix 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"charred 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
"colored 1.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1588,7 +1589,7 @@ dependencies = [
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum base64 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff"
"checksum bibliographix 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37feda13663b7ebab576b6d710c4c5b26f9e406556bdc60e38dd791bc7543e8d"
"checksum bibliographix 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a2a4e7a8fa9104c899346763b98d489704d1e00a95d2c3cc8b34d179ee350a35"
"checksum bincode 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum bumpalo 3.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820"

@ -1,6 +1,6 @@
[package]
name = "snekdown"
version = "0.23.0"
version = "0.24.0"
authors = ["trivernis <trivernis@protonmail.com>"]
edition = "2018"
license-file = "LICENSE"
@ -19,7 +19,7 @@ path = "src/main.rs"
[dependencies]
charred = "0.3.3"
asciimath-rs = "0.5.7"
bibliographix = "0.3.1"
bibliographix = "0.4.0"
crossbeam-utils = "0.7.2"
structopt = "0.3.14"
minify = "1.1.1"

@ -175,8 +175,8 @@ Bibliography entries can be defined and referenced anywhere in the document.
Definition:
```md
[book]:[author=Snek, title = "Snekdown Book"]
[github]: https://github.com/trivernis/snekdown
[SD_BOOK]:[type=book, author=Snek, title = "Snekdown Book" date="20.08.2020", publisher=Snek]
[SD_GITHUB]: https://github.com/trivernis/snekdown
```
Usage:
@ -184,7 +184,28 @@ Usage:
There is a book about snekdown[^book] and a github repo[^github].
```
Bibliography entries are only shown when used in the document.
Entries can also be defined in a separate toml file with the following data layout:
```toml
[BIB_KEY]
key = "value"
[SD_BOOK]
type = "book"
author = "Snek"
title = "Snekdown Book"
date = "20.08.2020"
publisher = "Snek"
[SD_GITHUB]
type = "website"
url = "https://github.com/trivernis/snekdown"
```
The valid types for entries and required fields can be found on in the [bibliographix README](https://github.com/Trivernis/bibliographix#bibliography-types-and-fields).
Bibliography entries are not rendered. To render a list of used bibliography insert the
`bib` placeholder at the place you want it to be rendered.
## Math

@ -57,6 +57,7 @@ pub enum Block {
pub enum Line {
Text(TextLine),
Ruler(Ruler),
RefLink(RefLink),
Anchor(Anchor),
Centered(Centered),
BibEntry(BibEntry),
@ -240,11 +241,17 @@ pub struct Placeholder {
}
#[derive(Clone, Debug)]
pub struct Anchor {
pub struct RefLink {
pub(crate) description: Box<Line>,
pub(crate) reference: String,
}
#[derive(Clone, Debug)]
pub struct Anchor {
pub(crate) inner: Box<Line>,
pub(crate) key: String,
}
#[derive(Clone, Debug)]
pub struct Centered {
pub(crate) line: TextLine,
@ -318,7 +325,8 @@ impl Document {
self.elements.iter().for_each(|e| match e {
Block::Section(sec) => {
if !sec.get_hide_in_toc() {
let mut item = ListItem::new(Line::Anchor(sec.header.get_anchor()), 1, ordered);
let mut item =
ListItem::new(Line::RefLink(sec.header.get_anchor()), 1, ordered);
item.children.append(&mut sec.get_toc_list(ordered).items);
list.add_item(item);
}
@ -419,7 +427,8 @@ impl Section {
self.elements.iter().for_each(|e| {
if let Block::Section(sec) = e {
if !sec.get_hide_in_toc() {
let mut item = ListItem::new(Line::Anchor(sec.header.get_anchor()), 1, ordered);
let mut item =
ListItem::new(Line::RefLink(sec.header.get_anchor()), 1, ordered);
item.children.append(&mut sec.get_toc_list(ordered).items);
list.add_item(item);
}
@ -483,8 +492,8 @@ impl Header {
}
}
pub fn get_anchor(&self) -> Anchor {
Anchor {
pub fn get_anchor(&self) -> RefLink {
RefLink {
description: Box::new(self.line.clone()),
reference: self.anchor.clone(),
}
@ -715,6 +724,10 @@ impl BibReference {
let mut template = PlaceholderTemplate::new(display.get().as_string());
let mut value_map = HashMap::new();
value_map.insert("key".to_string(), entry.key());
if let Some(ord) = entry.raw_fields.get("ord") {
value_map.insert("number".to_string(), ord.clone());
}
template.set_replacements(value_map);
return template.render();
}

@ -39,9 +39,10 @@ impl ToHtml for Line {
match self {
Line::Text(text) => text.to_html(),
Line::Ruler(ruler) => ruler.to_html(),
Line::Anchor(anchor) => anchor.to_html(),
Line::RefLink(anchor) => anchor.to_html(),
Line::Centered(centered) => centered.to_html(),
Line::BibEntry(_) => "".to_string(),
Line::Anchor(a) => a.to_html(),
}
}
}
@ -494,7 +495,7 @@ impl ToHtml for Placeholder {
}
}
impl ToHtml for Anchor {
impl ToHtml for RefLink {
fn to_html(&self) -> String {
format!(
"<a href='#{}'>{}</a>",
@ -595,3 +596,13 @@ impl ToHtml for CharacterCode {
format!("&{};", encode_minimal(self.code.as_str()))
}
}
impl ToHtml for Anchor {
fn to_html(&self) -> String {
format!(
"<div id='{}'>{}</div>",
encode_attribute(self.key.as_str()),
self.inner.to_html()
)
}
}

@ -9,6 +9,7 @@ use bibliographix::bib_manager::BibManager;
use charred::tapemachine::{CharTapeMachine, TapeError, TapeResult};
use colored::*;
use crossbeam_utils::sync::WaitGroup;
use regex::Regex;
use std::fs::{read_to_string, File};
use std::io;
use std::io::{BufRead, BufReader, Cursor};
@ -204,10 +205,31 @@ impl Parser {
Ok(anchor)
}
/// Imports a bibliography toml file
fn import_bib(&mut self, path: PathBuf) -> ParseResult<()> {
let f = File::open(path).map_err(|_| self.ctm.err())?;
self.document
.bibliography
.read_bib_file(&mut BufReader::new(f))
.map_err(|_| self.ctm.err())?;
Ok(())
}
/// Imports a path
fn import(&mut self, path: String) -> ImportType {
let path = self.transform_path(path);
lazy_static::lazy_static! {
static ref BIB_NAME: Regex = Regex::new(r".*\.bib\.toml$").unwrap();
}
if let Some(fname) = path.file_name().and_then(|f| Some(f.to_str().unwrap())) {
if BIB_NAME.is_match(fname) {
return ImportType::Bibliography(self.import_bib(path));
}
}
match path.extension() {
Some(e) if e.to_str().unwrap() == "css" => {
Some(e) if e.to_str().unwrap().to_lowercase() == "css" => {
if let Ok(content) = read_to_string(path) {
ImportType::Stylesheet(Ok(content))
} else {
@ -253,4 +275,5 @@ impl Parser {
pub(crate) enum ImportType {
Document(ParseResult<Arc<RwLock<ImportAnchor>>>),
Stylesheet(ParseResult<String>),
Bibliography(ParseResult<()>),
}

@ -1,5 +1,5 @@
use crate::elements::Inline;
use crate::elements::{BoldText, ItalicText, Line, List, ListItem, PlainText, TextLine};
use crate::elements::{Anchor, BoldText, ItalicText, Line, List, ListItem, PlainText, TextLine};
use crate::elements::{Inline, Url};
use bibliographix::bibliography::bib_types::article::Article;
use bibliographix::bibliography::bib_types::book::Book;
use bibliographix::bibliography::bib_types::booklet::Booklet;
@ -39,12 +39,44 @@ macro_rules! italic_text {
};
}
macro_rules! url_text {
($e:expr) => {
Inline::Url(Url {
url: $e,
description: None,
})
};
}
macro_rules! list_item {
($e:expr, $k:expr) => {
ListItem::new(
Line::Anchor(Anchor {
inner: Box::new(Line::Text($e)),
key: $k,
}),
0,
true,
)
};
}
const DATE_FORMAT: &str = "%d.%m.%Y";
/// Creates a list from a list of bib items
pub fn create_bib_list(entries: Vec<BibliographyEntryReference>) -> List {
let mut list = List::new();
list.ordered = true;
let mut count = 1;
for entry in entries {
entry
.lock()
.unwrap()
.raw_fields
.insert("ord".to_string(), count.to_string());
list.add_item(get_item_for_entry(entry));
count += 1;
}
list
@ -73,8 +105,6 @@ fn get_item_for_entry(entry: BibliographyEntryReference) -> ListItem {
/// Returns the formatted article bib entry
fn get_item_for_article(entry: &BibliographyEntry, a: &Article) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
text.subtext
.push(plain_text!(format!("{}.", a.author.clone())));
text.subtext
@ -90,23 +120,26 @@ fn get_item_for_article(entry: &BibliographyEntry, a: &Article) -> ListItem {
.push(plain_text!(format!(", Number: {}", number)));
}
text.subtext
.push(plain_text!(format!(", {}", a.date.format("%d.%m.%y"))));
.push(plain_text!(format!(", {}", a.date.format(DATE_FORMAT))));
if let Some(pages) = a.pages.clone() {
text.subtext
.push(plain_text!(format!(", Pages: {}", pages)));
}
if let Some(url) = a.url.clone() {
text.subtext.push(plain_text!(format!(", URL: {}", url)));
text.subtext.push(plain_text!(", URL: ".to_string()));
text.subtext.push(url_text!(url));
}
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns a list item for a book entry
fn get_item_for_book(entry: &BibliographyEntry, b: &Book) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
text.subtext
.push(plain_text!(format!("{}.", b.author.clone())));
text.subtext
@ -128,21 +161,23 @@ fn get_item_for_book(entry: &BibliographyEntry, b: &Book) -> ListItem {
)
.to_string()));
text.subtext
.push(plain_text!(format!("on {}", b.date.format("%d.%m.%y"))));
.push(plain_text!(format!("on {}", b.date.format(DATE_FORMAT))));
if let Some(url) = b.url.clone() {
text.subtext.push(plain_text!(format!("URL: {}", url)))
text.subtext.push(plain_text!(", URL: ".to_string()));
text.subtext.push(url_text!(url));
}
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns the list item for a booklet
fn get_item_for_booklet(entry: &BibliographyEntry, b: &Booklet) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
if let Some(author) = b.author.clone() {
text.subtext.push(plain_text!(format!("{}.", author)))
text.subtext.push(plain_text!(format!("{}. ", author)))
}
text.subtext
.push(plain_text!(format!("\"{}\", Published ", b.title.clone())));
@ -151,19 +186,20 @@ fn get_item_for_booklet(entry: &BibliographyEntry, b: &Booklet) -> ListItem {
}
if let Some(date) = b.date {
text.subtext
.push(plain_text!(format!("on {}", date.format("%d.%m.%y"))))
.push(plain_text!(format!("on {}", date.format(DATE_FORMAT))))
}
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns the list item for an in book bib entry
fn get_item_for_in_book(entry: &BibliographyEntry, ib: &InBook) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
text.subtext
.push(plain_text!(format!("{}.", ib.author.clone())));
.push(plain_text!(format!("{}. ", ib.author.clone())));
text.subtext
.push(plain_text!(format!("\"{}\"", ib.title.clone())));
text.subtext
@ -183,17 +219,18 @@ fn get_item_for_in_book(entry: &BibliographyEntry, ib: &InBook) -> ListItem {
", Published By: {}",
ib.publisher.clone()
)));
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns the list item for an InCollection bib entry
fn get_item_for_in_collection(entry: &BibliographyEntry, ic: &InCollection) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
text.subtext
.push(plain_text!(format!("{}.", ic.author.clone())));
.push(plain_text!(format!("{}. ", ic.author.clone())));
if let Some(editor) = ic.editor.clone() {
text.subtext
@ -216,18 +253,19 @@ fn get_item_for_in_collection(entry: &BibliographyEntry, ic: &InCollection) -> L
text.subtext.push(plain_text!("In: ".to_string()));
text.subtext.push(italic_text!(series))
}
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns the list item for a manual
fn get_item_for_manual(entry: &BibliographyEntry, m: &Manual) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
if let Some(author) = m.author.clone() {
text.subtext.push(plain_text!(format!("{}.", author)));
text.subtext.push(plain_text!(format!("{}. ", author)));
}
text.subtext
.push(plain_text!(format!("\"{}\"", m.title.clone())));
@ -241,20 +279,21 @@ fn get_item_for_manual(entry: &BibliographyEntry, m: &Manual) -> ListItem {
}
if let Some(date) = m.date {
text.subtext
.push(plain_text!(format!(" on {}", date.format("%d.%m.%y"))))
.push(plain_text!(format!(" on {}", date.format(DATE_FORMAT))))
}
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns the list item for a misc bib entry
fn get_item_for_misc(entry: &BibliographyEntry, m: &Misc) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
if let Some(author) = m.author.clone() {
text.subtext.push(plain_text!(format!("{}.", author)));
text.subtext.push(plain_text!(format!("{}. ", author)));
}
if let Some(title) = m.title.clone() {
text.subtext.push(plain_text!(format!("\"{}\"", title)));
@ -264,83 +303,88 @@ fn get_item_for_misc(entry: &BibliographyEntry, m: &Misc) -> ListItem {
}
if let Some(date) = m.date {
text.subtext
.push(plain_text!(format!("on {}", date.format("%d.%m.%y"))))
.push(plain_text!(format!("on {}", date.format(DATE_FORMAT))))
}
if let Some(url) = m.url.clone() {
text.subtext.push(plain_text!(format!(", URL: {}", url)));
}
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns a list item for a repository bib entry
fn get_item_for_repository(entry: &BibliographyEntry, r: &Repository) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
text.subtext.push(italic_text!(r.title.clone()));
text.subtext
.push(plain_text!(format!(" by {}", r.author.clone())));
if let Some(url) = r.url.clone() {
text.subtext.push(plain_text!(format!(", URL: {}", url)))
text.subtext.push(plain_text!(", URL: ".to_string()));
text.subtext.push(url_text!(url));
}
if let Some(accessed) = r.accessed_at.clone() {
text.subtext.push(plain_text!(format!(
"(accessed: {})",
accessed.format("%d.%m.%y")
accessed.format(DATE_FORMAT)
)))
}
if let Some(license) = r.license.clone() {
text.subtext
.push(plain_text!(format!(", License: {}", license)))
}
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns the list item for the tech report type
fn get_item_for_tech_report(entry: &BibliographyEntry, tr: &TechReport) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
text.subtext
.push(plain_text!(format!("{}.", tr.author.clone())));
.push(plain_text!(format!("{}. ", tr.author.clone())));
text.subtext
.push(plain_text!(format!("\"{}\"", tr.title.clone())));
text.subtext
.push(plain_text!(format!("by {}", tr.institution.clone())));
.push(plain_text!(format!(" by {}", tr.institution.clone())));
text.subtext
.push(plain_text!(format!(" on {}", tr.date.format("%d.%m.%y"))));
.push(plain_text!(format!(" on {}", tr.date.format(DATE_FORMAT))));
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns a list item for a thesis
fn get_item_for_thesis(entry: &BibliographyEntry, t: &Thesis) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
text.subtext
.push(plain_text!(format!("{}.", t.author.clone())));
.push(plain_text!(format!("{}. ", t.author.clone())));
text.subtext
.push(plain_text!(format!("\"{}\"", t.title.clone())));
.push(plain_text!(format!("\"{}\" ", t.title.clone())));
text.subtext
.push(plain_text!(format!("at {}", t.school.clone())));
text.subtext
.push(plain_text!(format!(" on {}", t.date.format("%d.%m.%y"))));
.push(plain_text!(format!(" on {}", t.date.format(DATE_FORMAT))));
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
/// Returns the list item for an unpublished bib type
fn get_item_for_unpublished(entry: &BibliographyEntry, u: &Unpublished) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
text.subtext
.push(plain_text!(format!("{}.", u.author.clone())));
@ -348,36 +392,40 @@ fn get_item_for_unpublished(entry: &BibliographyEntry, u: &Unpublished) -> ListI
.push(plain_text!(format!("\"{}\"", u.title.clone())));
if let Some(date) = u.date.clone() {
text.subtext
.push(plain_text!(format!(" on {}", date.format("%d.%m.%y"))));
.push(plain_text!(format!(" on {}", date.format(DATE_FORMAT))));
}
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}
fn get_item_for_website(entry: &BibliographyEntry, w: &Website) -> ListItem {
let mut text = TextLine::new();
text.subtext
.push(bold_text!(format!("{}: ", entry.key().clone())));
if let Some(title) = w.title.clone() {
text.subtext.push(italic_text!(format!("{} - ", title)));
}
text.subtext.push(plain_text!(format!("{}", w.url)));
text.subtext.push(url_text!(w.url.clone()));
if let Some(author) = w.author.clone() {
text.subtext.push(bold_text!(format!(" by {}", author)))
}
if let Some(accessed) = w.accessed_at.clone() {
text.subtext.push(plain_text!(format!(
"(accessed: {})",
accessed.format("%d.%m.%y")
accessed.format(DATE_FORMAT)
)))
}
if let Some(date) = w.date.clone() {
text.subtext.push(plain_text!(format!(
", Published On: {}",
date.format("%d.%m.%y")
date.format(DATE_FORMAT)
)))
}
if let Some(notes) = entry.note.clone() {
text.subtext.push(plain_text!(notes))
}
ListItem::new(Line::Text(text), 0, true)
list_item!(text, entry.key())
}

@ -1,4 +1,4 @@
[bibliography]
entry_display = "{{number}}: {{author}} - {{title}} - {{date}} - {{url}}"
reference_display = "{{key}}"
reference_display = "{{number}}"
hide_unused = true

@ -1,4 +1,5 @@
use crate::elements::*;
use crate::references::bibliography::create_bib_list;
use chrono::prelude::*;
use regex::Regex;
@ -29,6 +30,7 @@ pub(crate) trait ProcessPlaceholders {
const S_VALUE: &str = "value";
const P_TOC: &str = "toc";
const P_BIB: &str = "bib";
const P_DATE: &str = "date";
const P_TIME: &str = "time";
const P_DATETIME: &str = "datetime";
@ -47,6 +49,9 @@ impl ProcessPlaceholders for Document {
};
pholder.set_value(block!(Block::List(self.create_toc(ordered))))
}
P_BIB => pholder.set_value(block!(Block::List(create_bib_list(
self.bibliography.get_entry_list_by_occurrence()
)))),
P_DATE => pholder.set_value(inline!(Inline::Plain(PlainText {
value: get_date_string()
}))),

Loading…
Cancel
Save