fix: scan ahead panic
This commit is contained in:
parent
9fe5735127
commit
2cc9ed7445
3 changed files with 127 additions and 13 deletions
|
@ -323,7 +323,7 @@ hr.margin {
|
|||
}
|
||||
|
||||
span.img_sizer {
|
||||
display: block;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
p,
|
||||
|
|
|
@ -27,13 +27,29 @@ pub fn render_markdown(input: &str) -> String {
|
|||
.replace("</span>:temp_style", "</style>")
|
||||
}
|
||||
|
||||
pub(crate) fn is_numeric(value: &str) -> bool {
|
||||
let mut is_numeric = false;
|
||||
|
||||
for char in value.chars() {
|
||||
is_numeric = char.is_numeric();
|
||||
}
|
||||
|
||||
is_numeric
|
||||
}
|
||||
|
||||
pub(crate) fn slice(x: &str, range: core::ops::RangeFrom<usize>) -> String {
|
||||
(&x.chars().collect::<Vec<char>>()[range])
|
||||
.iter()
|
||||
.collect::<String>()
|
||||
}
|
||||
|
||||
fn parse_text_color_line(output: &mut String, buffer: &mut String, line: &str) {
|
||||
let mut in_color_buffer = false;
|
||||
let mut in_main_buffer = false;
|
||||
let mut color_buffer = String::new();
|
||||
let mut close_1 = false;
|
||||
|
||||
for char in line.chars() {
|
||||
for (i, char) in line.chars().enumerate() {
|
||||
if close_1 && char != '%' {
|
||||
// we expected to see another percentage to close the main buffer,
|
||||
// not getting that means this wasn't meant to be a color
|
||||
|
@ -60,7 +76,7 @@ fn parse_text_color_line(output: &mut String, buffer: &mut String, line: &str) {
|
|||
// by this point, we have: !
|
||||
// %color_buffer%main_buffer%%
|
||||
output.push_str(&format!(
|
||||
"<span style=\"color: {color_buffer}\">{buffer}</span>\n"
|
||||
"<span style=\"color: {color_buffer}\">{buffer}</span>"
|
||||
));
|
||||
|
||||
color_buffer.clear();
|
||||
|
@ -73,6 +89,13 @@ fn parse_text_color_line(output: &mut String, buffer: &mut String, line: &str) {
|
|||
}
|
||||
|
||||
// start
|
||||
// scan ahead
|
||||
let ahead = slice(line, i..);
|
||||
if !ahead.contains("%%") {
|
||||
// no closing sequence, we're done
|
||||
continue;
|
||||
}
|
||||
|
||||
// flush buffer
|
||||
output.push_str(&buffer);
|
||||
buffer.clear();
|
||||
|
@ -336,7 +359,17 @@ fn parse_image_size_line(output: &mut String, buffer: &mut String, line: &str) {
|
|||
if in_size && in_size_rhs {
|
||||
// end
|
||||
output.push_str(&format!(
|
||||
"<span style=\"width: {size_lhs}; height: {size_rhs}\" class=\"img_sizer\">![{buffer}</span>"
|
||||
"<span style=\"width: {}; height: {}\" class=\"img_sizer\">![{buffer}</span>",
|
||||
if is_numeric(&size_lhs) {
|
||||
format!("{size_lhs}px")
|
||||
} else {
|
||||
size_lhs
|
||||
},
|
||||
if is_numeric(&size_rhs) {
|
||||
format!("{size_rhs}px")
|
||||
} else {
|
||||
size_rhs
|
||||
}
|
||||
));
|
||||
|
||||
size_lhs = String::new();
|
||||
|
@ -487,8 +520,7 @@ fn parse_link_line(output: &mut String, buffer: &mut String, line: &str) {
|
|||
buffer.clear();
|
||||
|
||||
// scan for closing, otherwise quit
|
||||
let haystack = &line[i..];
|
||||
|
||||
let haystack = slice(line, i..);
|
||||
if !haystack.contains("]") {
|
||||
output.push('[');
|
||||
continue;
|
||||
|
|
96
src/model.rs
96
src/model.rs
|
@ -1,3 +1,4 @@
|
|||
use crate::markdown::is_numeric;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_valid::Validate;
|
||||
use std::fmt::Display;
|
||||
|
@ -259,12 +260,64 @@ pub struct EntryMetadata {
|
|||
#[serde(default, alias = "CONTAINER_SHADOW")]
|
||||
#[validate(max_length = 32)]
|
||||
pub container_shadow: String,
|
||||
/// If the container is a flexbox.
|
||||
#[serde(default, alias = "CONTAINER_FLEX")]
|
||||
pub container_flex: bool,
|
||||
/// The direction of the container's content (if container has flex enabled).
|
||||
#[serde(default, alias = "CONTAINER_FLEX_DIRECTION")]
|
||||
#[validate(max_length = 16)]
|
||||
pub container_flex_direction: String,
|
||||
/// The gap of the container's content (if container has flex enabled).
|
||||
///
|
||||
/// Syntax: <https://developer.mozilla.org/en-US/docs/Web/CSS/gap>
|
||||
#[serde(default, alias = "CONTAINER_FLEX_GAP")]
|
||||
#[validate(max_length = 16)]
|
||||
pub container_flex_gap: String,
|
||||
/// If the container's content wraps (if container has flex enabled).
|
||||
///
|
||||
/// Syntax: <https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap>
|
||||
#[serde(default, alias = "CONTAINER_FLEX_WRAP")]
|
||||
pub container_flex_wrap: bool,
|
||||
/// The alignment of the container's content horizontally (if container has flex enabled).
|
||||
///
|
||||
/// Swapped to vertical when direction is `column*`.
|
||||
///
|
||||
/// Syntax: <https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content>
|
||||
#[serde(default, alias = "CONTAINER_FLEX_ALIGN_HORIZONTAL")]
|
||||
#[validate(max_length = 16)]
|
||||
pub container_flex_align_horizontal: String,
|
||||
/// The alignment of the container's content vertically (if container has flex enabled).
|
||||
///
|
||||
/// Swapped to horizontal when direction is `column*`.
|
||||
///
|
||||
/// Syntax: <https://developer.mozilla.org/en-US/docs/Web/CSS/align-items>
|
||||
#[serde(default, alias = "CONTAINER_FLEX_ALIGN_VERTICAL")]
|
||||
#[validate(max_length = 16)]
|
||||
pub container_flex_align_vertical: String,
|
||||
/// The shadow under text.
|
||||
///
|
||||
/// Syntax: <https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow>
|
||||
#[serde(default, alias = "CONTENT_TEXT_SHADOW")]
|
||||
#[validate(max_length = 32)]
|
||||
pub content_text_shadow: String,
|
||||
/// The shadow under text.
|
||||
///
|
||||
/// Syntax: <https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow>
|
||||
#[serde(default, alias = "CONTENT_TEXT_SHADOW_COLOR")]
|
||||
#[validate(max_length = 32)]
|
||||
pub content_text_shadow_color: String,
|
||||
/// The shadow under text.
|
||||
///
|
||||
/// Syntax: <https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow>
|
||||
#[serde(default, alias = "CONTENT_TEXT_SHADOW_OFFSET")]
|
||||
#[validate(max_length = 32)]
|
||||
pub content_text_shadow_offset: String,
|
||||
/// The shadow under text.
|
||||
///
|
||||
/// Syntax: <https://developer.mozilla.org/en-US/docs/Web/CSS/text-shadow>
|
||||
#[serde(default, alias = "CONTENT_TEXT_SHADOW_BLUR")]
|
||||
#[validate(max_length = 32)]
|
||||
pub content_text_shadow_blur: String,
|
||||
/// The name of a font from Google Fonts to use.
|
||||
#[serde(default, alias = "CONTENT_FONT")]
|
||||
#[validate(max_length = 32)]
|
||||
|
@ -287,6 +340,9 @@ pub struct EntryMetadata {
|
|||
/// The color of links.
|
||||
#[serde(default, alias = "CONTENT_TEXT_LINK_COLOR")]
|
||||
pub content_text_link_color: String,
|
||||
/// If paragraph elements have a margin below them.
|
||||
#[serde(default, alias = "CONTENT_DISABLE_PARAGRAPH_MARGIN")]
|
||||
pub content_disable_paragraph_margin: bool,
|
||||
}
|
||||
|
||||
macro_rules! metadata_css {
|
||||
|
@ -446,6 +502,31 @@ impl EntryMetadata {
|
|||
));
|
||||
}
|
||||
|
||||
if !self.content_text_shadow_color.is_empty() {
|
||||
output.push_str(&format!(
|
||||
".container {{ text-shadow: {} {} {}; }}",
|
||||
self.content_text_shadow_offset,
|
||||
self.content_text_shadow_blur,
|
||||
self.content_text_shadow_color
|
||||
));
|
||||
}
|
||||
|
||||
if self.container_flex {
|
||||
output.push_str(".container { display: flex; }");
|
||||
metadata_css!(".container", "gap", self.container_flex_gap->output);
|
||||
metadata_css!(".container", "flex-direction", self.container_flex_direction->output);
|
||||
metadata_css!(".container", "align-items", self.container_flex_align_vertical->output);
|
||||
metadata_css!(".container", "justify-content", self.container_flex_align_horizontal->output);
|
||||
|
||||
if self.container_flex_wrap {
|
||||
output.push_str(".container { flex-wrap: wrap; }");
|
||||
}
|
||||
}
|
||||
|
||||
if self.content_disable_paragraph_margin {
|
||||
output.push_str(".container p { margin: 0; }");
|
||||
}
|
||||
|
||||
output + "</style>"
|
||||
}
|
||||
|
||||
|
@ -482,13 +563,14 @@ impl EntryMetadata {
|
|||
value = value.trim().to_string();
|
||||
|
||||
// determine if we need to stringify
|
||||
let mut is_numeric = false;
|
||||
|
||||
for char in value.chars() {
|
||||
is_numeric = char.is_numeric();
|
||||
}
|
||||
|
||||
if !is_numeric && !value.starts_with("[") && !value.starts_with("\"") {
|
||||
let is_numeric = is_numeric(&value);
|
||||
if !is_numeric
|
||||
&& !value.starts_with("[")
|
||||
&& !value.starts_with("\"")
|
||||
&& value != "true"
|
||||
&& value != "false"
|
||||
|| value.starts_with("#")
|
||||
{
|
||||
value = format!("\"{value}\"");
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue