Added bindings & tests
This commit is contained in:
parent
35408f03b1
commit
b3b99c4069
10 changed files with 321 additions and 52 deletions
4
src/cache/cache.rs
vendored
4
src/cache/cache.rs
vendored
|
@ -23,7 +23,7 @@ pub trait Cached {
|
|||
|
||||
fn key(&self) -> <Self as Cached>::Key;
|
||||
|
||||
fn init(con: &mut Connection) -> Result<(), rusqlite::Error> {
|
||||
fn init(con: &Connection) -> Result<(), rusqlite::Error> {
|
||||
con.execute(<Self as Cached>::sql_table(), ()).map(|_| ())
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ pub trait Cached {
|
|||
/// Note that on error, [`f`] may still have been called
|
||||
fn cached<E, F>(
|
||||
&self,
|
||||
con: &mut Connection,
|
||||
con: &Connection,
|
||||
f: F,
|
||||
) -> Result<<Self as Cached>::Value, CachedError<E>>
|
||||
where
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use std::cell::Ref;
|
||||
use std::cell::RefCell;
|
||||
use std::cell::RefMut;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
@ -20,27 +19,20 @@ pub enum Target {
|
|||
LATEX,
|
||||
}
|
||||
|
||||
pub struct Compiler {
|
||||
pub struct Compiler<'a> {
|
||||
target: Target,
|
||||
cache: Option<RefCell<Connection>>,
|
||||
cache: Option<&'a Connection>,
|
||||
reference_count: RefCell<HashMap<String, HashMap<String, usize>>>,
|
||||
sections_counter: RefCell<Vec<usize>>,
|
||||
|
||||
unresolved_references: RefCell<Vec<(usize, CrossReference)>>,
|
||||
}
|
||||
|
||||
impl Compiler {
|
||||
pub fn new(target: Target, db_path: Option<String>) -> Self {
|
||||
let cache = match db_path {
|
||||
None => None,
|
||||
Some(path) => match Connection::open(path) {
|
||||
Err(e) => panic!("Cannot connect to database: {e}"),
|
||||
Ok(con) => Some(con),
|
||||
},
|
||||
};
|
||||
impl<'a> Compiler<'a> {
|
||||
pub fn new(target: Target, con: Option<&'a Connection>) -> Self {
|
||||
Self {
|
||||
target,
|
||||
cache: cache.map(|con| RefCell::new(con)),
|
||||
cache: con,
|
||||
reference_count: RefCell::new(HashMap::new()),
|
||||
sections_counter: RefCell::new(vec![]),
|
||||
unresolved_references: RefCell::new(vec![]),
|
||||
|
@ -94,7 +86,7 @@ impl Compiler {
|
|||
///
|
||||
/// # Parameters
|
||||
/// - [`reference`] The reference to get or insert
|
||||
pub fn reference_id<'a>(&self, document: &'a dyn Document, reference: ElemReference) -> usize {
|
||||
pub fn reference_id<'b>(&self, document: &'b dyn Document, reference: ElemReference) -> usize {
|
||||
let mut borrow = self.reference_count.borrow_mut();
|
||||
let reference = document.get_from_reference(&reference).unwrap();
|
||||
let refkey = reference.refcount_key();
|
||||
|
@ -129,8 +121,9 @@ impl Compiler {
|
|||
|
||||
pub fn target(&self) -> Target { self.target }
|
||||
|
||||
pub fn cache(&self) -> Option<RefMut<'_, Connection>> {
|
||||
self.cache.as_ref().map(RefCell::borrow_mut)
|
||||
pub fn cache(&self) -> Option<&'a Connection> {
|
||||
self.cache
|
||||
//self.cache.as_ref().map(RefCell::borrow_mut)
|
||||
}
|
||||
|
||||
pub fn header(&self, document: &dyn Document) -> String {
|
||||
|
|
|
@ -221,6 +221,8 @@ mod tests {
|
|||
use rand::rngs::OsRng;
|
||||
use rand::RngCore;
|
||||
|
||||
use crate::compiler::process::process_from_memory;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
|
@ -244,4 +246,54 @@ mod tests {
|
|||
assert_eq!(shuffled, entries);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn batch() {
|
||||
let result = process_from_memory(
|
||||
Target::HTML,
|
||||
vec![
|
||||
r#"
|
||||
@html.page_title = 0
|
||||
@compiler.output = 0.html
|
||||
@nav.title = C
|
||||
@nav.category = First
|
||||
"#
|
||||
.into(),
|
||||
r#"
|
||||
@html.page_title = 1
|
||||
@compiler.output = 1.html
|
||||
@nav.title = A
|
||||
@nav.category = First
|
||||
"#
|
||||
.into(),
|
||||
r#"
|
||||
@html.page_title = 2
|
||||
@compiler.output = 2.html
|
||||
@nav.title = B
|
||||
@nav.category = First
|
||||
"#
|
||||
.into(),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let nav = create_navigation(&result).unwrap();
|
||||
assert_eq!(nav.children.get("First").unwrap().entries, vec![
|
||||
(
|
||||
"A".to_string(),
|
||||
"1.html".to_string(),
|
||||
None,
|
||||
),
|
||||
(
|
||||
"B".to_string(),
|
||||
"2.html".to_string(),
|
||||
None,
|
||||
),
|
||||
(
|
||||
"C".to_string(),
|
||||
"0.html".to_string(),
|
||||
None,
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,7 +102,7 @@ pub fn process(
|
|||
let doc = parse(&parser, Rc::new(source), debug_opts)?;
|
||||
|
||||
// Compile
|
||||
let compiler = Compiler::new(target, db_path.clone());
|
||||
let compiler = Compiler::new(target, Some(&con));
|
||||
let (mut compiled, postprocess) = compiler.compile(&*doc);
|
||||
|
||||
compiled.mtime = modified.duration_since(UNIX_EPOCH).unwrap().as_secs();
|
||||
|
|
|
@ -268,15 +268,15 @@ impl Element for Code {
|
|||
Target::HTML => {
|
||||
static CACHE_INIT: Once = Once::new();
|
||||
CACHE_INIT.call_once(|| {
|
||||
if let Some(mut con) = compiler.cache() {
|
||||
if let Err(e) = Code::init(&mut con) {
|
||||
if let Some(con) = compiler.cache() {
|
||||
if let Err(e) = Code::init(con) {
|
||||
eprintln!("Unable to create cache table: {e}");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(mut con) = compiler.cache() {
|
||||
match self.cached(&mut con, |s| s.highlight_html(compiler)) {
|
||||
if let Some(con) = compiler.cache() {
|
||||
match self.cached(con, |s| s.highlight_html(compiler)) {
|
||||
Ok(s) => Ok(s),
|
||||
Err(e) => match e {
|
||||
CachedError::SqlErr(e) => {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use std::collections::HashMap;
|
||||
use std::ops::Range;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Once;
|
||||
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::util::Property;
|
||||
use crate::parser::util::PropertyMapError;
|
||||
|
@ -16,6 +18,9 @@ use crypto::sha2::Sha512;
|
|||
use graphviz_rust::cmd::Format;
|
||||
use graphviz_rust::cmd::Layout;
|
||||
use graphviz_rust::exec_dot;
|
||||
use mlua::Error::BadArgument;
|
||||
use mlua::Function;
|
||||
use mlua::Lua;
|
||||
use regex::Captures;
|
||||
use regex::Regex;
|
||||
|
||||
|
@ -111,21 +116,26 @@ impl Element for Graphviz {
|
|||
|
||||
fn element_name(&self) -> &'static str { "Graphviz" }
|
||||
|
||||
fn compile(&self, compiler: &Compiler, _document: &dyn Document, _cursor: usize) -> Result<String, String> {
|
||||
fn compile(
|
||||
&self,
|
||||
compiler: &Compiler,
|
||||
_document: &dyn Document,
|
||||
_cursor: usize,
|
||||
) -> Result<String, String> {
|
||||
match compiler.target() {
|
||||
Target::HTML => {
|
||||
static CACHE_INIT: Once = Once::new();
|
||||
CACHE_INIT.call_once(|| {
|
||||
if let Some(mut con) = compiler.cache() {
|
||||
if let Err(e) = Graphviz::init(&mut con) {
|
||||
if let Some(con) = compiler.cache() {
|
||||
if let Err(e) = Graphviz::init(con) {
|
||||
eprintln!("Unable to create cache table: {e}");
|
||||
}
|
||||
}
|
||||
});
|
||||
// TODO: Format svg in a div
|
||||
|
||||
if let Some(mut con) = compiler.cache() {
|
||||
match self.cached(&mut con, |s| s.dot_to_svg()) {
|
||||
if let Some(con) = compiler.cache() {
|
||||
match self.cached(con, |s| s.dot_to_svg()) {
|
||||
Ok(s) => Ok(s),
|
||||
Err(e) => match e {
|
||||
CachedError::SqlErr(e) => {
|
||||
|
@ -178,7 +188,7 @@ impl GraphRule {
|
|||
}
|
||||
|
||||
impl RegexRule for GraphRule {
|
||||
fn name(&self) -> &'static str { "Graph" }
|
||||
fn name(&self) -> &'static str { "Graphviz" }
|
||||
fn previous(&self) -> Option<&'static str> { Some("Tex") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
@ -360,4 +370,102 @@ impl RegexRule for GraphRule {
|
|||
|
||||
reports
|
||||
}
|
||||
|
||||
fn register_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
||||
let mut bindings = vec![];
|
||||
bindings.push((
|
||||
"push".to_string(),
|
||||
lua.create_function(|_, (layout, width, dot): (String, String, String)| {
|
||||
let mut result = Ok(());
|
||||
|
||||
CTX.with_borrow(|ctx| {
|
||||
ctx.as_ref().map(|ctx| {
|
||||
let layout = match layout_from_str(layout.as_str()) {
|
||||
Err(err) => {
|
||||
result = Err(BadArgument {
|
||||
to: Some("push".to_string()),
|
||||
pos: 1,
|
||||
name: Some("layout".to_string()),
|
||||
cause: Arc::new(mlua::Error::external(format!(
|
||||
"Unable to get layout type: {err}"
|
||||
))),
|
||||
});
|
||||
return;
|
||||
}
|
||||
Ok(layout) => layout,
|
||||
};
|
||||
|
||||
ctx.state.push(
|
||||
ctx.document,
|
||||
Box::new(Graphviz {
|
||||
location: ctx.location.clone(),
|
||||
dot,
|
||||
layout,
|
||||
width,
|
||||
}),
|
||||
);
|
||||
})
|
||||
});
|
||||
|
||||
result
|
||||
})
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
bindings
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::parser::langparser::LangParser;
|
||||
use crate::parser::parser::Parser;
|
||||
use crate::parser::source::SourceFile;
|
||||
use crate::validate_document;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
pub fn parse() {
|
||||
let source = Rc::new(SourceFile::with_content(
|
||||
"".to_string(),
|
||||
r#"
|
||||
[graph][width=200px, layout=neato]
|
||||
Some graph...
|
||||
[/graph]
|
||||
[graph]
|
||||
Another graph
|
||||
[/graph]
|
||||
"#
|
||||
.to_string(),
|
||||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Graphviz { width == "200px", dot == "Some graph..." };
|
||||
Graphviz { dot == "Another graph" };
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn lua() {
|
||||
let source = Rc::new(SourceFile::with_content(
|
||||
"".to_string(),
|
||||
r#"
|
||||
%<nml.graphviz.push("neato", "200px", "Some graph...")>%
|
||||
%<nml.graphviz.push("dot", "", "Another graph")>%
|
||||
"#
|
||||
.to_string(),
|
||||
None,
|
||||
));
|
||||
let parser = LangParser::default();
|
||||
let (doc, _) = parser.parse(ParserState::new(&parser, None), source, None);
|
||||
|
||||
validate_document!(doc.content().borrow(), 0,
|
||||
Graphviz { width == "200px", dot == "Some graph..." };
|
||||
Graphviz { dot == "Another graph" };
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -325,7 +325,7 @@ impl MediaRule {
|
|||
|
||||
impl RegexRule for MediaRule {
|
||||
fn name(&self) -> &'static str { "Media" }
|
||||
fn previous(&self) -> Option<&'static str> { Some("Graph") }
|
||||
fn previous(&self) -> Option<&'static str> { Some("Graphviz") }
|
||||
|
||||
fn regexes(&self) -> &[regex::Regex] { &self.re }
|
||||
|
||||
|
|
|
@ -366,15 +366,17 @@ use crate::parser::source::SourceFile;
|
|||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_external()
|
||||
{
|
||||
let result = process_from_memory(Target::HTML, vec![
|
||||
pub fn test_external() {
|
||||
let result = process_from_memory(
|
||||
Target::HTML,
|
||||
vec![
|
||||
r#"
|
||||
@html.page_title = 0
|
||||
@compiler.output = a.html
|
||||
|
||||
#{ref} Referenceable section
|
||||
"#.into(),
|
||||
"#
|
||||
.into(),
|
||||
r#"
|
||||
@html.page_title = 1
|
||||
@compiler.output = b.html
|
||||
|
@ -382,14 +384,18 @@ r#"
|
|||
§{#ref}
|
||||
§{a#ref}
|
||||
#{ref2} Another Referenceable section
|
||||
"#.into(),
|
||||
"#
|
||||
.into(),
|
||||
r#"
|
||||
@html.page_title = 2
|
||||
|
||||
§{#ref}[caption=from 0]
|
||||
§{#ref2}[caption=from 1]
|
||||
"#.into(),
|
||||
]).unwrap();
|
||||
"#
|
||||
.into(),
|
||||
],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
assert!(result[1].0.borrow().body.starts_with("<div class=\"content\"><p><a href=\"a.html#Referenceable_section\">#ref</a><a href=\"a.html#Referenceable_section\">a#ref</a></p>"));
|
||||
assert!(result[2].0.borrow().body.starts_with("<div class=\"content\"><p><a href=\"a.html#Referenceable_section\">from 0</a><a href=\"b.html#Another_Referenceable_section\">from 1</a></p>"));
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::process::Command;
|
|||
use std::process::Stdio;
|
||||
use std::rc::Rc;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Once;
|
||||
|
||||
use ariadne::Fmt;
|
||||
|
@ -14,6 +15,8 @@ use ariadne::Report;
|
|||
use ariadne::ReportKind;
|
||||
use crypto::digest::Digest;
|
||||
use crypto::sha2::Sha512;
|
||||
use mlua::Function;
|
||||
use mlua::Lua;
|
||||
use regex::Captures;
|
||||
use regex::Match;
|
||||
use regex::Regex;
|
||||
|
@ -25,6 +28,7 @@ use crate::compiler::compiler::Target;
|
|||
use crate::document::document::Document;
|
||||
use crate::document::element::ElemKind;
|
||||
use crate::document::element::Element;
|
||||
use crate::lua::kernel::CTX;
|
||||
use crate::parser::parser::ParserState;
|
||||
use crate::parser::parser::ReportColors;
|
||||
use crate::parser::rule::RegexRule;
|
||||
|
@ -149,13 +153,18 @@ impl Element for Tex {
|
|||
|
||||
fn element_name(&self) -> &'static str { "LaTeX" }
|
||||
|
||||
fn compile(&self, compiler: &Compiler, document: &dyn Document, _cursor: usize) -> Result<String, String> {
|
||||
fn compile(
|
||||
&self,
|
||||
compiler: &Compiler,
|
||||
document: &dyn Document,
|
||||
_cursor: usize,
|
||||
) -> Result<String, String> {
|
||||
match compiler.target() {
|
||||
Target::HTML => {
|
||||
static CACHE_INIT: Once = Once::new();
|
||||
CACHE_INIT.call_once(|| {
|
||||
if let Some(mut con) = compiler.cache() {
|
||||
if let Err(e) = FormattedTex::init(&mut con) {
|
||||
if let Some(con) = compiler.cache() {
|
||||
if let Err(e) = FormattedTex::init(con) {
|
||||
eprintln!("Unable to create cache table: {e}");
|
||||
}
|
||||
}
|
||||
|
@ -185,8 +194,8 @@ impl Element for Tex {
|
|||
Tex::format_latex(&fontsize, &preamble, &format!("{prepend}{}", self.tex))
|
||||
};
|
||||
|
||||
let result = if let Some(mut con) = compiler.cache() {
|
||||
match latex.cached(&mut con, |s| s.latex_to_svg(&exec, &fontsize)) {
|
||||
let result = if let Some(con) = compiler.cache() {
|
||||
match latex.cached(con, |s| s.latex_to_svg(&exec, &fontsize)) {
|
||||
Ok(s) => Ok(s),
|
||||
Err(e) => match e {
|
||||
CachedError::SqlErr(e) => {
|
||||
|
@ -427,6 +436,95 @@ impl RegexRule for TexRule {
|
|||
|
||||
reports
|
||||
}
|
||||
|
||||
fn register_bindings<'lua>(&self, lua: &'lua Lua) -> Vec<(String, Function<'lua>)> {
|
||||
let mut bindings = vec![];
|
||||
bindings.push((
|
||||
"push_math".to_string(),
|
||||
lua.create_function(
|
||||
|_, (env, kind, tex, caption): (Option<String>, String, String, Option<String>)| {
|
||||
let mut result = Ok(());
|
||||
CTX.with_borrow(|ctx| {
|
||||
ctx.as_ref().map(|ctx| {
|
||||
let kind = match TexKind::from_str(kind.as_str()) {
|
||||
Ok(kind) => kind,
|
||||
Err(err) => {
|
||||
result = Err(mlua::Error::BadArgument {
|
||||
to: Some("push".to_string()),
|
||||
pos: 2,
|
||||
name: Some("kind".to_string()),
|
||||
cause: Arc::new(mlua::Error::external(format!(
|
||||
"Unable to get tex kind: {err}"
|
||||
))),
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
ctx.state.push(
|
||||
ctx.document,
|
||||
Box::new(Tex {
|
||||
location: ctx.location.clone(),
|
||||
mathmode: true,
|
||||
kind,
|
||||
env: env.unwrap_or("main".to_string()),
|
||||
tex,
|
||||
caption,
|
||||
}),
|
||||
);
|
||||
})
|
||||
});
|
||||
|
||||
result
|
||||
},
|
||||
)
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
bindings.push((
|
||||
"push".to_string(),
|
||||
lua.create_function(
|
||||
|_, (env, kind, tex, caption): (Option<String>, String, String, Option<String>)| {
|
||||
let mut result = Ok(());
|
||||
CTX.with_borrow(|ctx| {
|
||||
ctx.as_ref().map(|ctx| {
|
||||
let kind = match TexKind::from_str(kind.as_str()) {
|
||||
Ok(kind) => kind,
|
||||
Err(err) => {
|
||||
result = Err(mlua::Error::BadArgument {
|
||||
to: Some("push".to_string()),
|
||||
pos: 2,
|
||||
name: Some("kind".to_string()),
|
||||
cause: Arc::new(mlua::Error::external(format!(
|
||||
"Unable to get tex kind: {err}"
|
||||
))),
|
||||
});
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
ctx.state.push(
|
||||
ctx.document,
|
||||
Box::new(Tex {
|
||||
location: ctx.location.clone(),
|
||||
mathmode: false,
|
||||
kind,
|
||||
env: env.unwrap_or("main".to_string()),
|
||||
tex,
|
||||
caption,
|
||||
}),
|
||||
);
|
||||
})
|
||||
});
|
||||
|
||||
result
|
||||
},
|
||||
)
|
||||
.unwrap(),
|
||||
));
|
||||
|
||||
bindings
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -447,6 +545,9 @@ mod tests {
|
|||
$[kind=block, caption=Some\, text\\] 1+1=2 $
|
||||
$|[env=another] Non Math \LaTeX |$
|
||||
$[kind=block,env=another] e^{i\pi}=-1$
|
||||
%<nml.tex.push_math(nil, "block", "1+1=2", "Some, text\\")>%
|
||||
%<nml.tex.push("another", "block", "Non Math \\LaTeX", nil)>%
|
||||
%<nml.tex.push_math("another", "block", "e^{i\\pi}=-1", nil)>%
|
||||
"#
|
||||
.to_string(),
|
||||
None,
|
||||
|
@ -458,6 +559,9 @@ $[kind=block,env=another] e^{i\pi}=-1$
|
|||
Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) };
|
||||
Tex { mathmode == false, tex == "Non Math \\LaTeX", env == "another" };
|
||||
Tex { mathmode == true, tex == "e^{i\\pi}=-1", env == "another" };
|
||||
Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) };
|
||||
Tex { mathmode == false, tex == "Non Math \\LaTeX", env == "another" };
|
||||
Tex { mathmode == true, tex == "e^{i\\pi}=-1", env == "another" };
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -469,6 +573,9 @@ $[kind=block,env=another] e^{i\pi}=-1$
|
|||
$[ caption=Some\, text\\] 1+1=2 $
|
||||
$|[env=another, kind=inline , caption = Enclosed \]. ] Non Math \LaTeX|$
|
||||
$[env=another] e^{i\pi}=-1$
|
||||
%<nml.tex.push_math("main", "inline", "1+1=2", "Some, text\\")>%
|
||||
%<nml.tex.push("another", "inline", "Non Math \\LaTeX", "Enclosed ].")>%
|
||||
%<nml.tex.push_math("another", "inline", "e^{i\\pi}=-1", nil)>%
|
||||
"#
|
||||
.to_string(),
|
||||
None,
|
||||
|
@ -479,7 +586,10 @@ $[env=another] e^{i\pi}=-1$
|
|||
validate_document!(doc.content().borrow(), 0,
|
||||
Paragraph {
|
||||
Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) };
|
||||
Tex { mathmode == false, tex == "Non Math \\LaTeX", env == "another" };
|
||||
Tex { mathmode == false, tex == "Non Math \\LaTeX", env == "another", caption == Some("Enclosed ].".to_string()) };
|
||||
Tex { mathmode == true, tex == "e^{i\\pi}=-1", env == "another" };
|
||||
Tex { mathmode == true, tex == "1+1=2", env == "main", caption == Some("Some, text\\".to_string()) };
|
||||
Tex { mathmode == false, tex == "Non Math \\LaTeX", env == "another", caption == Some("Enclosed ].".to_string()) };
|
||||
Tex { mathmode == true, tex == "e^{i\\pi}=-1", env == "another" };
|
||||
};
|
||||
);
|
||||
|
|
|
@ -205,7 +205,7 @@ mod tests {
|
|||
"Blockquote",
|
||||
"Code",
|
||||
"Tex",
|
||||
"Graph",
|
||||
"Graphviz",
|
||||
"Media",
|
||||
"Layout",
|
||||
"Style",
|
||||
|
|
Loading…
Reference in a new issue