mirror of
https://github.com/lise-henry/crowbook
synced 2024-05-27 13:06:15 +02:00
Remove warnings
This commit is contained in:
parent
6b0f4b7637
commit
487864ffbb
|
@ -33,7 +33,6 @@ output.html:path # {output_html}
|
|||
output.html.dir:path # {output_html_dir}
|
||||
output.tex:path # {output_tex}
|
||||
output.pdf:path # {output_pdf}
|
||||
output.odt:path # {output_odt}
|
||||
output.html.if:path # {output_if}
|
||||
output.base_path:path:\"\" # {output_base_path}
|
||||
|
||||
|
@ -201,6 +200,8 @@ proofread.repetitions.fuzzy:bool:true # {removed}
|
|||
proofread.repetitions.fuzzy.threshold:float:0.2 # {removed}
|
||||
proofread.repetitions.ignore_proper:bool:true # {removed}
|
||||
proofread.repetitions.threshold:float:2.0 # {removed}
|
||||
output.odt:path # {removed}
|
||||
|
||||
",
|
||||
metadata = lformat!("Metadata"),
|
||||
metadata2 = lformat!("Additional metadata"),
|
||||
|
@ -236,7 +237,6 @@ proofread.repetitions.threshold:float:2.0 # {removed}
|
|||
output_html = lformat!("Output file name for HTML rendering"),
|
||||
output_tex = lformat!("Output file name for LaTeX rendering"),
|
||||
output_pdf = lformat!("Output file name for PDF rendering"),
|
||||
output_odt = lformat!("Output file name for ODT rendering"),
|
||||
output_if = lformat!("Output file name for HTML (interactive fiction) rendering"),
|
||||
output_html_dir = lformat!("Output directory name for HTML rendering"),
|
||||
output_base_path = lformat!("Directory where those output files will we written"),
|
||||
|
@ -835,7 +835,6 @@ impl BookOptions {
|
|||
| "output.html.dir"
|
||||
| "output.pdf"
|
||||
| "output.tex"
|
||||
| "output.odt"
|
||||
| "output.proofread.html"
|
||||
| "output.proofread.html.dir"
|
||||
| "output.proofread.pdf"
|
||||
|
|
|
@ -28,7 +28,6 @@ use crate::syntax::Syntax;
|
|||
use crate::token::Data;
|
||||
use crate::token::Token;
|
||||
use crate::text_view;
|
||||
use crate::misc;
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::convert::{AsMut, AsRef};
|
||||
|
|
|
@ -145,8 +145,6 @@ mod html_single;
|
|||
mod lang;
|
||||
mod latex;
|
||||
mod number;
|
||||
#[cfg(feature = "odt")]
|
||||
mod odt;
|
||||
mod parser;
|
||||
mod renderer;
|
||||
mod resource_handler;
|
||||
|
|
284
src/lib/odt.rs
284
src/lib/odt.rs
|
@ -1,284 +0,0 @@
|
|||
use crate::book::{compile_str, Book};
|
||||
use crate::book_renderer::BookRenderer;
|
||||
use crate::error::Result;
|
||||
use crate::number::Number;
|
||||
use crate::parser::Parser;
|
||||
use crate::templates::odt;
|
||||
use crate::token::Token;
|
||||
use crate::zipper::Zipper;
|
||||
|
||||
use crowbook_text_processing::escape;
|
||||
|
||||
use std::io::Write;
|
||||
|
||||
/// Rendererer for ODT
|
||||
///
|
||||
/// Still very experimental.
|
||||
pub struct OdtRenderer<'a> {
|
||||
book: &'a Book,
|
||||
current_numbering: i32,
|
||||
current_hide: bool,
|
||||
current_chapter: i32,
|
||||
automatic_styles: String,
|
||||
}
|
||||
|
||||
impl<'a> OdtRenderer<'a> {
|
||||
/// Creates a new OdtRenderer
|
||||
pub fn new(book: &'a Book) -> OdtRenderer {
|
||||
OdtRenderer {
|
||||
book,
|
||||
current_chapter: 1,
|
||||
current_numbering: book.options.get_i32("rendering.num_depth").unwrap(),
|
||||
current_hide: false,
|
||||
automatic_styles: String::from(
|
||||
"
|
||||
<style:style style:name=\"T1\" \
|
||||
style:family=\"text\">
|
||||
<style:text-properties \
|
||||
fo:font-style=\"italic\" \
|
||||
style:font-style-asian=\"italic\" \
|
||||
style:font-style-complex=\"italic\"/>
|
||||
</style:style>
|
||||
\
|
||||
<style:style style:name=\"T2\" \
|
||||
style:family=\"text\">
|
||||
<style:text-properties \
|
||||
fo:font-weight=\"bold\" \
|
||||
style:font-weight-asian=\"bold\" \
|
||||
style:font-weight-complex=\"bold\"/>
|
||||
</style:style>",
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
/// Renders a full book
|
||||
///
|
||||
/// This will try to generate an ODT file according to self.book options.
|
||||
///
|
||||
/// # Returns
|
||||
/// * `Ok(s)` where `s` contains the output of the `zip` command
|
||||
/// used to create the ODT file.
|
||||
/// * An error if there was somel problem during either the rendering to
|
||||
/// ODT format, or the generation of the ODT file itself.
|
||||
pub fn render_book(&mut self, to: &mut dyn Write) -> Result<String> {
|
||||
let content = self.render_content()?;
|
||||
|
||||
let mut zipper = Zipper::new(&self.book.options.get_path("crowbook.temp_dir").unwrap())?;
|
||||
|
||||
// Write template.odt there
|
||||
zipper.write("template.odt", odt::ODT, false)?;
|
||||
// unzip it
|
||||
zipper.unzip("template.odt")?;
|
||||
// Complete it with content.xml
|
||||
zipper.write("content.xml", content.as_bytes(), false)?;
|
||||
// Zip and copy
|
||||
zipper.generate_odt(
|
||||
self.book.options.get_str("crowbook.zip.command").unwrap(),
|
||||
to,
|
||||
)
|
||||
}
|
||||
|
||||
/// Render content.xml
|
||||
fn render_content(&mut self) -> Result<String> {
|
||||
// Print a warning for the features that aren't supported in ODT.
|
||||
let mut missing = vec![];
|
||||
if self.book.features.image {
|
||||
missing.push(lformat!("images"));
|
||||
}
|
||||
if self.book.features.blockquote {
|
||||
missing.push(lformat!("blockquotes"));
|
||||
}
|
||||
if self.book.features.codeblock {
|
||||
missing.push(lformat!("codeblocks"));
|
||||
}
|
||||
if self.book.features.ordered_list {
|
||||
missing.push(lformat!("ordered lists"));
|
||||
}
|
||||
if self.book.features.footnote {
|
||||
missing.push(lformat!("footnotes"));
|
||||
}
|
||||
if self.book.features.table {
|
||||
missing.push(lformat!("tables"));
|
||||
}
|
||||
if self.book.features.superscript {
|
||||
missing.push(lformat!("superscript"));
|
||||
}
|
||||
if self.book.features.subscript {
|
||||
missing.push(lformat!("subscript"));
|
||||
}
|
||||
|
||||
if !missing.is_empty() {
|
||||
let missing = missing.join(", ");
|
||||
warn!("{}", lformat!("ODT: The document uses the following features, that are not implemented for ODT output: {features}. They will be ignored in the generated document.",
|
||||
features = missing));
|
||||
}
|
||||
|
||||
let mut content = String::new();
|
||||
|
||||
for chapter in &self.book.chapters {
|
||||
let n = chapter.number;
|
||||
let v = &chapter.content;
|
||||
self.current_hide = false;
|
||||
match n {
|
||||
Number::Unnumbered | Number::UnnumberedPart => self.current_numbering = 0,
|
||||
Number::Default | Number::DefaultPart => {
|
||||
self.current_numbering =
|
||||
self.book.options.get_i32("rendering.num_depth").unwrap()
|
||||
}
|
||||
Number::Specified(n) | Number::SpecifiedPart(n) => {
|
||||
self.current_numbering = self.book.options.get_i32("numbering").unwrap();
|
||||
self.current_chapter = n;
|
||||
}
|
||||
Number::Hidden => {
|
||||
self.current_numbering = 0;
|
||||
self.current_hide = true;
|
||||
}
|
||||
}
|
||||
if n.is_part() {
|
||||
error!("{}", lformat!("Parts are not supported yet in ODT"));
|
||||
}
|
||||
|
||||
for token in v {
|
||||
content.push_str(&self.parse_token(token));
|
||||
}
|
||||
}
|
||||
|
||||
let template = compile_str(
|
||||
odt::CONTENT,
|
||||
&self.book.source,
|
||||
"could not compile template for content.xml",
|
||||
)?;
|
||||
let data = self
|
||||
.book
|
||||
.get_metadata(|s| Ok(s.to_owned()))?
|
||||
.insert_str("content", content)
|
||||
.insert_str("automatic_styles", self.automatic_styles.clone())
|
||||
.build();
|
||||
|
||||
let mut res: Vec<u8> = vec![];
|
||||
template.render_data(&mut res, &data)?;
|
||||
match String::from_utf8(res) {
|
||||
Err(_) => panic!("{}", lformat!("generated content.xml was not utf-8 valid")),
|
||||
Ok(res) => Ok(res),
|
||||
}
|
||||
}
|
||||
|
||||
/// Transform a vector of `Token`s to Odt format
|
||||
fn render_vec(&mut self, tokens: &[Token]) -> String {
|
||||
let mut res = String::new();
|
||||
|
||||
for token in tokens {
|
||||
res.push_str(&self.parse_token(token));
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
fn parse_token(&mut self, token: &Token) -> String {
|
||||
match *token {
|
||||
Token::Str(ref text) => escape::html(self.book.clean(text.as_str())).into_owned(),
|
||||
Token::Paragraph(ref vec) => {
|
||||
format!(
|
||||
"<text:p text:style-name=\"Text_20_body\">{}</text:p>\n",
|
||||
self.render_vec(vec)
|
||||
)
|
||||
}
|
||||
Token::Header(n, ref vec) => {
|
||||
if n == 1 && self.current_hide {
|
||||
return String::new();
|
||||
}
|
||||
let s = if n == 1 && self.current_numbering >= 1 {
|
||||
let chapter = self.current_chapter;
|
||||
self.current_chapter += 1;
|
||||
let res = self
|
||||
.book
|
||||
.get_chapter_header(chapter, self.render_vec(vec), |s| {
|
||||
Ok(self.render_vec(&Parser::new().parse_inline(s)?))
|
||||
});
|
||||
res.unwrap().text
|
||||
} else {
|
||||
self.render_vec(vec)
|
||||
};
|
||||
format!(
|
||||
"<text:h text:style-name=\"Heading_20_{}\">\n{}</text:h>\n",
|
||||
n, s
|
||||
)
|
||||
}
|
||||
Token::Emphasis(ref vec) => {
|
||||
format!(
|
||||
"<text:span text:style-name=\"T1\">{}</text:span>",
|
||||
self.render_vec(vec)
|
||||
)
|
||||
}
|
||||
Token::Strong(ref vec) => {
|
||||
format!(
|
||||
"<text:span text:style-name=\"T2\">{}</text:span>",
|
||||
self.render_vec(vec)
|
||||
)
|
||||
}
|
||||
Token::List(ref vec) => format!("<text:list>\n{}</text:list>\n", self.render_vec(vec)),
|
||||
Token::OrderedList(_, ref vec) => {
|
||||
format!("<text:list>\n{}</text:list>\n", self.render_vec(vec))
|
||||
}
|
||||
Token::Item(ref vec) => {
|
||||
format!(
|
||||
"<text:list-item>\n<text:p>{}</text:p></text:list-item>",
|
||||
self.render_vec(vec)
|
||||
)
|
||||
}
|
||||
Token::Link(ref url, _, ref vec) => {
|
||||
format!(
|
||||
"<text:a xlink:type=\"simple\" xlink:href=\"{}\">{}</text:a>",
|
||||
url,
|
||||
self.render_vec(vec)
|
||||
)
|
||||
}
|
||||
Token::Code(ref s) => {
|
||||
format!(
|
||||
"<text:span text:style-name=\"Preformatted_20_Text\">{}</text:span>",
|
||||
s
|
||||
)
|
||||
}
|
||||
Token::Subscript(ref vec) | Token::Superscript(ref vec) => self.render_vec(vec),
|
||||
Token::BlockQuote(ref vec) => format!(
|
||||
"<text:p text:style-name=\"Text_20_Body\">{}</text:p>\n",
|
||||
self.render_vec(vec)
|
||||
),
|
||||
Token::CodeBlock(_, ref s) => {
|
||||
format!("<text:p text:style-name=\"Text_20_Body\">{}</text:p>\n", s)
|
||||
}
|
||||
Token::SoftBreak | Token::HardBreak => String::from(" "),
|
||||
Token::Rule => String::from("<text:p /><text:p>***</text:p><text:p />"),
|
||||
Token::Image(_, _, _) | Token::StandaloneImage(_, _, _) => String::from(" "),
|
||||
Token::Table(_, _) | Token::TableHead(_) | Token::TableRow(_) | Token::TableCell(_) => {
|
||||
String::from(" ")
|
||||
}
|
||||
Token::FootnoteReference(..) | Token::FootnoteDefinition(..) => String::new(),
|
||||
Token::Annotation(_, ref vec) => self.render_vec(vec),
|
||||
Token::DescriptionList(ref v)
|
||||
| Token::DescriptionItem(ref v)
|
||||
| Token::DescriptionTerm(ref v)
|
||||
| Token::DescriptionDetails(ref v)
|
||||
| Token::Strikethrough(ref v)
|
||||
| Token::TaskItem(_, ref v) => {
|
||||
warn!(
|
||||
"{}",
|
||||
lformat!("ODT: Description list and strikethrough not handled in this output")
|
||||
);
|
||||
self.render_vec(v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Odt {}
|
||||
|
||||
impl BookRenderer for Odt {
|
||||
fn auto_path(&self, book_name: &str) -> Result<String> {
|
||||
Ok(format!("{}.odt", book_name))
|
||||
}
|
||||
|
||||
fn render(&self, book: &Book, to: &mut dyn Write) -> Result<()> {
|
||||
OdtRenderer::new(book).render_book(to)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -16,9 +16,7 @@
|
|||
// along with Crowbook. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::default::Default;
|
||||
use std::mem;
|
||||
|
||||
use crate::token::Data;
|
||||
use crate::token::Token;
|
||||
|
||||
pub fn traverse_token<F1, F2, R>(token: &Token, f: &F1, add: &F2) -> R
|
||||
|
@ -67,210 +65,212 @@ pub fn view_as_text(tokens: &[Token]) -> String {
|
|||
traverse_vec(tokens, &|s| s.to_owned(), &|s1, s2| s1 + &s2)
|
||||
}
|
||||
|
||||
pub fn count_length(tokens: &[Token]) -> usize {
|
||||
traverse_vec(tokens, &|s| s.chars().count(), &|s1, s2| s1 + s2)
|
||||
}
|
||||
// Should it be removed?
|
||||
// pub fn count_length(tokens: &[Token]) -> usize {
|
||||
// traverse_vec(tokens, &|s| s.chars().count(), &|s1, s2| s1 + s2)
|
||||
// }
|
||||
|
||||
/// Insert an annotation at begin and end pos begin+len in the text_view
|
||||
#[doc(hidden)]
|
||||
pub fn insert_annotation(
|
||||
tokens: &mut Vec<Token>,
|
||||
annotation: &Data,
|
||||
pos: usize,
|
||||
length: usize,
|
||||
) -> Option<usize> {
|
||||
let mut pos = pos;
|
||||
let mut found_left = None;
|
||||
let mut found_right = None;
|
||||
for (i, item) in tokens.iter_mut().enumerate() {
|
||||
let recurse = match item {
|
||||
Token::Str(ref s) => {
|
||||
let len = s.chars().count();
|
||||
if pos < len || (pos == len && found_left.is_some()) {
|
||||
// We found the first element already, so now it's the right
|
||||
if found_left.is_some() {
|
||||
found_right = Some((i, pos));
|
||||
break;
|
||||
}
|
||||
found_left = Some((i, pos));
|
||||
pos += length;
|
||||
if pos <= len {
|
||||
found_right = Some((i, pos));
|
||||
break;
|
||||
}
|
||||
}
|
||||
pos -= len;
|
||||
false
|
||||
}
|
||||
// Should it be removed ?
|
||||
// #[doc(hidden)]
|
||||
// pub fn insert_annotation(
|
||||
// tokens: &mut Vec<Token>,
|
||||
// annotation: &Data,
|
||||
// pos: usize,
|
||||
// length: usize,
|
||||
// ) -> Option<usize> {
|
||||
// let mut pos = pos;
|
||||
// let mut found_left = None;
|
||||
// let mut found_right = None;
|
||||
// for (i, item) in tokens.iter_mut().enumerate() {
|
||||
// let recurse = match item {
|
||||
// Token::Str(ref s) => {
|
||||
// let len = s.chars().count();
|
||||
// if pos < len || (pos == len && found_left.is_some()) {
|
||||
// // We found the first element already, so now it's the right
|
||||
// if found_left.is_some() {
|
||||
// found_right = Some((i, pos));
|
||||
// break;
|
||||
// }
|
||||
// found_left = Some((i, pos));
|
||||
// pos += length;
|
||||
// if pos <= len {
|
||||
// found_right = Some((i, pos));
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// pos -= len;
|
||||
// false
|
||||
// }
|
||||
|
||||
Token::Rule | Token::SoftBreak | Token::HardBreak => {
|
||||
if pos < 1 {
|
||||
if found_left.is_some() {
|
||||
found_right = Some((i, pos));
|
||||
break;
|
||||
}
|
||||
found_left = Some((i, pos));
|
||||
pos += length;
|
||||
if pos <= 1 {
|
||||
found_right = Some((i, pos));
|
||||
break;
|
||||
}
|
||||
}
|
||||
pos -= 1;
|
||||
false
|
||||
}
|
||||
// Token::Rule | Token::SoftBreak | Token::HardBreak => {
|
||||
// if pos < 1 {
|
||||
// if found_left.is_some() {
|
||||
// found_right = Some((i, pos));
|
||||
// break;
|
||||
// }
|
||||
// found_left = Some((i, pos));
|
||||
// pos += length;
|
||||
// if pos <= 1 {
|
||||
// found_right = Some((i, pos));
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// pos -= 1;
|
||||
// false
|
||||
// }
|
||||
|
||||
_ => {
|
||||
if let Some(inner) = item.inner() {
|
||||
let len = count_length(inner);
|
||||
// Only recurse if the two is in this subtree
|
||||
if pos < len {
|
||||
if found_left.is_none() {
|
||||
true
|
||||
} else {
|
||||
warn!(
|
||||
"{}",
|
||||
lformat!(
|
||||
"ignored annotation {:?} as it \
|
||||
wasn't compatible with the \
|
||||
Markdown structure",
|
||||
annotation
|
||||
)
|
||||
);
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
pos -= len;
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
};
|
||||
// _ => {
|
||||
// if let Some(inner) = item.inner() {
|
||||
// let len = count_length(inner);
|
||||
// // Only recurse if the two is in this subtree
|
||||
// if pos < len {
|
||||
// if found_left.is_none() {
|
||||
// true
|
||||
// } else {
|
||||
// warn!(
|
||||
// "{}",
|
||||
// lformat!(
|
||||
// "ignored annotation {:?} as it \
|
||||
// wasn't compatible with the \
|
||||
// Markdown structure",
|
||||
// annotation
|
||||
// )
|
||||
// );
|
||||
// return None;
|
||||
// }
|
||||
// } else {
|
||||
// pos -= len;
|
||||
// false
|
||||
// }
|
||||
// } else {
|
||||
// false
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
// Moved out of the match 'thanks' to borrowcheck
|
||||
if recurse {
|
||||
if let Some(ref mut inner) = item.inner_mut() {
|
||||
if let Some(new_pos) = insert_annotation(inner, annotation, pos, length) {
|
||||
pos = new_pos;
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// // Moved out of the match 'thanks' to borrowcheck
|
||||
// if recurse {
|
||||
// if let Some(ref mut inner) = item.inner_mut() {
|
||||
// if let Some(new_pos) = insert_annotation(inner, annotation, pos, length) {
|
||||
// pos = new_pos;
|
||||
// } else {
|
||||
// return None;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
if let (Some((i, pos_left)), Some((j, pos_right))) = (found_left, found_right) {
|
||||
let pos_right = pos_right;
|
||||
let mut vec = vec![];
|
||||
// if let (Some((i, pos_left)), Some((j, pos_right))) = (found_left, found_right) {
|
||||
// let pos_right = pos_right;
|
||||
// let mut vec = vec![];
|
||||
|
||||
// Beginning token: keep the left part in the str, put the right one in our vec
|
||||
if !tokens[i].is_str() || pos_left == 0 {
|
||||
// do nothing
|
||||
} else {
|
||||
let old_token = mem::replace(&mut tokens[i], Token::Str(String::new()));
|
||||
if let Token::Str(old_str) = old_token {
|
||||
let mut chars_left: Vec<char> = old_str.chars().collect();
|
||||
let mut chars_right = chars_left.split_off(pos_left);
|
||||
// // Beginning token: keep the left part in the str, put the right one in our vec
|
||||
// if !tokens[i].is_str() || pos_left == 0 {
|
||||
// // do nothing
|
||||
// } else {
|
||||
// let old_token = mem::replace(&mut tokens[i], Token::Str(String::new()));
|
||||
// if let Token::Str(old_str) = old_token {
|
||||
// let mut chars_left: Vec<char> = old_str.chars().collect();
|
||||
// let mut chars_right = chars_left.split_off(pos_left);
|
||||
|
||||
let str_left: String = chars_left.into_iter().collect();
|
||||
tokens[i] = Token::Str(str_left);
|
||||
// let str_left: String = chars_left.into_iter().collect();
|
||||
// tokens[i] = Token::Str(str_left);
|
||||
|
||||
if i == j {
|
||||
// i and j are in same str, so split again
|
||||
if length != chars_right.len() {
|
||||
let inline_token = chars_right.split_off(length);
|
||||
let inline_token = Token::Str(inline_token.into_iter().collect());
|
||||
if pos_left == 0 {
|
||||
tokens.insert(i, inline_token)
|
||||
} else if i == tokens.len() {
|
||||
tokens.push(inline_token);
|
||||
} else {
|
||||
tokens.insert(i + 1, inline_token);
|
||||
}
|
||||
}
|
||||
let annot = Token::Annotation(
|
||||
annotation.clone(),
|
||||
vec![Token::Str(chars_right.into_iter().collect())],
|
||||
);
|
||||
if pos_left == 0 {
|
||||
tokens.insert(i, annot)
|
||||
} else if i == tokens.len() {
|
||||
tokens.push(annot);
|
||||
} else {
|
||||
tokens.insert(i + 1, annot);
|
||||
}
|
||||
return None;
|
||||
}
|
||||
// if i == j {
|
||||
// // i and j are in same str, so split again
|
||||
// if length != chars_right.len() {
|
||||
// let inline_token = chars_right.split_off(length);
|
||||
// let inline_token = Token::Str(inline_token.into_iter().collect());
|
||||
// if pos_left == 0 {
|
||||
// tokens.insert(i, inline_token)
|
||||
// } else if i == tokens.len() {
|
||||
// tokens.push(inline_token);
|
||||
// } else {
|
||||
// tokens.insert(i + 1, inline_token);
|
||||
// }
|
||||
// }
|
||||
// let annot = Token::Annotation(
|
||||
// annotation.clone(),
|
||||
// vec![Token::Str(chars_right.into_iter().collect())],
|
||||
// );
|
||||
// if pos_left == 0 {
|
||||
// tokens.insert(i, annot)
|
||||
// } else if i == tokens.len() {
|
||||
// tokens.push(annot);
|
||||
// } else {
|
||||
// tokens.insert(i + 1, annot);
|
||||
// }
|
||||
// return None;
|
||||
// }
|
||||
|
||||
let str_right: String = chars_right.into_iter().collect();
|
||||
vec.push(Token::Str(str_right));
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
// let str_right: String = chars_right.into_iter().collect();
|
||||
// vec.push(Token::Str(str_right));
|
||||
// } else {
|
||||
// unreachable!();
|
||||
// }
|
||||
// }
|
||||
|
||||
// Middle tokens: remove them entirely and put them in our vec
|
||||
for _ in i + 1..j {
|
||||
vec.push(tokens.remove(i + 1));
|
||||
}
|
||||
// // Middle tokens: remove them entirely and put them in our vec
|
||||
// for _ in i + 1..j {
|
||||
// vec.push(tokens.remove(i + 1));
|
||||
// }
|
||||
|
||||
// End token: keep the right part in the str, put the left one in our vec
|
||||
// j is now i + 1 because all tokens in between have been removed
|
||||
// unless j was equal to i to begin with
|
||||
let j = if i == j || i >= tokens.len() - 1 {
|
||||
i
|
||||
} else {
|
||||
i + 1
|
||||
};
|
||||
// // End token: keep the right part in the str, put the left one in our vec
|
||||
// // j is now i + 1 because all tokens in between have been removed
|
||||
// // unless j was equal to i to begin with
|
||||
// let j = if i == j || i >= tokens.len() - 1 {
|
||||
// i
|
||||
// } else {
|
||||
// i + 1
|
||||
// };
|
||||
|
||||
if !tokens[j].is_str() {
|
||||
// do nothing
|
||||
} else {
|
||||
let count = if let Token::Str(ref s) = tokens[j] {
|
||||
s.chars().count()
|
||||
} else {
|
||||
unreachable!()
|
||||
};
|
||||
if count != pos_right {
|
||||
let old_token = mem::replace(&mut tokens[j], Token::Rule);
|
||||
if let Token::Str(old_str) = old_token {
|
||||
let mut chars_left: Vec<char> = old_str.chars().collect();
|
||||
let chars_right = chars_left.split_off(pos_right);
|
||||
let str_left: String = chars_left.into_iter().collect();
|
||||
let str_right: String = chars_right.into_iter().collect();
|
||||
tokens[j] = Token::Str(str_right);
|
||||
// todo: if only one token, maybe concat the strings
|
||||
vec.push(Token::Str(str_left));
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
let new_token = Token::Annotation(annotation.clone(), vec);
|
||||
if pos_left == 0 {
|
||||
tokens.insert(i, new_token);
|
||||
} else if i >= tokens.len() - 1 {
|
||||
tokens.push(new_token);
|
||||
} else {
|
||||
tokens.insert(i + 1, new_token);
|
||||
}
|
||||
None
|
||||
} else if found_left.is_none() && found_right.is_none() {
|
||||
Some(pos)
|
||||
} else {
|
||||
warn!(
|
||||
"{}",
|
||||
lformat!(
|
||||
"ignored annotation {:?} as it wasn't compatible \
|
||||
with the Markdown structure",
|
||||
annotation
|
||||
)
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
// if !tokens[j].is_str() {
|
||||
// // do nothing
|
||||
// } else {
|
||||
// let count = if let Token::Str(ref s) = tokens[j] {
|
||||
// s.chars().count()
|
||||
// } else {
|
||||
// unreachable!()
|
||||
// };
|
||||
// if count != pos_right {
|
||||
// let old_token = mem::replace(&mut tokens[j], Token::Rule);
|
||||
// if let Token::Str(old_str) = old_token {
|
||||
// let mut chars_left: Vec<char> = old_str.chars().collect();
|
||||
// let chars_right = chars_left.split_off(pos_right);
|
||||
// let str_left: String = chars_left.into_iter().collect();
|
||||
// let str_right: String = chars_right.into_iter().collect();
|
||||
// tokens[j] = Token::Str(str_right);
|
||||
// // todo: if only one token, maybe concat the strings
|
||||
// vec.push(Token::Str(str_left));
|
||||
// } else {
|
||||
// unreachable!();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// let new_token = Token::Annotation(annotation.clone(), vec);
|
||||
// if pos_left == 0 {
|
||||
// tokens.insert(i, new_token);
|
||||
// } else if i >= tokens.len() - 1 {
|
||||
// tokens.push(new_token);
|
||||
// } else {
|
||||
// tokens.insert(i + 1, new_token);
|
||||
// }
|
||||
// None
|
||||
// } else if found_left.is_none() && found_right.is_none() {
|
||||
// Some(pos)
|
||||
// } else {
|
||||
// warn!(
|
||||
// "{}",
|
||||
// lformat!(
|
||||
// "ignored annotation {:?} as it wasn't compatible \
|
||||
// with the Markdown structure",
|
||||
// annotation
|
||||
// )
|
||||
// );
|
||||
// None
|
||||
// }
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn test_text_view() {
|
||||
|
|
Loading…
Reference in New Issue