Skip to content

Commit

Permalink
Fixed svg and html tags
Browse files Browse the repository at this point in the history
  • Loading branch information
nricciardi committed Jul 9, 2024
1 parent 148eae3 commit abca1cd
Show file tree
Hide file tree
Showing 17 changed files with 312 additions and 134 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ clap = "4.4.18"
env_logger = "0.10.1"
getset = "0.1.2"
image = "0.24.8"
infer = "0.16.0"
log = "0.4.20"
notify = "6.1.1"
once_cell = "1.19.0"
Expand Down
2 changes: 0 additions & 2 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,7 @@ impl NmdCli {
.help("compile only a documents subset")
.action(ArgAction::Append)
)

)

)
.subcommand(
Command::new("generate")
Expand Down
12 changes: 10 additions & 2 deletions src/compiler/assembler/html_assembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,9 @@ impl Assembler for HtmlAssembler {
div_chapter = div_chapter.with_attributes(vec![("class", tag.value().as_ref().unwrap().as_str())])
},

_ => ()
_ => {
log::warn!("chapter tag key not supported yet")
}
}
}

Expand All @@ -275,7 +277,13 @@ impl Assembler for HtmlAssembler {
for paragraph in chapter.paragraphs() {
if let Some(parsed_content) = paragraph.parsed_content().as_ref() {

div_chapter_content.push_str(&parsed_content.parsed_content());
let parsed_content = parsed_content.parsed_content();

if parsed_content.is_empty() {
continue;
}

div_chapter_content.push_str(&parsed_content);

} else {
return Err(AssemblerError::ParsedContentNotFound)
Expand Down
60 changes: 31 additions & 29 deletions src/compiler/codex.rs

Large diffs are not rendered by default.

3 changes: 1 addition & 2 deletions src/compiler/codex/modifier/standard_text_modifier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use super::{base_modifier::BaseModifier, constants::NEW_LINE, modifiers_bucket::

#[derive(Debug, PartialEq, Clone)]
pub enum StandardTextModifier {

// CONTENT MODIFIERs

BoldStarVersion,
BoldUnderscoreVersion,
ItalicStarVersion,
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/dossier/document/chapter/paragraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ impl Parsable for Paragraph {

let parsing_outcome = Parser::parse_paragraph(&codex, self, Arc::clone(&parsing_configuration), parsing_configuration_overlay)?;

log::debug!("end to parse paragraph:\n{:#?}", parsing_outcome);

self.parsed_content = Some(parsing_outcome);

Ok(())
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,11 @@ impl Loader {
return
}

if matched_str.is_empty() {
log::debug!("paragraph discarded because empty");
return;
}

let paragraph = Paragraph::new(matched_str, paragraph_modifier.identifier().clone());

if !paragraph.contains_only_newlines() {
Expand Down
5 changes: 4 additions & 1 deletion src/compiler/parsing/parsing_error.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use thiserror::Error;

use crate::resource::resource_reference::ResourceReferenceError;
use crate::resource::{resource_reference::ResourceReferenceError, ResourceError};

#[derive(Error, Debug)]
pub enum ParsingError {
Expand All @@ -19,6 +19,9 @@ pub enum ParsingError {
#[error(transparent)]
ReferenceError(#[from] ResourceReferenceError),

#[error(transparent)]
ResourceError(#[from] ResourceError),

#[error("unknown error occurs")]
Unknown,
}
8 changes: 7 additions & 1 deletion src/compiler/parsing/parsing_rule/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@ use crate::compiler::codex::modifier::constants::NEW_LINE;
pub static DOUBLE_NEW_LINE_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(&format!("{}{{2}}", NEW_LINE)).unwrap());


pub const SPACE_TAB_EQUIVALENCE: &str = r" ";
pub const SPACE_TAB_EQUIVALENCE: &str = r" ";

pub static ESCAPE_HTML: Lazy<Vec<(Regex, String)>> = Lazy::new(|| vec![
(Regex::new(r"&").unwrap(), "&amp;".to_string()),
(Regex::new(r"<").unwrap(), "&lt;".to_string()),
(Regex::new(r">").unwrap(), "&gt;".to_string()),
]);
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use std::sync::{Arc, RwLock};
use once_cell::sync::Lazy;
use regex::Regex;

use crate::compiler::{codex::{modifier::{constants::NEW_LINE, modifiers_bucket::ModifiersBucket, standard_paragraph_modifier::StandardParagraphModifier, Modifier}, Codex}, parsing::{parsing_configuration::ParsingConfiguration, parsing_error::ParsingError, parsing_outcome::{ParsingOutcome, ParsingOutcomePart}}};
use crate::{compiler::{codex::{modifier::{constants::NEW_LINE, modifiers_bucket::ModifiersBucket, standard_paragraph_modifier::StandardParagraphModifier, Modifier}, Codex}, parsing::{parsing_configuration::ParsingConfiguration, parsing_error::ParsingError, parsing_outcome::{ParsingOutcome, ParsingOutcomePart}}}, utility::text_utility};

use super::{constants::DOUBLE_NEW_LINE_REGEX, ParsingRule};
use super::{constants::{DOUBLE_NEW_LINE_REGEX, ESCAPE_HTML}, ParsingRule};

static CHECK_EXTENDED_BLOCK_QUOTE_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(r"(?:^(?m:^> \[!(.*)\]))").unwrap());

Expand Down Expand Up @@ -74,7 +74,7 @@ impl ParsingRule for HtmlExtendedBlockQuoteRule {
<div class="focus-quote-block focus-quote-block-{}">
<div class="focus-quote-block-title focus-quote-block-{}-title"></div>
<div class="focus-quote-block-description focus-quote-block-{}-description">"#, quote_type, quote_type, quote_type) },
ParsingOutcomePart::Mutable { content: tag_body },
ParsingOutcomePart::Mutable { content: text_utility::replace(&tag_body, &ESCAPE_HTML) },
ParsingOutcomePart::Fixed { content: String::from("</div></div>") }
]);

Expand Down
120 changes: 66 additions & 54 deletions src/compiler/parsing/parsing_rule/html_image_rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ use crate::compiler::parser::Parser;
use crate::compiler::parsing::parsing_configuration::ParsingConfiguration;
use crate::compiler::parsing::parsing_error::ParsingError;
use crate::compiler::parsing::parsing_outcome::ParsingOutcome;
use crate::compiler::parsing::parsing_rule::constants::ESCAPE_HTML;
use crate::resource::resource_reference::ResourceReference;
use crate::resource::{image_resource::ImageResource, remote_resource::RemoteResource};
use crate::utility::text_utility;

use super::ParsingRule;

Expand Down Expand Up @@ -74,7 +76,7 @@ impl HtmlImageRule {
panic!("unsupported image modifier identifier");
}

fn create_figure_img(src: &str, alt: Option<&str>, caption: Option<&str>, id: Option<ResourceReference>, img_classes: Vec<&str>, style: Option<String>) -> String {
fn build_html_img(src: &str, alt: Option<&String>, caption: Option<&String>, id: Option<ResourceReference>, img_classes: Vec<&str>, style: Option<String>) -> String {

let id_attr: String;

Expand All @@ -94,7 +96,7 @@ impl HtmlImageRule {
}

if let Some(c) = caption {
html_caption = format!(r#"<figcaption class="image-caption">{}</figcaption>"#, c);
html_caption = format!(r#"<figcaption class="image-caption">{}</figcaption>"#, text_utility::replace(c, &ESCAPE_HTML));
} else {
html_caption = String::new();
}
Expand All @@ -113,86 +115,80 @@ impl HtmlImageRule {
</figure>"#, id_attr, src, html_alt, img_classes.join(" "), style_attr, html_caption)
}

fn build_img(src: &str, alt: Option<&str>, caption: Option<&str>, id: Option<ResourceReference>, img_classes: Vec<&str>, figure_style: Option<String>, parsing_configuration: &RwLockReadGuard<ParsingConfiguration>) -> String {
fn build_not_embed_remote_img(image: &mut ImageResource, id: Option<ResourceReference>, img_classes: Vec<&str>, figure_style: Option<String>, parsing_configuration: &RwLockReadGuard<ParsingConfiguration>) -> Result<String, ParsingError> {
let src = Url::parse(image.src().to_str().unwrap()).unwrap();

if RemoteResource::is_valid_remote_resource(src) { // remote image (e.g. URL)

if parsing_configuration.embed_remote_image() {

todo!()
return Ok(Self::build_html_img(&image.src().to_string_lossy().to_string(), image.label().as_ref(), image.caption().as_ref(), id, img_classes, figure_style))
}

} else {
let src = Url::parse(src).unwrap();
fn build_embed_remote_img(image: &mut ImageResource, id: Option<ResourceReference>, img_classes: Vec<&str>, figure_style: Option<String>, parsing_configuration: &RwLockReadGuard<ParsingConfiguration>) -> Result<String, ParsingError> {
todo!()
}

return Self::create_figure_img(src.as_str(), alt, caption, id, img_classes, figure_style)
}
fn build_embed_local_img(image: &mut ImageResource, id: Option<ResourceReference>, img_classes: Vec<&str>, figure_style: Option<String>, parsing_configuration: &RwLockReadGuard<ParsingConfiguration>) -> Result<String, ParsingError> {
let base64_image = image.to_base64(parsing_configuration.compress_embed_image());

} else { // local image
if let Some(mt) = image.mime_type().as_ref() {

let create_local_not_embed_figure_img = |src: PathBuf| {
let local_not_embed_src = fs::canonicalize(src).unwrap();
return Ok(Self::build_html_img(&format!("data:{};base64,{}", mt, base64_image.unwrap()), image.label().as_ref(), image.caption().as_ref(), id, img_classes, figure_style));

return Self::create_figure_img(local_not_embed_src.to_str().unwrap(), alt, caption, id.clone(), img_classes.clone(), figure_style.clone());
};
} else {
if parsing_configuration.strict_image_src_check() {

let mut src_path_buf = PathBuf::from(src);
return Err(ParsingError::ResourceError(crate::resource::ResourceError::InvalidResourceVerbose(format!("image {:?} mime type not found", image.src()))));

if src_path_buf.is_relative() {
} else {

let image_file_name = src;
log::warn!("{:?} will be parse as local NOT embed image due to an error", image.src());

src_path_buf = parsing_configuration.input_location().clone().join(image_file_name);
return Ok(Self::build_not_embed_local_img(image, id, img_classes, figure_style, parsing_configuration).unwrap());
}
}
}

if !src_path_buf.exists() {
fn build_not_embed_local_img(image: &mut ImageResource, id: Option<ResourceReference>, img_classes: Vec<&str>, figure_style: Option<String>, parsing_configuration: &RwLockReadGuard<ParsingConfiguration>) -> Result<String, ParsingError> {
let local_not_embed_src = fs::canonicalize(image.src()).unwrap();

log::debug!("'{}' not found, try adding images directory path", src_path_buf.to_string_lossy());
return Ok(Self::build_html_img(&local_not_embed_src.to_string_lossy().to_string(), image.label().as_ref(), image.caption().as_ref(), id.clone(), img_classes.clone(), figure_style.clone()));
}

src_path_buf = parsing_configuration.input_location().clone().join(dossier::ASSETS_DIR).join(dossier::IMAGES_DIR).join(image_file_name);
}
}

if src_path_buf.exists() {
fn build_img_from_parsing_configuration(image: &mut ImageResource, id: Option<ResourceReference>, img_classes: Vec<&str>, figure_style: Option<String>, parsing_configuration: &RwLockReadGuard<ParsingConfiguration>) -> Result<String, ParsingError> {

if parsing_configuration.embed_local_image() {
if RemoteResource::is_valid_remote_resource(image.src().to_str().unwrap()) { // remote image (e.g. URL)

let image_res = ImageResource::try_from(src_path_buf.clone());
if parsing_configuration.embed_remote_image() {

if let Ok(image) = image_res {

let base64_image = image.to_base64(parsing_configuration.compress_embed_image());

return Self::create_figure_img(format!("data:image/png;base64,{}", base64_image.unwrap()).as_str(), alt, caption, id, img_classes, figure_style);


} else {
if parsing_configuration.strict_image_src_check() {
return Self::build_embed_remote_img(image, id, img_classes, figure_style, parsing_configuration);

image_res.err().unwrap();
unreachable!()
} else {

return Self::build_not_embed_remote_img(image, id, img_classes, figure_style, parsing_configuration);
}

} else {
} else { // local image

log::warn!("{:?} will be parse as local not embed image due to an error", src_path_buf);
if image.src().exists() {

return create_local_not_embed_figure_img(src_path_buf);
}
}
if parsing_configuration.embed_local_image() {

return Self::build_embed_local_img(image, id, img_classes, figure_style, parsing_configuration);

} else { // local not embed
return create_local_not_embed_figure_img(src_path_buf);

return Ok(Self::build_not_embed_local_img(image, id, img_classes, figure_style, parsing_configuration).unwrap());
}


} else if parsing_configuration.strict_image_src_check() {

log::error!("{}", ParsingError::InvalidSource(String::from(src)));
log::error!("{}", ParsingError::InvalidSource(String::from(image.src().to_string_lossy().to_string())));

panic!("invalid src")

} else {
return Self::create_figure_img(src, alt, caption, id, img_classes, figure_style) // create image tag of invalid image instead of panic

return Ok(Self::build_html_img(&image.src().to_string_lossy().to_string(), image.label().as_ref(), image.caption().as_ref(), id, img_classes, figure_style)) // create image tag of invalid image instead of panic
}

}
Expand Down Expand Up @@ -227,12 +223,23 @@ impl HtmlImageRule {
if let Some(id) = captures.get(2) {
let id = ResourceReference::of_internal_from_without_sharp(id.as_str(), Some(document_name)).unwrap();

return Self::build_img(src.as_str(), Some(label.as_str()), Some(&parsed_label.parsed_content()), Some(id), vec!["image"], style, &parsing_configuration);
let mut image: ImageResource = ImageResource::new(PathBuf::from(src.as_str()), Some(parsed_label.parsed_content()), Some(label.as_str().to_string()))
.elaborating_relative_path(parsing_configuration.input_location())
.inferring_mime_type()
.unwrap();

return Self::build_img_from_parsing_configuration(&mut image, Some(id), vec!["image"], style, &parsing_configuration).unwrap();

} else {

let id = ResourceReference::of(label.as_str(), Some(document_name)).unwrap();

return Self::build_img(src.as_str(), Some(label.as_str()), Some(&parsed_label.parsed_content()), Some(id), vec!["image"], style, &parsing_configuration);
let mut image: ImageResource = ImageResource::new(PathBuf::from(src.as_str()), Some(parsed_label.parsed_content()), Some(label.as_str().to_string()))
.elaborating_relative_path(parsing_configuration.input_location())
.inferring_mime_type()
.unwrap();

return Self::build_img_from_parsing_configuration(&mut image, Some(id), vec!["image"], style, &parsing_configuration).unwrap();

}
}
Expand All @@ -245,7 +252,7 @@ impl HtmlImageRule {
Ok(ParsingOutcome::new_fixed(parsed_content))
}

fn parse_abridged_image(search_pattern_regex: &Regex, content: &str, codex: &Codex, parsing_configuration: Arc<RwLock<ParsingConfiguration>>) -> Result<ParsingOutcome, ParsingError> {
fn parse_abridged_image(search_pattern_regex: &Regex, content: &str, _codex: &Codex, parsing_configuration: Arc<RwLock<ParsingConfiguration>>) -> Result<ParsingOutcome, ParsingError> {

let parsing_configuration = parsing_configuration.read().unwrap();

Expand Down Expand Up @@ -275,7 +282,12 @@ impl HtmlImageRule {
style = None;
}

return Self::build_img(src.as_str(), None, None, id, vec!["image", "abridged-image"], style, &parsing_configuration);
let mut image = ImageResource::new(PathBuf::from(src.as_str()), None, None)
.elaborating_relative_path(parsing_configuration.input_location())
.inferring_mime_type()
.unwrap();

return Self::build_img_from_parsing_configuration(&mut image, id, vec!["image", "abridged-image"], style, &parsing_configuration).unwrap();

}).to_string();

Expand Down Expand Up @@ -376,7 +388,7 @@ impl ParsingRule for HtmlImageRule {
Self::parse_image_from_identifier(&self.image_modifier_identifier, &self.search_pattern_regex, content, codex, Arc::clone(&parsing_configuration))
}

fn fast_parse(&self, content: &str, codex: &Codex, parsing_configuration: Arc<RwLock<ParsingConfiguration>>) -> Result<ParsingOutcome, ParsingError> {
fn fast_parse(&self, content: &str, _codex: &Codex, _parsing_configuration: Arc<RwLock<ParsingConfiguration>>) -> Result<ParsingOutcome, ParsingError> {
Ok(ParsingOutcome::new_fixed(format!(r#"<img alt="{}" />"#, content)))
}

Expand Down
8 changes: 5 additions & 3 deletions src/compiler/parsing/parsing_rule/html_list_rule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ use std::sync::{Arc, RwLock};
use once_cell::sync::Lazy;
use regex::Regex;

use crate::compiler::{codex::{modifier::standard_paragraph_modifier::StandardParagraphModifier, Codex}, parsing::{parsing_configuration::{list_bullet_configuration_record::{self, ListBulletConfigurationRecord}, ParsingConfiguration}, parsing_error::ParsingError, parsing_metadata::ParsingMetadata, parsing_outcome::ParsingOutcome}};
use crate::{compiler::{codex::{modifier::standard_paragraph_modifier::StandardParagraphModifier, Codex}, parsing::{parsing_configuration::{list_bullet_configuration_record::{self, ListBulletConfigurationRecord}, ParsingConfiguration}, parsing_error::ParsingError, parsing_metadata::ParsingMetadata, parsing_outcome::ParsingOutcome}}, utility::text_utility};

use super::{constants::SPACE_TAB_EQUIVALENCE, ParsingRule};
use super::{constants::{ESCAPE_HTML, SPACE_TAB_EQUIVALENCE}, ParsingRule};

static SEARCH_LIST_ITEM_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(&StandardParagraphModifier::ListItem.modifier_pattern()).unwrap());

Expand Down Expand Up @@ -100,12 +100,14 @@ impl ParsingRule for HtmlListRule {

let bullet = Self::bullet_transform(bullet, indentation_level, parsing_configuration.read().unwrap().list_bullets_configuration());

let content = text_utility::replace(&content, &ESCAPE_HTML);

parsing_outcome.add_fixed_part(r#"<li class="list-item">"#.to_string());
parsing_outcome.add_fixed_part(LIST_ITEM_INDENTATION.repeat(indentation_level));
parsing_outcome.add_fixed_part(r#"<span class="list-item-bullet">"#.to_string());
parsing_outcome.add_fixed_part(bullet);
parsing_outcome.add_fixed_part(r#"</span><span class="list-item-content">"#.to_string());
parsing_outcome.add_mutable_part(content.to_string());
parsing_outcome.add_mutable_part(content);
parsing_outcome.add_fixed_part(r#"</span></li>"#.to_string());

}
Expand Down
Loading

0 comments on commit abca1cd

Please sign in to comment.