Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add configuration parameters for tag names #31

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ members = [
]

[workspace.package]
version = "0.5.0"
version = "0.6.0-pre1"
authors = ["Kailan Blanks <kblanks@fastly.com>"]
license = "MIT"
edition = "2018"
51 changes: 46 additions & 5 deletions esi/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,21 @@
/// ## Usage Example
/// ```rust,no_run
/// let config = esi::Configuration::default()
/// .with_namespace("app");
/// .with_tag_names(esi::TagNames::from_namespace_with_defaults("app"));
/// ```
#[allow(clippy::return_self_not_must_use)]
#[derive(Clone, Debug)]
pub struct Configuration {
/// The XML namespace to use when scanning for ESI tags. Defaults to `esi`.
pub namespace: String,
// Define the tag names that the processor will operate on.
pub tag_names: TagNames,
/// For working with non-HTML ESI templates, e.g. JSON files, this option allows you to disable the unescaping of URLs
pub is_escaped_content: bool,
}

impl Default for Configuration {
fn default() -> Self {
Self {
namespace: String::from("esi"),
tag_names: Default::default(),
is_escaped_content: true,
}
}
Expand All @@ -27,8 +27,17 @@ impl Configuration {
/// Sets an alternative ESI namespace, which is used to identify ESI instructions.
///
/// For example, setting this to `test` would cause the processor to only match tags like `<test:include>`.
#[deprecated(
since = "0.6.0",
note = "This method is deprecated and will be removed in a future release. Use `with_tag_names(TagNames#from_namespace_with_defaults)` instead."
)]
pub fn with_namespace(mut self, namespace: impl Into<String>) -> Self {
self.namespace = namespace.into();
self.tag_names = TagNames::from_namespace_with_defaults(&namespace.into());
self
}
/// Sets the tag names that the processor will operate on.
pub fn with_tag_names(mut self, tag_names: TagNames) -> Self {
self.tag_names = tag_names;
self
}
/// For working with non-HTML ESI templates, eg JSON files, allows to disable URLs unescaping
Expand All @@ -37,3 +46,35 @@ impl Configuration {
self
}
}

/// Defines the HTML tag names that the processor will operate on.
#[derive(Clone, Debug)]
pub struct TagNames {
pub include: Vec<u8>,
pub comment: Vec<u8>,
pub remove: Vec<u8>,
pub r#try: Vec<u8>,
pub attempt: Vec<u8>,
pub except: Vec<u8>,
}

impl TagNames {
/// Returns tag names as defined within the ESI specification within the given namespace.
/// e.g. if `namespace` is `esi`, the tag names will be `esi:include`, `esi:comment`, etc.
pub fn from_namespace_with_defaults(namespace: &str) -> Self {
Self {
include: format!("{namespace}:include",).into_bytes(),
comment: format!("{namespace}:comment",).into_bytes(),
remove: format!("{namespace}:remove",).into_bytes(),
r#try: format!("{namespace}:try",).into_bytes(),
attempt: format!("{namespace}:attempt",).into_bytes(),
except: format!("{namespace}:except",).into_bytes(),
}
}
}

impl Default for TagNames {
fn default() -> Self {
Self::from_namespace_with_defaults("esi")
}
}
7 changes: 3 additions & 4 deletions esi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ use log::{debug, error, trace};
use std::collections::VecDeque;
use std::io::{BufRead, Write};

pub use crate::config::{Configuration, TagNames};
pub use crate::document::{Element, Fragment};
pub use crate::error::ExecutionError;
pub use crate::error::Result;
pub use crate::parse::{parse_tags, Event, Include, Tag, Tag::Try};

pub use crate::config::Configuration;
pub use crate::error::ExecutionError;

// re-export quick_xml Reader and Writer
pub use quick_xml::{Reader, Writer};

Expand Down Expand Up @@ -147,7 +146,7 @@ impl Processor {
// on each tag / event it finds in the document.
// The callback function `handle_events` will handle the event.
parse_tags(
&self.configuration.namespace,
&self.configuration.tag_names,
&mut src_document,
&mut |event| {
event_receiver(
Expand Down
30 changes: 3 additions & 27 deletions esi/src/parse.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{ExecutionError, Result};
use crate::{ExecutionError, Result, TagNames};
use log::debug;
use quick_xml::events::{BytesStart, Event as XmlEvent};
use quick_xml::name::QName;
Expand Down Expand Up @@ -43,28 +43,6 @@ pub enum Event<'e> {
ESI(Tag<'e>),
}

// #[derive(Debug)]
struct TagNames {
include: Vec<u8>,
comment: Vec<u8>,
remove: Vec<u8>,
r#try: Vec<u8>,
attempt: Vec<u8>,
except: Vec<u8>,
}
impl TagNames {
fn init(namespace: &str) -> Self {
Self {
include: format!("{namespace}:include",).into_bytes(),
comment: format!("{namespace}:comment",).into_bytes(),
remove: format!("{namespace}:remove",).into_bytes(),
r#try: format!("{namespace}:try",).into_bytes(),
attempt: format!("{namespace}:attempt",).into_bytes(),
except: format!("{namespace}:except",).into_bytes(),
}
}
}

fn do_parse<'a, R>(
reader: &mut Reader<R>,
callback: &mut dyn FnMut(Event<'a>) -> Result<()>,
Expand Down Expand Up @@ -185,7 +163,7 @@ where

/// Parses the ESI document from the given `reader` and calls the `callback` closure upon each successfully parsed ESI tag.
pub fn parse_tags<'a, R>(
namespace: &str,
tag_names: &TagNames,
reader: &mut Reader<R>,
callback: &mut dyn FnMut(Event<'a>) -> Result<()>,
) -> Result<()>
Expand All @@ -194,8 +172,6 @@ where
{
debug!("Parsing document...");

// Initialize the ESI tags
let tags = TagNames::init(namespace);
// set the initial depth of nested tags
let mut depth = 0;
let mut root = Vec::new();
Expand All @@ -208,7 +184,7 @@ where
&mut root,
&mut depth,
&mut current_arm,
&tags,
tag_names,
)?;
debug!("Root: {:?}", root);

Expand Down
Loading
Loading