From 70403bcc630771523c6272ee5498ad877a7886a0 Mon Sep 17 00:00:00 2001 From: Tropical <42101043+Tropix126@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:36:24 -0400 Subject: [PATCH 01/36] refactor: organize inconsistent attributes (#950) * organize inconsistent attributes * remove some nonsensical attributes * adjust some attributes that I misunderstood --------- Co-authored-by: Marc Espin --- crates/elements/src/definitions.rs | 242 +++++++++++++++++++++-------- 1 file changed, 174 insertions(+), 68 deletions(-) diff --git a/crates/elements/src/definitions.rs b/crates/elements/src/definitions.rs index abeb5c600..a0a92abb7 100644 --- a/crates/elements/src/definitions.rs +++ b/crates/elements/src/definitions.rs @@ -172,8 +172,7 @@ builder_constructors! { /// } /// ``` rect { - #[doc = include_str!("_docs/attributes/padding.md")] - padding: String, + // Layout #[doc = include_str!("_docs/attributes/width_height.md")] height: String, width: String, @@ -183,17 +182,45 @@ builder_constructors! { #[doc = include_str!("_docs/attributes/max_width_max_height.md")] max_height: String, max_width: String, + #[doc = include_str!("_docs/attributes/margin.md")] + margin: String, + #[doc = include_str!("_docs/attributes/padding.md")] + padding: String, + #[doc = include_str!("_docs/attributes/position.md")] + position: String, + position_top: String, + position_right: String, + position_bottom: String, + position_left: String, + layer: String, + + // Children layout + #[doc = include_str!("_docs/attributes/direction.md")] + direction: String, + #[doc = include_str!("_docs/attributes/content.md")] + content: String, + #[doc = include_str!("_docs/attributes/main_align_cross_align.md")] + main_align: String, + cross_align: String, + #[doc = include_str!("_docs/attributes/spacing.md")] + spacing: String, + #[doc = include_str!("_docs/attributes/overflow.md")] + overflow: String, + offset_x: String, + offset_y: String, + + // Style #[doc = include_str!("_docs/attributes/background.md")] background: String, #[doc = include_str!("_docs/attributes/border.md")] border: String, - #[doc = include_str!("_docs/attributes/direction.md")] - direction: String, #[doc = include_str!("_docs/attributes/shadow.md")] shadow: String, #[doc = include_str!("_docs/attributes/corner.md")] corner_radius: String, corner_smoothing: String, + + // Font style #[doc = include_str!("_docs/attributes/color.md")] color: String, #[doc = include_str!("_docs/attributes/font_size.md")] @@ -206,39 +233,39 @@ builder_constructors! { font_weight: String, #[doc = include_str!("_docs/attributes/font_width.md")] font_width: String, - #[doc = include_str!("_docs/attributes/main_align_cross_align.md")] - main_align: String, - cross_align: String, #[doc = include_str!("_docs/attributes/text_align.md")] text_align: String, + #[doc = include_str!("_docs/attributes/line_height.md")] + line_height: String, + #[doc = include_str!("_docs/attributes/text_shadow.md")] + text_shadow: String, + #[doc = include_str!("_docs/attributes/max_lines.md")] + max_lines: String, + #[doc = include_str!("_docs/attributes/decoration.md")] + decoration: String, + #[doc = include_str!("_docs/attributes/decoration_style.md")] + decoration_style: String, + #[doc = include_str!("_docs/attributes/decoration_color.md")] + decoration_color: String, + #[doc = include_str!("_docs/attributes/text_overflow.md")] + text_overflow: String, + #[doc = include_str!("_docs/attributes/letter_spacing.md")] + letter_spacing: String, + #[doc = include_str!("_docs/attributes/word_spacing.md")] + word_spacing: String, + + // Transform #[doc = include_str!("_docs/attributes/rotate.md")] rotate: String, - #[doc = include_str!("_docs/attributes/overflow.md")] - overflow: String, - #[doc = include_str!("_docs/attributes/margin.md")] - margin: String, - #[doc = include_str!("_docs/attributes/position.md")] - position: String, - position_top: String, - position_right: String, - position_bottom: String, - position_left: String, #[doc = include_str!("_docs/attributes/opacity.md")] opacity: String, - #[doc = include_str!("_docs/attributes/content.md")] - content: String, - #[doc = include_str!("_docs/attributes/line_height.md")] - line_height: String, - #[doc = include_str!("_docs/attributes/spacing.md")] - spacing: String, + // Reference canvas_reference: String, - layer: String, - offset_y: String, - offset_x: String, reference: Reference, cursor_reference: CursorReference, + // Accessibility a11y_id: String, a11y_focusable: String, a11y_auto_focus: String, @@ -323,15 +350,33 @@ builder_constructors! { /// } /// ``` label { - #[doc = include_str!("_docs/attributes/color.md")] - color: String, - #[doc = include_str!("_docs/attributes/text_shadow.md")] - text_shadow: String, + // Layout #[doc = include_str!("_docs/attributes/width_height.md")] height: String, width: String, + #[doc = include_str!("_docs/attributes/min_width_min_height.md")] + min_height: String, + min_width: String, + #[doc = include_str!("_docs/attributes/max_width_max_height.md")] + max_height: String, + max_width: String, + #[doc = include_str!("_docs/attributes/margin.md")] + margin: String, + #[doc = include_str!("_docs/attributes/position.md")] + position: String, + position_top: String, + position_right: String, + position_bottom: String, + position_left: String, + layer: String, + + // Children layout #[doc = include_str!("_docs/attributes/main_align_cross_align.md")] main_align: String, + + // Font style + #[doc = include_str!("_docs/attributes/color.md")] + color: String, #[doc = include_str!("_docs/attributes/font_size.md")] font_size: String, #[doc = include_str!("_docs/attributes/font_family.md")] @@ -344,16 +389,12 @@ builder_constructors! { font_width: String, #[doc = include_str!("_docs/attributes/text_align.md")] text_align: String, - #[doc = include_str!("_docs/attributes/max_lines.md")] - max_lines: String, - #[doc = include_str!("_docs/attributes/rotate.md")] - rotate: String, #[doc = include_str!("_docs/attributes/line_height.md")] line_height: String, - #[doc = include_str!("_docs/attributes/letter_spacing.md")] - letter_spacing: String, - #[doc = include_str!("_docs/attributes/word_spacing.md")] - word_spacing: String, + #[doc = include_str!("_docs/attributes/text_shadow.md")] + text_shadow: String, + #[doc = include_str!("_docs/attributes/max_lines.md")] + max_lines: String, #[doc = include_str!("_docs/attributes/decoration.md")] decoration: String, #[doc = include_str!("_docs/attributes/decoration_style.md")] @@ -362,13 +403,18 @@ builder_constructors! { decoration_color: String, #[doc = include_str!("_docs/attributes/text_overflow.md")] text_overflow: String, - #[doc = include_str!("_docs/attributes/margin.md")] - margin: String, + #[doc = include_str!("_docs/attributes/letter_spacing.md")] + letter_spacing: String, + #[doc = include_str!("_docs/attributes/word_spacing.md")] + word_spacing: String, + + // Transform + #[doc = include_str!("_docs/attributes/rotate.md")] + rotate: String, #[doc = include_str!("_docs/attributes/opacity.md")] opacity: String, - layer: String, - + // Accessibility a11y_id: String, a11y_auto_focus: String, a11y_focusable: String, @@ -460,6 +506,7 @@ builder_constructors! { /// } /// ``` paragraph { + // Layout #[doc = include_str!("_docs/attributes/width_height.md")] height: String, width: String, @@ -469,12 +516,23 @@ builder_constructors! { #[doc = include_str!("_docs/attributes/max_width_max_height.md")] max_height: String, max_width: String, + #[doc = include_str!("_docs/attributes/margin.md")] + margin: String, + #[doc = include_str!("_docs/attributes/position.md")] + position: String, + position_top: String, + position_right: String, + position_bottom: String, + position_left: String, + layer: String, + + // Children layout #[doc = include_str!("_docs/attributes/main_align_cross_align.md")] main_align: String, - #[doc = include_str!("_docs/attributes/text_align.md")] - text_align: String, - #[doc = include_str!("_docs/attributes/rotate.md")] - rotate: String, + + // Font style + #[doc = include_str!("_docs/attributes/color.md")] + color: String, #[doc = include_str!("_docs/attributes/font_size.md")] font_size: String, #[doc = include_str!("_docs/attributes/font_family.md")] @@ -485,36 +543,43 @@ builder_constructors! { font_weight: String, #[doc = include_str!("_docs/attributes/font_width.md")] font_width: String, + #[doc = include_str!("_docs/attributes/text_align.md")] + text_align: String, #[doc = include_str!("_docs/attributes/line_height.md")] line_height: String, - #[doc = include_str!("_docs/attributes/letter_spacing.md")] - letter_spacing: String, - #[doc = include_str!("_docs/attributes/word_spacing.md")] - word_spacing: String, + #[doc = include_str!("_docs/attributes/text_shadow.md")] + text_shadow: String, + #[doc = include_str!("_docs/attributes/max_lines.md")] + max_lines: String, #[doc = include_str!("_docs/attributes/decoration.md")] decoration: String, #[doc = include_str!("_docs/attributes/decoration_style.md")] decoration_style: String, #[doc = include_str!("_docs/attributes/decoration_color.md")] + decoration_color: String, + #[doc = include_str!("_docs/attributes/text_overflow.md")] text_overflow: String, - #[doc = include_str!("_docs/attributes/overflow.md")] - overflow: String, - #[doc = include_str!("_docs/attributes/margin.md")] - margin: String, + #[doc = include_str!("_docs/attributes/letter_spacing.md")] + letter_spacing: String, + #[doc = include_str!("_docs/attributes/word_spacing.md")] + word_spacing: String, + + // Transform + #[doc = include_str!("_docs/attributes/rotate.md")] + rotate: String, #[doc = include_str!("_docs/attributes/opacity.md")] opacity: String, - layer: String, + // Text Editing cursor_index: String, - max_lines: String, cursor_color: String, cursor_mode: String, cursor_id: String, - highlights: String, highlight_color: String, highlight_mode: String, + // Accessibility a11y_id: String, a11y_focusable: String, a11y_auto_focus: String, @@ -586,11 +651,10 @@ builder_constructors! { }; /// `text` element is simply a text span used for the `paragraph` element. text { + // Font style #[doc = include_str!("_docs/attributes/color.md")] color: String, #[doc = include_str!("_docs/attributes/font_size.md")] - text_shadow: String, - #[doc = include_str!("_docs/attributes/font_size.md")] font_size: String, #[doc = include_str!("_docs/attributes/font_family.md")] font_family: String, @@ -600,18 +664,22 @@ builder_constructors! { font_weight: String, #[doc = include_str!("_docs/attributes/font_width.md")] font_width: String, + #[doc = include_str!("_docs/attributes/text_align.md")] + text_align: String, #[doc = include_str!("_docs/attributes/line_height.md")] line_height: String, - #[doc = include_str!("_docs/attributes/letter_spacing.md")] - letter_spacing: String, - #[doc = include_str!("_docs/attributes/word_spacing.md")] - word_spacing: String, + #[doc = include_str!("_docs/attributes/text_shadow.md")] + text_shadow: String, #[doc = include_str!("_docs/attributes/decoration.md")] decoration: String, #[doc = include_str!("_docs/attributes/decoration_style.md")] decoration_style: String, #[doc = include_str!("_docs/attributes/decoration_color.md")] decoration_color: String, + #[doc = include_str!("_docs/attributes/letter_spacing.md")] + letter_spacing: String, + #[doc = include_str!("_docs/attributes/word_spacing.md")] + word_spacing: String, }; /// `image` element let's you show an image. /// @@ -633,20 +701,40 @@ builder_constructors! { /// } /// ``` image { - #[doc = include_str!("_docs/attributes/width_height.md")] + // Layout + #[doc = include_str!("_docs/attributes/width_height.md")] height: String, width: String, + #[doc = include_str!("_docs/attributes/min_width_min_height.md")] + min_height: String, + min_width: String, + #[doc = include_str!("_docs/attributes/max_width_max_height.md")] + max_height: String, + max_width: String, + #[doc = include_str!("_docs/attributes/margin.md")] + margin: String, + #[doc = include_str!("_docs/attributes/position.md")] + position: String, + position_top: String, + position_right: String, + position_bottom: String, + position_left: String, + layer: String, + + // Transform #[doc = include_str!("_docs/attributes/rotate.md")] rotate: String, #[doc = include_str!("_docs/attributes/opacity.md")] opacity: String, + // Image image_data: String, image_reference: String, + // Accessibility a11y_id: String, - a11y_auto_focus: String, a11y_focusable: String, + a11y_auto_focus: String, a11y_name: String, a11y_description: String, a11y_value: String, @@ -734,19 +822,37 @@ builder_constructors! { /// } /// ``` svg { - #[doc = include_str!("_docs/attributes/margin.md")] - margin: String, - #[doc = include_str!("_docs/attributes/width_height.md")] + // Layout + #[doc = include_str!("_docs/attributes/width_height.md")] height: String, width: String, + #[doc = include_str!("_docs/attributes/min_width_min_height.md")] + min_height: String, + min_width: String, + #[doc = include_str!("_docs/attributes/max_width_max_height.md")] + max_height: String, + max_width: String, + #[doc = include_str!("_docs/attributes/margin.md")] + margin: String, + #[doc = include_str!("_docs/attributes/position.md")] + position: String, + position_top: String, + position_right: String, + position_bottom: String, + position_left: String, + layer: String, + + // Transform #[doc = include_str!("_docs/attributes/rotate.md")] rotate: String, #[doc = include_str!("_docs/attributes/opacity.md")] opacity: String, + // Svg svg_data: String, svg_content: String, + // Accessibility a11y_id: String, a11y_focusable: String, a11y_auto_focus: String, From 66523af9afbec5e57b20e5decb349d5f0954d477 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sat, 12 Oct 2024 13:58:34 +0200 Subject: [PATCH 02/36] feat: `text_height` attribute to control the height behavior of text (#976) * feat: `text_height` attribute to control the height behavior of text * update mocked apis * clean up --- crates/components/src/button.rs | 1 + crates/components/src/progress_bar.rs | 1 + crates/core/src/render/utils/label.rs | 4 ++- crates/core/src/render/utils/paragraph.rs | 12 +++++-- .../src/_docs/attributes/text_height.md | 22 +++++++++++++ crates/elements/src/definitions.rs | 6 ++++ crates/engine/src/mocked.rs | 14 +++++++-- crates/native-core/src/attributes.rs | 2 ++ crates/state/src/font_style.rs | 24 +++++++++++++- crates/state/src/values/mod.rs | 2 ++ crates/state/src/values/text_height.rs | 31 +++++++++++++++++++ 11 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 crates/elements/src/_docs/attributes/text_height.md create mode 100644 crates/state/src/values/text_height.rs diff --git a/crates/components/src/button.rs b/crates/components/src/button.rs index 9f4e97a23..9ab309b82 100644 --- a/crates/components/src/button.rs +++ b/crates/components/src/button.rs @@ -274,6 +274,7 @@ pub fn ButtonBase( corner_radius: "{corner_radius}", background: "{background}", text_align: "center", + text_height: "disable-least-ascent", main_align: "center", cross_align: "center", {&children} diff --git a/crates/components/src/progress_bar.rs b/crates/components/src/progress_bar.rs index df797f144..c26adc492 100644 --- a/crates/components/src/progress_bar.rs +++ b/crates/components/src/progress_bar.rs @@ -76,6 +76,7 @@ pub fn ProgressBar( width: "100%", color: "{color}", max_lines: "1", + text_height: "disable-least-ascent", "{progress.floor()}%" } } diff --git a/crates/core/src/render/utils/label.rs b/crates/core/src/render/utils/label.rs index e1d1619b2..1ed471caa 100644 --- a/crates/core/src/render/utils/label.rs +++ b/crates/core/src/render/utils/label.rs @@ -21,12 +21,14 @@ pub fn create_label( paragraph_style.set_text_align(font_style.text_align); paragraph_style.set_max_lines(font_style.max_lines); paragraph_style.set_replace_tab_characters(true); + paragraph_style.set_text_height_behavior(font_style.text_height); if let Some(ellipsis) = font_style.text_overflow.get_ellipsis() { paragraph_style.set_ellipsis(ellipsis); } - let text_style = font_style.text_style(default_font_family, scale_factor); + let text_style = + font_style.text_style(default_font_family, scale_factor, font_style.text_height); paragraph_style.set_text_style(&text_style); let mut paragraph_builder = ParagraphBuilder::new(¶graph_style, font_collection); diff --git a/crates/core/src/render/utils/paragraph.rs b/crates/core/src/render/utils/paragraph.rs index 6e8754a28..c4b84dabf 100644 --- a/crates/core/src/render/utils/paragraph.rs +++ b/crates/core/src/render/utils/paragraph.rs @@ -34,6 +34,7 @@ pub fn create_paragraph( paragraph_style.set_text_align(font_style.text_align); paragraph_style.set_max_lines(font_style.max_lines); paragraph_style.set_replace_tab_characters(true); + paragraph_style.set_text_height_behavior(font_style.text_height); if let Some(ellipsis) = font_style.text_overflow.get_ellipsis() { paragraph_style.set_ellipsis(ellipsis); @@ -41,7 +42,8 @@ pub fn create_paragraph( let mut paragraph_builder = ParagraphBuilder::new(¶graph_style, font_collection); - let text_style = font_style.text_style(default_font_family, scale_factor); + let text_style = + font_style.text_style(default_font_family, scale_factor, font_style.text_height); paragraph_builder.push_style(&text_style); for text_span in node.children() { @@ -52,8 +54,12 @@ pub fn create_paragraph( let text_nodes = text_span.children(); let text_node = *text_nodes.first().unwrap(); let text_node_type = &*text_node.node_type(); - let font_style = text_span.get::().unwrap(); - let text_style = font_style.text_style(default_font_family, scale_factor); + let text_font_style = text_span.get::().unwrap(); + let text_style = text_font_style.text_style( + default_font_family, + scale_factor, + font_style.text_height, + ); paragraph_builder.push_style(&text_style); if let NodeType::Text(text) = text_node_type { diff --git a/crates/elements/src/_docs/attributes/text_height.md b/crates/elements/src/_docs/attributes/text_height.md new file mode 100644 index 000000000..270d7450a --- /dev/null +++ b/crates/elements/src/_docs/attributes/text_height.md @@ -0,0 +1,22 @@ +Specify the text height behavior. + +Accepted values: + +- `disable-all` (default) +- `all` +- `disable-first-ascent` +- `disable-least-ascent` + +### Example + +```rust, no_run +# use freya::prelude::*; +fn app() -> Element { + rsx!( + label { + text_height: "disable-all", + "Hello, World!" + } + ) +} +``` \ No newline at end of file diff --git a/crates/elements/src/definitions.rs b/crates/elements/src/definitions.rs index a0a92abb7..fffe3f5b3 100644 --- a/crates/elements/src/definitions.rs +++ b/crates/elements/src/definitions.rs @@ -253,6 +253,8 @@ builder_constructors! { letter_spacing: String, #[doc = include_str!("_docs/attributes/word_spacing.md")] word_spacing: String, + #[doc = include_str!("_docs/attributes/text_height.md")] + text_height: String, // Transform #[doc = include_str!("_docs/attributes/rotate.md")] @@ -407,6 +409,8 @@ builder_constructors! { letter_spacing: String, #[doc = include_str!("_docs/attributes/word_spacing.md")] word_spacing: String, + #[doc = include_str!("_docs/attributes/text_height.md")] + text_height: String, // Transform #[doc = include_str!("_docs/attributes/rotate.md")] @@ -563,6 +567,8 @@ builder_constructors! { letter_spacing: String, #[doc = include_str!("_docs/attributes/word_spacing.md")] word_spacing: String, + #[doc = include_str!("_docs/attributes/text_height.md")] + text_height: String, // Transform #[doc = include_str!("_docs/attributes/rotate.md")] diff --git a/crates/engine/src/mocked.rs b/crates/engine/src/mocked.rs index cfeb00df0..3ba169335 100644 --- a/crates/engine/src/mocked.rs +++ b/crates/engine/src/mocked.rs @@ -613,6 +613,18 @@ impl TextStyle { pub fn set_placeholder(&mut self) -> &mut Self { unimplemented!("This is mocked") } + + pub fn set_height_behavior(&mut self, behavior: TextHeightBehavior) { + unimplemented!("This is mocked") + } +} + +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum TextHeightBehavior { + All = 0, + DisableFirstAscent = 1, + DisableLastDescent = 2, + DisableAll = 3, } pub struct Typeface; @@ -988,8 +1000,6 @@ impl From<&FontCollection> for FontCollection { pub struct StrutStyle; -pub struct TextHeightBehavior; - #[repr(i32)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub enum TextDirection { diff --git a/crates/native-core/src/attributes.rs b/crates/native-core/src/attributes.rs index 1e7f2713a..59526e20c 100644 --- a/crates/native-core/src/attributes.rs +++ b/crates/native-core/src/attributes.rs @@ -33,6 +33,7 @@ pub enum AttributeName { DecorationColor, DecorationStyle, TextOverflow, + TextHeight, Rotate, Overflow, Margin, @@ -253,6 +254,7 @@ impl FromStr for AttributeName { "decoration_color" => Ok(AttributeName::DecorationColor), "decoration_style" => Ok(AttributeName::DecorationStyle), "text_overflow" => Ok(AttributeName::TextOverflow), + "text_height" => Ok(AttributeName::TextHeight), "rotate" => Ok(AttributeName::Rotate), "overflow" => Ok(AttributeName::Overflow), "margin" => Ok(AttributeName::Margin), diff --git a/crates/state/src/font_style.rs b/crates/state/src/font_style.rs index 81005d484..18c033488 100644 --- a/crates/state/src/font_style.rs +++ b/crates/state/src/font_style.rs @@ -26,6 +26,7 @@ use crate::{ ExtSplit, Parse, ParseAttribute, + TextHeight, TextOverflow, }; @@ -45,10 +46,16 @@ pub struct FontStyleState { pub text_align: TextAlign, pub max_lines: Option, pub text_overflow: TextOverflow, + pub text_height: TextHeightBehavior, } impl FontStyleState { - pub fn text_style(&self, default_font_family: &[String], scale_factor: f32) -> TextStyle { + pub fn text_style( + &self, + default_font_family: &[String], + scale_factor: f32, + paragraph_text_height: TextHeightBehavior, + ) -> TextStyle { let mut text_style = TextStyle::new(); let mut font_family = self.font_family.clone(); @@ -66,6 +73,11 @@ impl FontStyleState { .set_word_spacing(self.word_spacing) .set_letter_spacing(self.letter_spacing); + if paragraph_text_height.needs_custom_height() { + text_style.set_height_override(true); + text_style.set_half_leading(true); + } + if let Some(line_height) = self.line_height { text_style.set_height_override(true).set_height(line_height); } @@ -102,6 +114,7 @@ impl Default for FontStyleState { text_align: TextAlign::default(), max_lines: None, text_overflow: TextOverflow::default(), + text_height: TextHeightBehavior::DisableAll, } } } @@ -234,6 +247,14 @@ impl ParseAttribute for FontStyleState { } } } + AttributeName::TextHeight => { + let value = attr.value.as_text(); + if let Some(value) = value { + if let Ok(text_height) = TextHeightBehavior::parse(value) { + self.text_height = text_height; + } + } + } _ => {} } @@ -267,6 +288,7 @@ impl State for FontStyleState { AttributeName::DecorationColor, AttributeName::DecorationStyle, AttributeName::TextOverflow, + AttributeName::TextHeight, ])); fn update<'a>( diff --git a/crates/state/src/values/mod.rs b/crates/state/src/values/mod.rs index 7cabda902..83d564b48 100644 --- a/crates/state/src/values/mod.rs +++ b/crates/state/src/values/mod.rs @@ -16,6 +16,7 @@ mod overflow; mod position; mod shadow; mod size; +mod text_height; mod text_shadow; pub use border::*; @@ -30,3 +31,4 @@ pub use highlight::*; pub use overflow::*; pub use shadow::*; pub use size::*; +pub use text_height::*; diff --git a/crates/state/src/values/text_height.rs b/crates/state/src/values/text_height.rs new file mode 100644 index 000000000..4977b383d --- /dev/null +++ b/crates/state/src/values/text_height.rs @@ -0,0 +1,31 @@ +use freya_engine::prelude::*; + +use crate::{ + Parse, + ParseError, +}; + +impl Parse for TextHeightBehavior { + fn parse(value: &str) -> Result { + match value { + "all" => Ok(TextHeightBehavior::All), + "disable-first-ascent" => Ok(TextHeightBehavior::DisableFirstAscent), + "disable-least-ascent" => Ok(TextHeightBehavior::DisableLastDescent), + "disable-all" => Ok(TextHeightBehavior::DisableAll), + _ => Err(ParseError), + } + } +} + +pub trait TextHeight { + fn needs_custom_height(&self) -> bool; +} + +impl TextHeight for TextHeightBehavior { + fn needs_custom_height(&self) -> bool { + matches!( + self, + Self::All | Self::DisableFirstAscent | Self::DisableLastDescent + ) + } +} From 3a2e73a07bd0558499d06ffcd33a05d00bc4dc87 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sat, 12 Oct 2024 16:56:37 +0200 Subject: [PATCH 03/36] chore: Clean up readme `Tile` --- crates/components/src/tile.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/components/src/tile.rs b/crates/components/src/tile.rs index 17cd1aa52..a18cea3a0 100644 --- a/crates/components/src/tile.rs +++ b/crates/components/src/tile.rs @@ -42,8 +42,6 @@ pub fn Tile( onselect: Option>, /// Theme override. theme: Option, - - a11y_name: Option, ) -> Element { let mut status = use_signal(TileStatus::default); let platform = use_platform(); From 3305e7cd54e5ccdd0b6f17463acfe0b5ba1c09db Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sun, 13 Oct 2024 10:11:26 +0200 Subject: [PATCH 04/36] docs: Add missing 0.2 docs (#916) * docs: Add missing 0.2 docs * docs: Update image and svg docs * fmt --- crates/components/src/activable_route.rs | 24 +++++++++++++++++++++++- crates/elements/src/definitions.rs | 13 ++++++++----- crates/hooks/src/use_activable_route.rs | 1 + 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/crates/components/src/activable_route.rs b/crates/components/src/activable_route.rs index e07fbe36a..362adc2b6 100644 --- a/crates/components/src/activable_route.rs +++ b/crates/components/src/activable_route.rs @@ -5,7 +5,29 @@ use dioxus_router::{ }; use freya_hooks::ActivableRouteContext; -/// Provide a context to the inner components so they can know whether the passed route is the current router in the Router or not. +/// Sometimes you might want to know if a route is selected so you can style a specific UI element in a different way, +/// like a button with a different color. +/// To avoid cluttering your components with router-specific code you might instead want to wrap your component in an `ActivableRoute` +/// and inside your component call `use_activable_route`. +/// +/// This way, your component and all its desdendants will just know whether a route is activated or not, but not which one. +/// +/// ```rs +/// Link { +/// to: Route::Home, // Direction route +/// ActivableRoute { +/// route: Route::Home, // Activation route +/// SidebarItem { +/// // `SidebarItem` will now appear "activated" when the route is `Route::Home` +/// // `ActivableRoute` is letting it know whether `Route::Home` is enabled +/// // or not, without the need to add router-specific logic in `SidebarItem`. +/// label { +/// "Go to Hey ! 👋" +/// } +/// }, +/// } +/// } +/// ``` #[allow(non_snake_case)] #[component] pub fn ActivableRoute( diff --git a/crates/elements/src/definitions.rs b/crates/elements/src/definitions.rs index fffe3f5b3..4616f1ae4 100644 --- a/crates/elements/src/definitions.rs +++ b/crates/elements/src/definitions.rs @@ -689,6 +689,8 @@ builder_constructors! { }; /// `image` element let's you show an image. /// + /// For dynamic Images you may use `dynamic_bytes`. + /// /// ### Example /// /// ```rust, ignore, no_run @@ -700,8 +702,8 @@ builder_constructors! { /// rsx!( /// image { /// image_data: image_data, - /// width: "{size}", - /// height: "{size}", + /// width: "100%", // You must specify size otherwhise it will default to 0 + /// height: "100%", /// } /// ) /// } @@ -809,8 +811,7 @@ builder_constructors! { }; /// `svg` element let's you display SVG code. /// - /// You will need to use the [`dynamic_bytes`](https://docs.freyaui.dev/freya/prelude/fn.dynamic_bytes.html) - /// to transform the bytes into data the element can recognize. + /// For dynamic SVGs you may use `dynamic_bytes`. /// /// ### Example /// @@ -819,10 +820,12 @@ builder_constructors! { /// static FERRIS: &[u8] = include_bytes!("./ferris.svg"); /// /// fn app() -> Element { - /// let ferris = dynamic_bytes(FERRIS); + /// let ferris = static_bytes(FERRIS); /// rsx!( /// svg { /// svg_data: ferris, + /// width: "100%", // You must specify size otherwhise it will default to 0 + /// height: "100%", /// } /// ) /// } diff --git a/crates/hooks/src/use_activable_route.rs b/crates/hooks/src/use_activable_route.rs index 35c5a60ec..024b8fea8 100644 --- a/crates/hooks/src/use_activable_route.rs +++ b/crates/hooks/src/use_activable_route.rs @@ -13,6 +13,7 @@ impl ActivableRouteContext { } } +/// Consume an activable Route, use in combination with `ActivableRoute`. pub fn use_activable_route() -> bool { let ctx = try_use_context::(); From 9388a40bec84f3a900f7534a4797b8b6eb03567c Mon Sep 17 00:00:00 2001 From: _Robertas <66907345+RobertasJ@users.noreply.github.com> Date: Sun, 13 Oct 2024 13:33:32 +0200 Subject: [PATCH 05/36] feat: in-memory canvas snapshots (#979) * ignore bacon.toml * feat: create_snapshot * formatting * change docs Co-authored-by: Marc Espin * requested changes * formatting... * Apply suggestions from code review Co-authored-by: Marc Espin * formatting... --------- Co-authored-by: Marc Espin --- .gitignore | 3 ++- crates/testing/src/test_handler.rs | 18 +++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 4c4071f5b..79f56b260 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ Cargo.lock .idea snapshot_before.png snapshot_after.png -documents_example \ No newline at end of file +documents_example +bacon.toml diff --git a/crates/testing/src/test_handler.rs b/crates/testing/src/test_handler.rs index 3b4876622..e778182a6 100644 --- a/crates/testing/src/test_handler.rs +++ b/crates/testing/src/test_handler.rs @@ -15,6 +15,7 @@ use freya_core::prelude::{ use freya_engine::prelude::{ raster_n32_premul, Color, + Data, EncodedImageFormat, FontCollection, FontMgr, @@ -299,8 +300,8 @@ impl TestingHandler { self.utils.sdom() } - /// Render the app into a canvas and save it into a file. - pub fn save_snapshot(&mut self, snapshot_path: impl Into) { + /// Render the app into a canvas and make a snapshot of it. + pub fn create_snapshot(&mut self) -> Data { let fdom = self.utils.sdom.get(); let (width, height) = self.config.size.to_i32().to_tuple(); @@ -341,16 +342,19 @@ impl TestingHandler { // Capture snapshot let image = surface.image_snapshot(); let mut context = surface.direct_context(); - let snapshot_data = image + image .encode(context.as_mut(), EncodedImageFormat::PNG, None) - .expect("Failed to encode the snapshot."); + .expect("Failed to encode the snapshot.") + } - // Save snapshot + /// Render the app into a canvas and save it into a file. + pub fn save_snapshot(&mut self, snapshot_path: impl Into) { let mut snapshot_file = File::create(snapshot_path.into()).expect("Failed to create the snapshot file."); - let snapshot_bytes = snapshot_data.as_bytes(); + let snapshot_data = self.create_snapshot(); + snapshot_file - .write_all(snapshot_bytes) + .write_all(&snapshot_data) .expect("Failed to save the snapshot file."); } From 1c9d57992d257d75a3c6b050ee4042232a49f68a Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sun, 13 Oct 2024 13:33:59 +0200 Subject: [PATCH 06/36] feat: Allow passing state context in freya-testing (#981) * feat: Allow passing state context in freya-testing * fix * fix core tests --- crates/core/src/render/compositor.rs | 2 +- crates/hooks/src/use_init_native_platform.rs | 6 +++--- crates/hooks/src/use_node.rs | 2 +- crates/hooks/tests/use_focus.rs | 4 ++-- crates/hooks/tests/use_platform_information.rs | 2 +- crates/testing/src/config.rs | 10 ++++++---- crates/testing/src/launch.rs | 7 +++++-- crates/testing/src/lib.rs | 2 +- crates/testing/src/test_handler.rs | 12 ++++++++---- 9 files changed, 28 insertions(+), 19 deletions(-) diff --git a/crates/core/src/render/compositor.rs b/crates/core/src/render/compositor.rs index e7a1e503c..f133b88ee 100644 --- a/crates/core/src/render/compositor.rs +++ b/crates/core/src/render/compositor.rs @@ -257,7 +257,7 @@ mod test { use itertools::sorted; fn run_compositor( - utils: &TestingHandler, + utils: &TestingHandler<()>, compositor: &mut Compositor, ) -> (Layers, Layers, usize) { let sdom = utils.sdom(); diff --git a/crates/hooks/src/use_init_native_platform.rs b/crates/hooks/src/use_init_native_platform.rs index aa267f673..ce98be2d1 100644 --- a/crates/hooks/src/use_init_native_platform.rs +++ b/crates/hooks/src/use_init_native_platform.rs @@ -118,7 +118,7 @@ mod test { let mut utils = launch_test_with_config( use_focus_app, - TestingConfig { + TestingConfig::<()> { size: (100.0, 100.0).into(), ..TestingConfig::default() }, @@ -173,7 +173,7 @@ mod test { let mut utils = launch_test_with_config( use_focus_app, - TestingConfig { + TestingConfig::<()> { size: (100.0, 100.0).into(), ..TestingConfig::default() }, @@ -233,7 +233,7 @@ mod test { let mut utils = launch_test_with_config( use_focus_app, - TestingConfig { + TestingConfig::<()> { size: (100.0, 100.0).into(), ..TestingConfig::default() }, diff --git a/crates/hooks/src/use_node.rs b/crates/hooks/src/use_node.rs index 366541eab..fb5716dab 100644 --- a/crates/hooks/src/use_node.rs +++ b/crates/hooks/src/use_node.rs @@ -90,7 +90,7 @@ mod test { let mut utils = launch_test_with_config( use_node_app, - TestingConfig { + TestingConfig::<()> { size: (500.0, 800.0).into(), ..TestingConfig::default() }, diff --git a/crates/hooks/tests/use_focus.rs b/crates/hooks/tests/use_focus.rs index d62545d7a..f6552a842 100644 --- a/crates/hooks/tests/use_focus.rs +++ b/crates/hooks/tests/use_focus.rs @@ -37,7 +37,7 @@ pub async fn track_focus() { let mut utils = launch_test_with_config( use_focus_app, - TestingConfig { + TestingConfig::<()> { size: (100.0, 100.0).into(), ..TestingConfig::default() }, @@ -117,7 +117,7 @@ pub async fn block_focus() { let mut utils = launch_test_with_config( use_focus_app, - TestingConfig { + TestingConfig::<()> { size: (100.0, 100.0).into(), ..TestingConfig::default() }, diff --git a/crates/hooks/tests/use_platform_information.rs b/crates/hooks/tests/use_platform_information.rs index da26688bf..596513cf7 100644 --- a/crates/hooks/tests/use_platform_information.rs +++ b/crates/hooks/tests/use_platform_information.rs @@ -14,7 +14,7 @@ async fn window_size() { let mut utils = launch_test_with_config( use_animation_app, - TestingConfig { + TestingConfig::<()> { size: (333.0, 190.0).into(), ..TestingConfig::default() }, diff --git a/crates/testing/src/config.rs b/crates/testing/src/config.rs index 3b9d8d8bc..009c858a9 100644 --- a/crates/testing/src/config.rs +++ b/crates/testing/src/config.rs @@ -3,24 +3,26 @@ use std::time::Duration; use torin::geometry::Size2D; /// Configuration for [`crate::test_handler::TestingHandler`]. -#[derive(Clone, Copy)] -pub struct TestingConfig { +#[derive(Clone)] +pub struct TestingConfig { pub vdom_timeout: Duration, pub size: Size2D, pub event_loop_ticker: bool, + pub state: Option, } -impl Default for TestingConfig { +impl Default for TestingConfig { fn default() -> Self { Self { vdom_timeout: Duration::from_millis(16), size: Size2D::from((500.0, 500.0)), event_loop_ticker: true, + state: None, } } } -impl TestingConfig { +impl TestingConfig { pub fn new() -> Self { TestingConfig::default() } diff --git a/crates/testing/src/launch.rs b/crates/testing/src/launch.rs index 225dc4e64..7fad171c2 100644 --- a/crates/testing/src/launch.rs +++ b/crates/testing/src/launch.rs @@ -32,12 +32,15 @@ use crate::{ /// Run a Component in a headless testing environment. /// /// Default size is `500x500`. -pub fn launch_test(root: AppComponent) -> TestingHandler { +pub fn launch_test(root: AppComponent) -> TestingHandler<()> { launch_test_with_config(root, TestingConfig::default()) } /// Run a Component in a headless testing environment -pub fn launch_test_with_config(root: AppComponent, config: TestingConfig) -> TestingHandler { +pub fn launch_test_with_config( + root: AppComponent, + config: TestingConfig, +) -> TestingHandler { let vdom = with_accessibility(root); let fdom = FreyaDOM::default(); let sdom = SafeDOM::new(fdom); diff --git a/crates/testing/src/lib.rs b/crates/testing/src/lib.rs index 401d246b6..a92b65032 100644 --- a/crates/testing/src/lib.rs +++ b/crates/testing/src/lib.rs @@ -139,7 +139,7 @@ //! //! let mut utils = launch_test_with_config( //! our_component, -//! TestingConfig { +//! TestingConfig::<()> { //! size: (500.0, 800.0).into(), //! ..TestingConfig::default() //! }, diff --git a/crates/testing/src/test_handler.rs b/crates/testing/src/test_handler.rs index e778182a6..dd69962d9 100644 --- a/crates/testing/src/test_handler.rs +++ b/crates/testing/src/test_handler.rs @@ -54,7 +54,7 @@ use crate::{ }; /// Manages the lifecycle of your tests. -pub struct TestingHandler { +pub struct TestingHandler { pub(crate) vdom: VirtualDom, pub(crate) utils: TestUtils, pub(crate) event_emitter: EventEmitter, @@ -68,12 +68,12 @@ pub struct TestingHandler { pub(crate) font_collection: FontCollection, pub(crate) font_mgr: FontMgr, pub(crate) accessibility_tree: SharedAccessibilityTree, - pub(crate) config: TestingConfig, + pub(crate) config: TestingConfig, pub(crate) ticker_sender: broadcast::Sender<()>, pub(crate) cursor_icon: CursorIcon, } -impl TestingHandler { +impl TestingHandler { /// Init the DOM. pub(crate) fn init_dom(&mut self) { self.provide_vdom_contexts(); @@ -83,7 +83,7 @@ impl TestingHandler { } /// Get a mutable reference to the current [`TestingConfig`]. - pub fn config(&mut self) -> &mut TestingConfig { + pub fn config(&mut self) -> &mut TestingConfig { &mut self.config } @@ -102,6 +102,10 @@ impl TestingHandler { }; self.vdom .insert_any_root_context(Box::new(accessibility_generator)); + + if let Some(state) = self.config.state.clone() { + self.vdom.insert_any_root_context(Box::new(state)); + } } /// Wait and apply new changes From 65a8be7506dfb3b4a4ccdc9f7550944d2ad736c1 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sun, 13 Oct 2024 13:51:09 +0200 Subject: [PATCH 07/36] chore: Replace dioxus-sdk with dioxus-clipboard (#973) * chore: Replace dioxus-sdk with dioxus-clipboard * use freya elements in use_platform_information * fix import --- Cargo.toml | 4 ++-- crates/components/src/native_container.rs | 8 +++++++- crates/components/src/popup.rs | 5 ++++- crates/components/src/slider.rs | 1 + crates/components/src/tile.rs | 1 + crates/hooks/Cargo.toml | 2 +- crates/hooks/src/rope_editor.rs | 2 +- crates/hooks/src/text_editor.rs | 2 +- crates/hooks/src/use_editable.rs | 8 ++++---- crates/hooks/tests/use_platform_information.rs | 1 + examples/text_editors.rs | 2 +- 11 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 315f39f6a..313e95cce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ dioxus-signals = { version = "0.5" } dioxus-core = { version = "0.5" } dioxus-hot-reload = { version = "0.5", features = ["file_watcher"], default-features = false } dioxus-router = { version = "0.5", default-features = false } -dioxus-sdk = { version = "0.5", features = ["clipboard"]} +dioxus-clipboard = "0.1" skia-safe = { version = "0.75.0", features = ["gl", "textlayout", "svg"] } @@ -96,7 +96,7 @@ tree-sitter-highlight = "0.23.0" tree-sitter-rust = "0.23.0" rfd = "0.14.1" bytes = "1.5.0" -dioxus-sdk = { workspace = true } +dioxus-clipboard = { workspace = true } winit = { workspace = true } [profile.release] diff --git a/crates/components/src/native_container.rs b/crates/components/src/native_container.rs index 82d2b6db8..dc06f6f54 100644 --- a/crates/components/src/native_container.rs +++ b/crates/components/src/native_container.rs @@ -2,7 +2,13 @@ use dioxus::prelude::*; use freya_core::prelude::EventMessage; use freya_elements::{ elements as dioxus_elements, - events::KeyboardEvent, + events::{ + keyboard::{ + Key, + Modifiers, + }, + KeyboardEvent, + }, }; use freya_hooks::{ use_init_native_platform, diff --git a/crates/components/src/popup.rs b/crates/components/src/popup.rs index 68885634b..67f52af72 100644 --- a/crates/components/src/popup.rs +++ b/crates/components/src/popup.rs @@ -1,7 +1,10 @@ use dioxus::prelude::*; use freya_elements::{ elements as dioxus_elements, - events::KeyboardEvent, + events::{ + keyboard::Key, + KeyboardEvent, + }, }; use freya_hooks::{ theme_with, diff --git a/crates/components/src/slider.rs b/crates/components/src/slider.rs index ce3a9d3b3..e656e66fe 100644 --- a/crates/components/src/slider.rs +++ b/crates/components/src/slider.rs @@ -2,6 +2,7 @@ use dioxus::prelude::*; use freya_elements::{ elements as dioxus_elements, events::{ + keyboard::Key, KeyboardEvent, MouseEvent, WheelEvent, diff --git a/crates/components/src/tile.rs b/crates/components/src/tile.rs index a18cea3a0..c4563ad0d 100644 --- a/crates/components/src/tile.rs +++ b/crates/components/src/tile.rs @@ -2,6 +2,7 @@ use dioxus::prelude::*; use freya_elements::{ elements as dioxus_elements, events::{ + keyboard::Key, KeyboardEvent, MouseEvent, }, diff --git a/crates/hooks/Cargo.toml b/crates/hooks/Cargo.toml index 301dc163d..7c581176b 100644 --- a/crates/hooks/Cargo.toml +++ b/crates/hooks/Cargo.toml @@ -29,7 +29,7 @@ torin = { workspace = true } dioxus-hooks = { workspace = true } dioxus-signals = { workspace = true } dioxus-core = { workspace = true } -dioxus-sdk = { workspace = true } +dioxus-clipboard = { workspace = true } tokio = { workspace = true } winit = { workspace = true } diff --git a/crates/hooks/src/rope_editor.rs b/crates/hooks/src/rope_editor.rs index 017e95e0f..b46d992d3 100644 --- a/crates/hooks/src/rope_editor.rs +++ b/crates/hooks/src/rope_editor.rs @@ -4,7 +4,7 @@ use std::{ ops::Range, }; -use dioxus_sdk::clipboard::UseClipboard; +use dioxus_clipboard::prelude::UseClipboard; use ropey::iter::Lines; pub use ropey::Rope; diff --git a/crates/hooks/src/text_editor.rs b/crates/hooks/src/text_editor.rs index 936c3f13f..bbb48fdaa 100644 --- a/crates/hooks/src/text_editor.rs +++ b/crates/hooks/src/text_editor.rs @@ -5,7 +5,7 @@ use std::{ ops::Range, }; -use dioxus_sdk::clipboard::UseClipboard; +use dioxus_clipboard::prelude::UseClipboard; use freya_elements::events::keyboard::{ Code, Key, diff --git a/crates/hooks/src/use_editable.rs b/crates/hooks/src/use_editable.rs index a2af7ce88..d2008489a 100644 --- a/crates/hooks/src/use_editable.rs +++ b/crates/hooks/src/use_editable.rs @@ -1,14 +1,14 @@ use std::rc::Rc; +use dioxus_clipboard::prelude::{ + use_clipboard, + UseClipboard, +}; use dioxus_core::{ prelude::spawn, use_hook, AttributeValue, }; -use dioxus_sdk::clipboard::{ - use_clipboard, - UseClipboard, -}; use dioxus_signals::{ Readable, Signal, diff --git a/crates/hooks/tests/use_platform_information.rs b/crates/hooks/tests/use_platform_information.rs index 596513cf7..4bd7bbc61 100644 --- a/crates/hooks/tests/use_platform_information.rs +++ b/crates/hooks/tests/use_platform_information.rs @@ -1,5 +1,6 @@ use dioxus::prelude::*; use freya::prelude::use_platform_information; +use freya_elements::elements as dioxus_elements; use freya_testing::prelude::*; #[tokio::test] diff --git a/examples/text_editors.rs b/examples/text_editors.rs index 8ca01547a..58535b08e 100644 --- a/examples/text_editors.rs +++ b/examples/text_editors.rs @@ -3,7 +3,7 @@ windows_subsystem = "windows" )] -use dioxus_sdk::clipboard::use_clipboard; +use dioxus_clipboard::prelude::use_clipboard; use freya::prelude::*; fn main() { From 672a6b4a7a9f938e12a87d36c86435509a7760a2 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sun, 13 Oct 2024 17:37:38 +0200 Subject: [PATCH 08/36] feat: `on_deps_change` method for animations (#977) --- crates/components/src/switch.rs | 2 ++ crates/hooks/src/use_animation.rs | 21 +++++++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/crates/components/src/switch.rs b/crates/components/src/switch.rs index 925a2998a..4d2dc344c 100644 --- a/crates/components/src/switch.rs +++ b/crates/components/src/switch.rs @@ -15,6 +15,7 @@ use freya_hooks::{ AnimNum, Ease, Function, + OnDepsChange, SwitchThemeWith, }; use winit::window::CursorIcon; @@ -67,6 +68,7 @@ pub enum SwitchStatus { pub fn Switch(props: SwitchProps) -> Element { let theme = use_applied_theme!(&props.theme, switch); let animation = use_animation_with_dependencies(&theme, |ctx, theme| { + ctx.on_deps_change(OnDepsChange::Run); ( ctx.with( AnimNum::new(2., 22.) diff --git a/crates/hooks/src/use_animation.rs b/crates/hooks/src/use_animation.rs index b36336ddc..5f3004184 100644 --- a/crates/hooks/src/use_animation.rs +++ b/crates/hooks/src/use_animation.rs @@ -379,6 +379,7 @@ pub struct Context { animated_values: Vec>>, on_finish: OnFinish, auto_start: bool, + on_deps_change: OnDepsChange, } impl Context { @@ -398,6 +399,11 @@ impl Context { self.auto_start = auto_start; self } + + pub fn on_deps_change(&mut self, on_deps_change: OnDepsChange) -> &mut Self { + self.on_deps_change = on_deps_change; + self + } } /// Controls the direction of the animation. @@ -425,6 +431,14 @@ pub enum OnFinish { Restart, } +/// What to do once the animation dependencies change. By default it is [`Reset`](OnDepsChange::Reset) +#[derive(PartialEq, Clone, Copy, Default)] +pub enum OnDepsChange { + #[default] + Reset, + Run, +} + /// Animate your elements. Use [`use_animation`] to use this. #[derive(PartialEq, Clone)] pub struct UseAnimator { @@ -446,8 +460,11 @@ impl UseAnimator { /// Reset the animation to the default state. pub fn reset(&self) { + let mut has_run_yet = self.has_run_yet; let mut task = self.task; + has_run_yet.set(false); + if let Some(task) = task.write().take() { task.cancel(); } @@ -721,8 +738,8 @@ where }; use_memo(move || { - let _ = value_and_ctx.read(); - if *has_run_yet.peek() { + let value_and_ctx = value_and_ctx.read(); + if *has_run_yet.peek() && value_and_ctx.1.on_deps_change == OnDepsChange::Run { animator.run_update() } }); From cb4917d8a0d19ca0959d81dda00938d938afe1e1 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Thu, 24 Oct 2024 22:37:32 +0200 Subject: [PATCH 09/36] fix: Use the config size for the compositor dirty area in freya-testing when resizing (#989) --- crates/testing/src/launch.rs | 1 + crates/testing/src/test_handler.rs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/crates/testing/src/launch.rs b/crates/testing/src/launch.rs index 7fad171c2..4d934666b 100644 --- a/crates/testing/src/launch.rs +++ b/crates/testing/src/launch.rs @@ -79,6 +79,7 @@ pub fn launch_test_with_config( }; handler.init_dom(); + handler.resize(handler.config.size); handler } diff --git a/crates/testing/src/test_handler.rs b/crates/testing/src/test_handler.rs index dd69962d9..db2e6e339 100644 --- a/crates/testing/src/test_handler.rs +++ b/crates/testing/src/test_handler.rs @@ -292,6 +292,11 @@ impl TestingHandler { state.information.viewport_size = size; }); self.utils.sdom().get_mut().layout().reset(); + self.utils + .sdom() + .get_mut() + .compositor_dirty_area() + .unite_or_insert(&Area::new((0.0, 0.0).into(), size)); } /// Get the current [CursorIcon]. From e5f7f5a0b46933012c1bc52dd43f760cf7a8e640 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Thu, 31 Oct 2024 15:35:02 +0000 Subject: [PATCH 10/36] =?UTF-8?q?Deploying=20to=20main=20from=20@=20marc23?= =?UTF-8?q?32/freya@cb4917d8a0d19ca0959d81dda00938d938afe1e1=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 93233e2ba..2a821cb49 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ If you are interested in supporting the development of this project feel free to Thanks to my sponsors for supporting this project! 😄 -高庆丰 +高庆丰Lino Le Van ### Special thanks 💪 From b4be42b01a302b002dc6b545b40f2aedad4d1193 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Fri, 1 Nov 2024 18:02:32 +0100 Subject: [PATCH 11/36] feat: Consider antialising for incremental rendering (#985) * feat: Consider antialising for incremental rendering * adapt tests * add note --- crates/core/src/elements/utils.rs | 3 ++- crates/core/src/render/compositor.rs | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/core/src/elements/utils.rs b/crates/core/src/elements/utils.rs index 9d3d8e446..4575e653b 100644 --- a/crates/core/src/elements/utils.rs +++ b/crates/core/src/elements/utils.rs @@ -85,7 +85,8 @@ pub trait ElementUtils { } } - Some(drawing_area) + // Inflate the area by 1px in each side to cover potential off-bounds rendering caused by antialising + Some(drawing_area.inflate(1.0, 1.0)) } /// Measure the area for this element considering other diff --git a/crates/core/src/render/compositor.rs b/crates/core/src/render/compositor.rs index f133b88ee..63c5e6800 100644 --- a/crates/core/src/render/compositor.rs +++ b/crates/core/src/render/compositor.rs @@ -367,6 +367,7 @@ mod test { height: "100", width: "200", background: "red", + margin: "0 0 2 0", onclick: move |_| height += 10, } rect { @@ -374,6 +375,7 @@ mod test { width: "200", background: "green", shadow: "0 {shadow} 8 0 rgb(0, 0, 0, 0.5)", + margin: "0 0 2 0", onclick: move |_| height -= 10, } rect { @@ -418,7 +420,7 @@ mod test { let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); - // Root + First + Second rect + Third rect + // Root + First rect + Second rect + Third Rect assert_eq!(painted_nodes, 4); } @@ -440,6 +442,7 @@ mod test { height: "200", width: "200", direction: "horizontal", + spacing: "2", rect { onclick: move |_| msg_state.toggle(), height: "200", From 00ca9026013b4f50907d22675efbd1c699bc9743 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sun, 10 Nov 2024 12:34:23 +0100 Subject: [PATCH 12/36] feat: flex support (#920) * feat: flex support * move flex to content * flex tests * flex docs * fmt --- .../elements/src/_docs/attributes/content.md | 6 +- crates/elements/src/_docs/size_unit.rs | 27 ++ crates/state/src/values/content.rs | 1 + crates/state/src/values/size.rs | 10 + crates/torin/src/measure.rs | 111 +++++- crates/torin/src/values/content.rs | 6 + crates/torin/src/values/size.rs | 22 +- crates/torin/tests/flex.rs | 321 ++++++++++++++++++ examples/flex.rs | 53 +++ examples/flex_2.rs | 34 ++ 10 files changed, 570 insertions(+), 21 deletions(-) create mode 100644 crates/torin/tests/flex.rs create mode 100644 examples/flex.rs create mode 100644 examples/flex_2.rs diff --git a/crates/elements/src/_docs/attributes/content.md b/crates/elements/src/_docs/attributes/content.md index a26b154ed..d1d723c00 100644 --- a/crates/elements/src/_docs/attributes/content.md +++ b/crates/elements/src/_docs/attributes/content.md @@ -4,10 +4,12 @@ Accepted values: - `normal` (default): Uses parent bounds. - `fit`: Uses parent bounds but later shrunks to the size of the biggest element inside. +- `flex`: Marks the container as flex container, children of this element will be able to use `size`/`size(n)` in their `width` and `height` attributes. -The `fit` mode will allow the inner elements using `width: fill-min` to expand to the biggest element inside this element. -### Example +### `fit` + +The `fit` mode will allow the inner elements using `width: fill-min` to expand to the biggest element inside this element. ```rust, no_run # use freya::prelude::*; diff --git a/crates/elements/src/_docs/size_unit.rs b/crates/elements/src/_docs/size_unit.rs index 15a341bdb..ac2de49a9 100644 --- a/crates/elements/src/_docs/size_unit.rs +++ b/crates/elements/src/_docs/size_unit.rs @@ -102,3 +102,30 @@ //! ) //! } //! ``` +//! +//! #### Flex Factor +//! +//! When being a children of an element with `content: flex` you may change the growth factor of the size attributes. +//! +//! ```rust, no_run +//! # use freya::prelude::*; +//! fn app() -> Element { +//! rsx!( +//! rect { +//! content: "flex", +//! width: "200", +//! height: "200", +//! rect { +//! height: "flex(1)", +//! width: "100%", +//! background: "red" +//! } +//! rect { +//! height: "flex(3)", +//! width: "100%", +//! background: "blue" +//! } +//! } +//! ) +//! } +//! ``` diff --git a/crates/state/src/values/content.rs b/crates/state/src/values/content.rs index 7cd26f0a1..099599ba5 100644 --- a/crates/state/src/values/content.rs +++ b/crates/state/src/values/content.rs @@ -9,6 +9,7 @@ impl Parse for Content { fn parse(value: &str) -> Result { Ok(match value { "fit" => Content::Fit, + "flex" => Content::Flex, _ => Content::Normal, }) } diff --git a/crates/state/src/values/size.rs b/crates/state/src/values/size.rs index ae856e511..12148087a 100644 --- a/crates/state/src/values/size.rs +++ b/crates/state/src/values/size.rs @@ -15,6 +15,16 @@ impl Parse for Size { fn parse(value: &str) -> Result { if value == "auto" { Ok(Size::Inner) + } else if value == "flex" { + Ok(Size::Flex(Length::new(1.0))) + } else if value.contains("flex") { + Ok(Size::Flex(Length::new( + value + .replace("flex(", "") + .replace(')', "") + .parse::() + .map_err(|_| ParseError)?, + ))) } else if value == "fill" { Ok(Size::Fill) } else if value == "fill-min" { diff --git a/crates/torin/src/measure.rs b/crates/torin/src/measure.rs index 4ba77a479..78e17611e 100644 --- a/crates/torin/src/measure.rs +++ b/crates/torin/src/measure.rs @@ -20,6 +20,7 @@ use crate::{ AreaModel, DirectionMode, LayoutMetadata, + Length, Torin, }, }; @@ -308,8 +309,9 @@ where ) { let children = self.dom_adapter.children_of(parent_node_id); + let mut initial_phase_flex_grows = FxHashMap::default(); let mut initial_phase_sizes = FxHashMap::default(); - let mut initial_phase_inner_sizes = *inner_sizes; + let mut initial_phase_inner_sizes = Size2D::default(); // Used to calculate the spacing and some alignments let (non_absolute_children_len, first_child, last_child) = if parent_node.spacing.get() > 0. @@ -342,16 +344,18 @@ where ) }; - // Initial phase: Measure the size and position of the children if the parent has a - // non-start cross alignment, non-start main aligment of a fit-content. - if parent_node.cross_alignment.is_not_start() + let needs_initial_phase = parent_node.cross_alignment.is_not_start() || parent_node.main_alignment.is_not_start() || parent_node.content.is_fit() - { - let mut initial_phase_area = *area; - let mut initial_phase_inner_area = *inner_area; - let mut initial_phase_available_area = *available_area; + || parent_node.content.is_flex(); + let mut initial_phase_area = *area; + let mut initial_phase_inner_area = *inner_area; + let mut initial_phase_available_area = *available_area; + + // Initial phase: Measure the size and position of the children if the parent has a + // non-start cross alignment, non-start main aligment of a fit-content. + if needs_initial_phase { // Measure the children for child_id in children.iter() { let Some(child_data) = self.dom_adapter.get_node(child_id) else { @@ -382,11 +386,13 @@ where Self::stack_child( &mut initial_phase_available_area, parent_node, + &child_data, &mut initial_phase_area, &mut initial_phase_inner_area, &mut initial_phase_inner_sizes, &child_areas.area, is_last_child, + Phase::Initial, ); if parent_node.cross_alignment.is_not_start() @@ -394,8 +400,60 @@ where { initial_phase_sizes.insert(*child_id, child_areas.area.size); } + + if parent_node.content.is_flex() { + match parent_node.direction { + DirectionMode::Vertical => { + if let Some(ff) = child_data.height.flex_grow() { + initial_phase_flex_grows.insert(*child_id, ff); + } + } + DirectionMode::Horizontal => { + if let Some(ff) = child_data.width.flex_grow() { + initial_phase_flex_grows.insert(*child_id, ff); + } + } + } + } } + } + + let initial_available_area = *available_area; + let flex_grows = initial_phase_flex_grows + .values() + .cloned() + .reduce(|acc, v| acc + v) + .unwrap_or_default() + .max(Length::new(1.0)); + + let flex_axis = AlignAxis::new(&parent_node.direction, AlignmentDirection::Main); + + let flex_available_width = initial_available_area.width() - initial_phase_inner_sizes.width; + let flex_available_height = + initial_available_area.height() - initial_phase_inner_sizes.height; + + let initial_phase_inner_sizes_with_flex = + initial_phase_flex_grows + .values() + .fold(initial_phase_inner_sizes, |mut acc, f| { + let flex_grow_per = f.get() / flex_grows.get() * 100.; + + match flex_axis { + AlignAxis::Height => { + let size = flex_available_height / 100. * flex_grow_per; + acc.height += size; + } + AlignAxis::Width => { + let size = flex_available_width / 100. * flex_grow_per; + acc.width += size; + } + } + + acc + }); + + if needs_initial_phase { if parent_node.main_alignment.is_not_start() { // Adjust the available and inner areas of the Main axis Self::shrink_area_to_fit_when_unbounded( @@ -410,7 +468,7 @@ where Self::align_content( available_area, &initial_phase_inner_area, - &initial_phase_inner_sizes, + &initial_phase_inner_sizes_with_flex, &parent_node.main_alignment, &parent_node.direction, AlignmentDirection::Main, @@ -442,6 +500,25 @@ where let mut adapted_available_area = *available_area; + if parent_node.content.is_flex() { + let flex_grow = initial_phase_flex_grows.get(&child_id); + + if let Some(flex_grow) = flex_grow { + let flex_grow_per = flex_grow.get() / flex_grows.get() * 100.; + + match flex_axis { + AlignAxis::Height => { + let size = flex_available_height / 100. * flex_grow_per; + adapted_available_area.size.height = size; + } + AlignAxis::Width => { + let size = flex_available_width / 100. * flex_grow_per; + adapted_available_area.size.width = size; + } + } + } + } + // Only the stacked children will be aligned if parent_node.main_alignment.is_spaced() && !child_data.position.is_absolute() { // Align the Main axis if necessary @@ -449,7 +526,7 @@ where AlignmentDirection::Main, &mut adapted_available_area, &initial_available_area, - &initial_phase_inner_sizes, + &initial_phase_inner_sizes_with_flex, &parent_node.main_alignment, &parent_node.direction, non_absolute_children_len, @@ -492,11 +569,13 @@ where Self::stack_child( available_area, parent_node, + &child_data, area, inner_area, inner_sizes, &child_areas.area, is_last_child, + Phase::Final, ); } @@ -612,11 +691,13 @@ where fn stack_child( available_area: &mut Area, parent_node: &Node, + child_node: &Node, parent_area: &mut Area, inner_area: &mut Area, inner_sizes: &mut Size2D, child_area: &Area, is_last_sibiling: bool, + phase: Phase, ) { // Only apply the spacing to elements after `i > 0` and `i < len - 1` let spacing = (!is_last_sibiling) @@ -630,7 +711,10 @@ where available_area.size.width -= child_area.size.width + spacing.get(); inner_sizes.height = child_area.height().max(inner_sizes.height); - inner_sizes.width += child_area.width() + spacing.get(); + inner_sizes.width += spacing.get(); + if !child_node.width.is_flex() || phase == Phase::Final { + inner_sizes.width += child_area.width(); + } // Keep the biggest height if parent_node.height.inner_sized() { @@ -656,7 +740,10 @@ where available_area.size.height -= child_area.size.height + spacing.get(); inner_sizes.width = child_area.width().max(inner_sizes.width); - inner_sizes.height += child_area.height() + spacing.get(); + inner_sizes.height += spacing.get(); + if !child_node.height.is_flex() || phase == Phase::Final { + inner_sizes.height += child_area.height(); + } // Keep the biggest width if parent_node.width.inner_sized() { diff --git a/crates/torin/src/values/content.rs b/crates/torin/src/values/content.rs index a6193e8b8..c96b38afb 100644 --- a/crates/torin/src/values/content.rs +++ b/crates/torin/src/values/content.rs @@ -3,12 +3,17 @@ pub enum Content { #[default] Normal, Fit, + Flex, } impl Content { pub fn is_fit(&self) -> bool { self == &Self::Fit } + + pub fn is_flex(&self) -> bool { + self == &Self::Flex + } } impl Content { @@ -16,6 +21,7 @@ impl Content { match self { Self::Normal => "normal".to_owned(), Self::Fit => "fit".to_owned(), + Self::Flex => "flex".to_owned(), } } } diff --git a/crates/torin/src/values/size.rs b/crates/torin/src/values/size.rs index 2c1c347b2..066cd97ac 100644 --- a/crates/torin/src/values/size.rs +++ b/crates/torin/src/values/size.rs @@ -21,6 +21,7 @@ pub enum Size { RootPercentage(Length), InnerPercentage(Length), DynamicCalculations(Box>), + Flex(Length), } impl Default for Size { @@ -30,6 +31,17 @@ impl Default for Size { } impl Size { + pub fn flex_grow(&self) -> Option { + match self { + Self::Flex(f) => Some(*f), + _ => None, + } + } + + pub fn is_flex(&self) -> bool { + matches!(self, Self::Flex(_)) + } + pub fn inner_sized(&self) -> bool { matches!( self, @@ -58,6 +70,7 @@ impl Size { Size::FillMinimum => "fill-min".to_string(), Size::RootPercentage(p) => format!("{}% of root", p.get()), Size::InnerPercentage(p) => format!("{}% of auto", p.get()), + Size::Flex(f) => format!("flex({}", f.get()), } } @@ -76,14 +89,9 @@ impl Size { run_calculations(calculations.deref(), parent_value, root_value).unwrap_or(0.0), ), Size::Fill => Some(available_parent_value), - Size::FillMinimum => { - if phase == Phase::Initial { - None - } else { - Some(available_parent_value) - } - } + Size::FillMinimum if phase == Phase::Final => Some(available_parent_value), Size::RootPercentage(per) => Some(root_value / 100.0 * per.get()), + Size::Flex(_) if phase == Phase::Final => Some(available_parent_value), _ => None, } } diff --git a/crates/torin/tests/flex.rs b/crates/torin/tests/flex.rs new file mode 100644 index 000000000..d5fcd0902 --- /dev/null +++ b/crates/torin/tests/flex.rs @@ -0,0 +1,321 @@ +use euclid::Length; +use torin::{ + prelude::*, + test_utils::*, +}; + +#[test] +pub fn flex_generic() { + let (mut layout, mut measurer) = test_utils(); + + let mut mocked_dom = TestingDOM::default(); + mocked_dom.add( + 0, + None, + vec![1, 2, 3, 4], + Node::from_size_and_content( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + Content::Flex, + ), + ); + mocked_dom.add( + 1, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Percentage(Length::new(10.)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 2, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(1.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 3, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Pixels(Length::new(50.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 4, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(3.0)), + DirectionMode::Vertical, + ), + ); + + layout.measure( + 0, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1000.0, 1000.0)), + &mut measurer, + &mut mocked_dom, + ); + + assert_eq!( + layout.get(0).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(200.0, 200.0)), + ); + + assert_eq!( + layout.get(1).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(100.0, 20.0)), + ); + assert_eq!( + layout.get(2).unwrap().area, + Rect::new(Point2D::new(0.0, 20.0), Size2D::new(100.0, 32.5)), + ); + assert_eq!( + layout.get(3).unwrap().area, + Rect::new(Point2D::new(0.0, 52.5), Size2D::new(100.0, 50.0)), + ); + assert_eq!( + layout.get(4).unwrap().area, + Rect::new(Point2D::new(0.0, 102.5), Size2D::new(100.0, 97.5)), + ); +} + +#[test] +pub fn flex_under_1_flex_grow() { + let (mut layout, mut measurer) = test_utils(); + + let mut mocked_dom = TestingDOM::default(); + mocked_dom.add( + 0, + None, + vec![1, 2], + Node::from_size_and_content( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + Content::Flex, + ), + ); + mocked_dom.add( + 1, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(0.2)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 2, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(0.5)), + DirectionMode::Vertical, + ), + ); + + layout.measure( + 0, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1000.0, 1000.0)), + &mut measurer, + &mut mocked_dom, + ); + + assert_eq!( + layout.get(0).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(200.0, 200.0)), + ); + + assert_eq!( + layout.get(1).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(100.0, 40.0)), + ); + assert_eq!( + layout.get(2).unwrap().area, + Rect::new(Point2D::new(0.0, 40.0), Size2D::new(100.0, 100.0)), + ); +} + +#[test] +pub fn flex_grow_balance() { + let (mut layout, mut measurer) = test_utils(); + + let mut mocked_dom = TestingDOM::default(); + mocked_dom.add( + 0, + None, + vec![1, 2, 3, 4], + Node::from_size_and_content( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + Content::Flex, + ), + ); + mocked_dom.add( + 1, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(1.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 2, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(2.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 3, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(3.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 4, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(4.0)), + DirectionMode::Vertical, + ), + ); + + layout.measure( + 0, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1000.0, 1000.0)), + &mut measurer, + &mut mocked_dom, + ); + + assert_eq!( + layout.get(0).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(200.0, 200.0)), + ); + + assert_eq!( + layout.get(1).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(100.0, 20.0)), + ); + assert_eq!( + layout.get(2).unwrap().area, + Rect::new(Point2D::new(0.0, 20.0), Size2D::new(100.0, 40.0)), + ); + assert_eq!( + layout.get(3).unwrap().area.round(), + Rect::new(Point2D::new(0.0, 60.0), Size2D::new(100.0, 60.0)), + ); + assert_eq!( + layout.get(4).unwrap().area.round(), + Rect::new(Point2D::new(0.0, 120.0), Size2D::new(100.0, 80.0)), + ); +} + +#[test] +pub fn flex_large_grow_balance() { + let (mut layout, mut measurer) = test_utils(); + + let mut mocked_dom = TestingDOM::default(); + mocked_dom.add( + 0, + None, + vec![1, 2, 3, 4], + Node::from_size_and_content( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + Content::Flex, + ), + ); + mocked_dom.add( + 1, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(5.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 2, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(65.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 3, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(30.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 4, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(100.0)), + Size::Flex(Length::new(100.0)), + DirectionMode::Vertical, + ), + ); + + layout.measure( + 0, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1000.0, 1000.0)), + &mut measurer, + &mut mocked_dom, + ); + + assert_eq!( + layout.get(0).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(200.0, 200.0)), + ); + + assert_eq!( + layout.get(1).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(100.0, 5.0)), + ); + assert_eq!( + layout.get(2).unwrap().area, + Rect::new(Point2D::new(0.0, 5.0), Size2D::new(100.0, 65.0)), + ); + assert_eq!( + layout.get(3).unwrap().area.round(), + Rect::new(Point2D::new(0.0, 70.0), Size2D::new(100.0, 30.0)), + ); + assert_eq!( + layout.get(4).unwrap().area.round(), + Rect::new(Point2D::new(0.0, 100.0), Size2D::new(100.0, 100.0)), + ); +} diff --git a/examples/flex.rs b/examples/flex.rs new file mode 100644 index 000000000..a091c705b --- /dev/null +++ b/examples/flex.rs @@ -0,0 +1,53 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use freya::prelude::*; + +fn main() { + launch(app); +} + +fn app() -> Element { + rsx!( + rect { + height: "100%", + width: "100%", + direction: "horizontal", + content: "flex", + spacing: "4", + padding: "4", + rect { + height: "100%", + width: "10%", + background: "red", + } + rect { + width: "flex", + height: "100%", + background: "orange", + } + rect { + height: "100%", + width: "25", + background: "black", + } + rect { + width: "flex(3)", + height: "100%", + background: "yellow", + } + rect { + width: "flex", + height: "100%", + background: "green", + } + rect { + height: "100%", + width: "30%", + background: "blue", + } + } + ) +} diff --git a/examples/flex_2.rs b/examples/flex_2.rs new file mode 100644 index 000000000..d07c3126e --- /dev/null +++ b/examples/flex_2.rs @@ -0,0 +1,34 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use freya::prelude::*; + +fn main() { + launch(app); +} + +fn app() -> Element { + rsx!( + rect { + width: "100%", + height: "fill", + direction: "horizontal", + main_align: "space-around", + content: "flex", + + rect { + width: "flex(0.5)", + height: "fill", + background: "red", + } + + rect { + width: "120", + height: "fill", + background: "orange", + } + } + ) +} From f8107eb5ae4cad920e35257951f397c9a8f66b8c Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Wed, 20 Nov 2024 17:57:42 +0100 Subject: [PATCH 13/36] feat: Force SVG root element to have the specified size (#850) * feat: Force SVG root element to have the specified size * use new api * chore: Update skia-safe * chore: Fix cargo clippy * chore: Fix cargo clippy * fix: Update mocked svg APIs * fix: Update mocked svg APIs * fix mocked api * fix mocked api * fix mocked api * fix mocked api * chore: Revert changes on the ferris svg --- Cargo.toml | 2 +- crates/core/src/elements/svg.rs | 6 ++++- crates/engine/src/mocked.rs | 40 ++++++++++++++++++++++++++++++-- crates/engine/src/skia.rs | 1 + crates/native-core/src/passes.rs | 5 ++-- rust-toolchain.toml | 2 +- 6 files changed, 48 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 313e95cce..0deac8d48 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,7 @@ dioxus-hot-reload = { version = "0.5", features = ["file_watcher"], default-feat dioxus-router = { version = "0.5", default-features = false } dioxus-clipboard = "0.1" -skia-safe = { version = "0.75.0", features = ["gl", "textlayout", "svg"] } +skia-safe = { version = "0.80.0", features = ["gl", "textlayout", "svg"] } gl = "0.14.0" glutin = "0.32.0" diff --git a/crates/core/src/elements/svg.rs b/crates/core/src/elements/svg.rs index e0685d816..ae2419172 100644 --- a/crates/core/src/elements/svg.rs +++ b/crates/core/src/elements/svg.rs @@ -25,11 +25,15 @@ impl ElementUtils for SvgElement { let x = area.min_x(); let y = area.min_y(); if let Some(svg_data) = &node_style.svg_data { - let svg_dom = svg::Dom::from_bytes(svg_data.as_slice(), font_manager); + let resource_provider = LocalResourceProvider::new(font_manager); + let svg_dom = svg::Dom::from_bytes(svg_data.as_slice(), resource_provider); if let Ok(mut svg_dom) = svg_dom { canvas.save(); canvas.translate((x, y)); svg_dom.set_container_size((area.width() as i32, area.height() as i32)); + let mut root = svg_dom.root(); + root.set_width(svg::Length::new(100.0, svg::LengthUnit::Percentage)); + root.set_height(svg::Length::new(100.0, svg::LengthUnit::Percentage)); svg_dom.render(canvas); canvas.restore(); } diff --git a/crates/engine/src/mocked.rs b/crates/engine/src/mocked.rs index 3ba169335..27f15a925 100644 --- a/crates/engine/src/mocked.rs +++ b/crates/engine/src/mocked.rs @@ -1468,14 +1468,38 @@ pub enum BlurStyle { pub mod svg { use super::{ Canvas, - FontMgr, + LocalResourceProvider, Size, }; + pub enum LengthUnit { + Percentage, + } + + pub struct Length; + + impl Length { + pub fn new(value: f32, unit: LengthUnit) -> Self { + unimplemented!("This is mocked") + } + } + + pub struct SvgNode; + + impl SvgNode { + pub fn set_width(&mut self, _width: Length) { + unimplemented!("This is mocked") + } + + pub fn set_height(&mut self, _height: Length) { + unimplemented!("This is mocked") + } + } + pub struct Dom; impl Dom { - pub fn from_bytes(_bytes: &[u8], font_mgr: &FontMgr) -> Result { + pub fn from_bytes(_bytes: &[u8], provider: LocalResourceProvider) -> Result { unimplemented!("This is mocked") } @@ -1486,6 +1510,10 @@ pub mod svg { pub fn render(&self, _canvas: &Canvas) { unimplemented!("This is mocked") } + + pub fn root(&self) -> SvgNode { + unimplemented!("This is mocked") + } } } @@ -1751,3 +1779,11 @@ pub enum EncodedImageFormat { AVIF = 12, JPEGXL = 13, } + +pub struct LocalResourceProvider; + +impl LocalResourceProvider { + pub fn new(font_mgr: &FontMgr) -> Self { + unimplemented!("This is mocked") + } +} diff --git a/crates/engine/src/skia.rs b/crates/engine/src/skia.rs index c9c73a9b5..e8eb0ad52 100644 --- a/crates/engine/src/skia.rs +++ b/crates/engine/src/skia.rs @@ -24,6 +24,7 @@ pub use skia_safe::{ set_resource_cache_total_bytes_limit, }, path::ArcSize, + resources::LocalResourceProvider, rrect::Corner, runtime_effect::Uniform, surfaces::raster_n32_premul, diff --git a/crates/native-core/src/passes.rs b/crates/native-core/src/passes.rs index 11b4ca049..a8f84bd2a 100644 --- a/crates/native-core/src/passes.rs +++ b/crates/native-core/src/passes.rs @@ -61,9 +61,8 @@ impl DirtyNodes { } pub fn pop(&mut self) -> Option { - self.nodes_dirty.iter().next().copied().map(|id| { - self.nodes_dirty.remove(&id); - id + self.nodes_dirty.iter().next().copied().inspect(|id| { + self.nodes_dirty.remove(id); }) } } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 94cbe48dd..8fc77ba56 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "1.80.1" +channel = "1.82.0" profile = "default" \ No newline at end of file From ff0c29f8ca7f042ba9dbeb0e79b298a14f1b8ab0 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Fri, 22 Nov 2024 14:29:30 +0100 Subject: [PATCH 14/36] chore: Fmt and fix clippy warnings from 1.82 --- crates/core/src/render/compositor.rs | 6 +-- crates/state/tests/parse_focusable.rs | 1 - crates/torin/tests/alignment.rs | 2 +- crates/torin/tests/size.rs | 38 +++++++------------ examples/documents_editor.rs | 2 +- examples/gamepad_focus.rs | 54 ++++++++++++--------------- examples/gamepad_trace.rs | 13 +++---- examples/mouse.rs | 4 +- examples/website.rs | 2 +- 9 files changed, 51 insertions(+), 71 deletions(-) diff --git a/crates/core/src/render/compositor.rs b/crates/core/src/render/compositor.rs index 63c5e6800..734cc725f 100644 --- a/crates/core/src/render/compositor.rs +++ b/crates/core/src/render/compositor.rs @@ -273,10 +273,10 @@ mod test { // Process what nodes need to be rendered let rendering_layers = compositor.run( - &mut *compositor_dirty_nodes, - &mut *compositor_dirty_area, + &mut compositor_dirty_nodes, + &mut compositor_dirty_area, &mut compositor_cache, - &*layers, + &layers, &mut dirty_layers, &layout, rdom, diff --git a/crates/state/tests/parse_focusable.rs b/crates/state/tests/parse_focusable.rs index 62ae1d9c9..27832e9a7 100644 --- a/crates/state/tests/parse_focusable.rs +++ b/crates/state/tests/parse_focusable.rs @@ -1,4 +1,3 @@ -use freya_engine::prelude::*; use freya_node_state::{ Focusable, Parse, diff --git a/crates/torin/tests/alignment.rs b/crates/torin/tests/alignment.rs index 40889d4c1..536a807cc 100644 --- a/crates/torin/tests/alignment.rs +++ b/crates/torin/tests/alignment.rs @@ -627,7 +627,7 @@ pub fn alignment_with_absolute_child() { Node::from_size_and_position( Size::Pixels(Length::new(100.)), Size::Pixels(Length::new(100.)), - Position::Absolute(Box::new(AbsolutePosition::default())), + Position::Absolute(Box::default()), ), ); mocked_dom.add( diff --git a/crates/torin/tests/size.rs b/crates/torin/tests/size.rs index f7e89a96a..92e21b140 100644 --- a/crates/torin/tests/size.rs +++ b/crates/torin/tests/size.rs @@ -784,7 +784,7 @@ pub fn test_calc() { assert_eq!( run_calculations( - &vec![DynamicCalculation::Pixels(10.0)], + &[DynamicCalculation::Pixels(10.0)], PARENT_VALUE, PARENT_VALUE ), @@ -793,7 +793,7 @@ pub fn test_calc() { assert_eq!( run_calculations( - &vec![DynamicCalculation::Percentage(87.5)], + &[DynamicCalculation::Percentage(87.5)], PARENT_VALUE, PARENT_VALUE ), @@ -802,13 +802,11 @@ pub fn test_calc() { assert_eq!( run_calculations( - &vec![ - DynamicCalculation::Pixels(10.0), + &[DynamicCalculation::Pixels(10.0), DynamicCalculation::Add, DynamicCalculation::Pixels(20.0), DynamicCalculation::Mul, - DynamicCalculation::Percentage(50.0), - ], + DynamicCalculation::Percentage(50.0)], PARENT_VALUE, PARENT_VALUE ), @@ -817,8 +815,7 @@ pub fn test_calc() { assert_eq!( run_calculations( - &vec![ - DynamicCalculation::Pixels(10.0), + &[DynamicCalculation::Pixels(10.0), DynamicCalculation::Add, DynamicCalculation::Percentage(10.0), DynamicCalculation::Add, @@ -828,8 +825,7 @@ pub fn test_calc() { DynamicCalculation::Add, DynamicCalculation::Pixels(75.0), DynamicCalculation::Mul, - DynamicCalculation::Pixels(2.0), - ], + DynamicCalculation::Pixels(2.0)], PARENT_VALUE, PARENT_VALUE ), @@ -838,10 +834,8 @@ pub fn test_calc() { assert_eq!( run_calculations( - &vec![ - DynamicCalculation::Pixels(10.0), - DynamicCalculation::Pixels(20.0), - ], + &[DynamicCalculation::Pixels(10.0), + DynamicCalculation::Pixels(20.0)], PARENT_VALUE, PARENT_VALUE ), @@ -850,7 +844,7 @@ pub fn test_calc() { assert_eq!( run_calculations( - &vec![DynamicCalculation::Pixels(10.0), DynamicCalculation::Add], + &[DynamicCalculation::Pixels(10.0), DynamicCalculation::Add], PARENT_VALUE, PARENT_VALUE ), @@ -859,7 +853,7 @@ pub fn test_calc() { assert_eq!( run_calculations( - &vec![DynamicCalculation::Add, DynamicCalculation::Pixels(10.0)], + &[DynamicCalculation::Add, DynamicCalculation::Pixels(10.0)], PARENT_VALUE, PARENT_VALUE ), @@ -868,12 +862,10 @@ pub fn test_calc() { assert_eq!( run_calculations( - &vec![ - DynamicCalculation::Pixels(10.0), + &[DynamicCalculation::Pixels(10.0), DynamicCalculation::Add, DynamicCalculation::Add, - DynamicCalculation::Pixels(10.0) - ], + DynamicCalculation::Pixels(10.0)], PARENT_VALUE, PARENT_VALUE ), @@ -882,11 +874,9 @@ pub fn test_calc() { assert_eq!( run_calculations( - &vec![ - DynamicCalculation::Percentage(50.0), + &[DynamicCalculation::Percentage(50.0), DynamicCalculation::Sub, - DynamicCalculation::RootPercentage(20.0) - ], + DynamicCalculation::RootPercentage(20.0)], PARENT_VALUE, PARENT_VALUE ), diff --git a/examples/documents_editor.rs b/examples/documents_editor.rs index 3929f5cb3..eb0be866f 100644 --- a/examples/documents_editor.rs +++ b/examples/documents_editor.rs @@ -266,7 +266,7 @@ fn DocumentView(path: ReadOnlySignal) -> Element { } } -static LOREM_IPSUM: &'static str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; +static LOREM_IPSUM: &str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."; #[component] fn DocumentEdit(path: String) -> Element { diff --git a/examples/gamepad_focus.rs b/examples/gamepad_focus.rs index eb436e691..20aa32b62 100644 --- a/examples/gamepad_focus.rs +++ b/examples/gamepad_focus.rs @@ -22,7 +22,7 @@ use gilrs::{ fn main() { launch_cfg( app, - LaunchConfig::<()>::new().with_plugin(GamePadPlugin::default()), + LaunchConfig::<()>::new().with_plugin(GamePadPlugin), ) } @@ -38,32 +38,29 @@ impl GamePadPlugin { loop { while let Some(ev) = gilrs_instance.next_event() { - match ev.event { - EventType::ButtonReleased(_, code) => { - // NOTE: You might need to tweak these codes - match code.into_u32() { - 4 => { - handle.send_event_loop_event( - EventMessage::FocusPrevAccessibilityNode, - ); - } - 6 => { - handle.send_event_loop_event( - EventMessage::FocusNextAccessibilityNode, - ); - } - 13 => { - handle.send_platform_event(PlatformEvent::Keyboard { - name: EventName::KeyDown, - key: Key::Enter, - code: Code::Enter, - modifiers: Modifiers::default(), - }); - } - _ => {} + if let EventType::ButtonReleased(_, code) = ev.event { + // NOTE: You might need to tweak these codes + match code.into_u32() { + 4 => { + handle.send_event_loop_event( + EventMessage::FocusPrevAccessibilityNode, + ); } + 6 => { + handle.send_event_loop_event( + EventMessage::FocusNextAccessibilityNode, + ); + } + 13 => { + handle.send_platform_event(PlatformEvent::Keyboard { + name: EventName::KeyDown, + key: Key::Enter, + code: Code::Enter, + modifiers: Modifiers::default(), + }); + } + _ => {} } - _ => {} } } } @@ -73,11 +70,8 @@ impl GamePadPlugin { impl FreyaPlugin for GamePadPlugin { fn on_event(&mut self, event: &PluginEvent, handle: PluginHandle) { - match event { - PluginEvent::WindowCreated(_) => { - Self::listen_gamepad(handle); - } - _ => {} + if let PluginEvent::WindowCreated(_) = event { + Self::listen_gamepad(handle); } } } diff --git a/examples/gamepad_trace.rs b/examples/gamepad_trace.rs index 038a8349e..23dadce49 100644 --- a/examples/gamepad_trace.rs +++ b/examples/gamepad_trace.rs @@ -28,7 +28,7 @@ use gilrs::{ fn main() { launch_cfg( app, - LaunchConfig::<()>::new().with_plugin(GamePadPlugin::default()), + LaunchConfig::<()>::new().with_plugin(GamePadPlugin), ) } @@ -61,7 +61,7 @@ impl GamePadPlugin { } if diff_x != 0.0 { - x += diff_x as f64 * 10.; + x += diff_x * 10.; handle.send_platform_event(PlatformEvent::Mouse { name: EventName::MouseMove, cursor: (x, y).into(), @@ -70,7 +70,7 @@ impl GamePadPlugin { } if diff_x != 0.0 { - y -= diff_y as f64 * 10.; + y -= diff_y * 10.; handle.send_platform_event(PlatformEvent::Mouse { name: EventName::MouseMove, cursor: (x, y).into(), @@ -95,11 +95,8 @@ impl GamePadPlugin { impl FreyaPlugin for GamePadPlugin { fn on_event(&mut self, event: &PluginEvent, handle: PluginHandle) { - match event { - PluginEvent::WindowCreated(_) => { - Self::listen_gamepad(handle); - } - _ => {} + if let PluginEvent::WindowCreated(_) = event { + Self::listen_gamepad(handle); } } } diff --git a/examples/mouse.rs b/examples/mouse.rs index 3d07ae9f5..8018a5450 100644 --- a/examples/mouse.rs +++ b/examples/mouse.rs @@ -10,8 +10,8 @@ fn main() { } fn app() -> Element { - let mut cursor_pos_over = use_signal(|| CursorPoint::default()); - let mut cursor_pos_click = use_signal(|| CursorPoint::default()); + let mut cursor_pos_over = use_signal(CursorPoint::default); + let mut cursor_pos_click = use_signal(CursorPoint::default); let onmousemove = move |e: MouseEvent| { let cursor_pos = e.get_screen_coordinates(); diff --git a/examples/website.rs b/examples/website.rs index 6796ddcc1..cbb56cb29 100644 --- a/examples/website.rs +++ b/examples/website.rs @@ -353,7 +353,7 @@ fn Code() -> Element { .highlight(&rust_config, CODE.as_bytes(), None, |_| None) .unwrap(); - let rope = Rope::from_str(&CODE); + let rope = Rope::from_str(CODE); let mut syntax_blocks = SyntaxBlocks::default(); From 6432c09664db5ed67bef44656d51874b03f6558a Mon Sep 17 00:00:00 2001 From: marc2332 Date: Fri, 22 Nov 2024 14:33:59 +0100 Subject: [PATCH 15/36] chore: More formatting --- crates/torin/tests/size.rs | 30 ++++++++++++++++++++---------- examples/gamepad_focus.rs | 5 +---- examples/gamepad_trace.rs | 5 +---- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/crates/torin/tests/size.rs b/crates/torin/tests/size.rs index 92e21b140..1e4750d58 100644 --- a/crates/torin/tests/size.rs +++ b/crates/torin/tests/size.rs @@ -802,11 +802,13 @@ pub fn test_calc() { assert_eq!( run_calculations( - &[DynamicCalculation::Pixels(10.0), + &[ + DynamicCalculation::Pixels(10.0), DynamicCalculation::Add, DynamicCalculation::Pixels(20.0), DynamicCalculation::Mul, - DynamicCalculation::Percentage(50.0)], + DynamicCalculation::Percentage(50.0) + ], PARENT_VALUE, PARENT_VALUE ), @@ -815,7 +817,8 @@ pub fn test_calc() { assert_eq!( run_calculations( - &[DynamicCalculation::Pixels(10.0), + &[ + DynamicCalculation::Pixels(10.0), DynamicCalculation::Add, DynamicCalculation::Percentage(10.0), DynamicCalculation::Add, @@ -825,7 +828,8 @@ pub fn test_calc() { DynamicCalculation::Add, DynamicCalculation::Pixels(75.0), DynamicCalculation::Mul, - DynamicCalculation::Pixels(2.0)], + DynamicCalculation::Pixels(2.0) + ], PARENT_VALUE, PARENT_VALUE ), @@ -834,8 +838,10 @@ pub fn test_calc() { assert_eq!( run_calculations( - &[DynamicCalculation::Pixels(10.0), - DynamicCalculation::Pixels(20.0)], + &[ + DynamicCalculation::Pixels(10.0), + DynamicCalculation::Pixels(20.0) + ], PARENT_VALUE, PARENT_VALUE ), @@ -862,10 +868,12 @@ pub fn test_calc() { assert_eq!( run_calculations( - &[DynamicCalculation::Pixels(10.0), + &[ + DynamicCalculation::Pixels(10.0), DynamicCalculation::Add, DynamicCalculation::Add, - DynamicCalculation::Pixels(10.0)], + DynamicCalculation::Pixels(10.0) + ], PARENT_VALUE, PARENT_VALUE ), @@ -874,9 +882,11 @@ pub fn test_calc() { assert_eq!( run_calculations( - &[DynamicCalculation::Percentage(50.0), + &[ + DynamicCalculation::Percentage(50.0), DynamicCalculation::Sub, - DynamicCalculation::RootPercentage(20.0)], + DynamicCalculation::RootPercentage(20.0) + ], PARENT_VALUE, PARENT_VALUE ), diff --git a/examples/gamepad_focus.rs b/examples/gamepad_focus.rs index 20aa32b62..405b95972 100644 --- a/examples/gamepad_focus.rs +++ b/examples/gamepad_focus.rs @@ -20,10 +20,7 @@ use gilrs::{ }; fn main() { - launch_cfg( - app, - LaunchConfig::<()>::new().with_plugin(GamePadPlugin), - ) + launch_cfg(app, LaunchConfig::<()>::new().with_plugin(GamePadPlugin)) } #[derive(Default)] diff --git a/examples/gamepad_trace.rs b/examples/gamepad_trace.rs index 23dadce49..3dd20ce70 100644 --- a/examples/gamepad_trace.rs +++ b/examples/gamepad_trace.rs @@ -26,10 +26,7 @@ use gilrs::{ }; fn main() { - launch_cfg( - app, - LaunchConfig::<()>::new().with_plugin(GamePadPlugin), - ) + launch_cfg(app, LaunchConfig::<()>::new().with_plugin(GamePadPlugin)) } #[derive(Default)] From cd7bb58179353c47d4b8164e6b29b2d390e36b2b Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Fri, 22 Nov 2024 18:45:22 +0100 Subject: [PATCH 16/36] refactor: Remove `DirtyNodesResults` from `native-core` (#999) * refactor: Remove `DirtyNodesResult` from `native-core` * fmt --- crates/core/src/dom/doms.rs | 2 +- crates/native-core/Cargo.toml | 1 - crates/native-core/src/lib.rs | 10 +--------- crates/native-core/src/passes.rs | 10 +--------- crates/native-core/src/real_dom.rs | 23 ++--------------------- 5 files changed, 5 insertions(+), 41 deletions(-) diff --git a/crates/core/src/dom/doms.rs b/crates/core/src/dom/doms.rs index d93c5cf17..c1e597046 100644 --- a/crates/core/src/dom/doms.rs +++ b/crates/core/src/dom/doms.rs @@ -251,7 +251,7 @@ impl FreyaDOM { ctx.insert(self.accessibility_generator.clone()); // Update the Node's states - let (_, diff) = self.rdom.update_state(ctx); + let diff = self.rdom.update_state(ctx); let must_repaint = !diff.is_empty(); let must_relayout = !self.layout().get_dirty_nodes().is_empty(); diff --git a/crates/native-core/Cargo.toml b/crates/native-core/Cargo.toml index 84be2247e..072aeed33 100644 --- a/crates/native-core/Cargo.toml +++ b/crates/native-core/Cargo.toml @@ -18,7 +18,6 @@ smallvec = { workspace = true } rustc-hash = { workspace = true } anymap = "1.0.0-beta.2" parking_lot = { version = "0.12.1", features = ["send_guard"] } -dashmap = "6.0.0" shipyard = { workspace = true } [dev-dependencies] diff --git a/crates/native-core/src/lib.rs b/crates/native-core/src/lib.rs index 2501f2df1..efd2c6788 100644 --- a/crates/native-core/src/lib.rs +++ b/crates/native-core/src/lib.rs @@ -1,10 +1,6 @@ -use std::{ - any::Any, - hash::BuildHasherDefault, -}; +use std::any::Any; use node_ref::NodeMask; -use rustc_hash::FxHasher; pub mod attributes; pub mod dioxus; @@ -65,9 +61,5 @@ pub mod prelude { }; } -/// A map that can be sent between threads -pub type FxDashMap = dashmap::DashMap>; -/// A set that can be sent between threads -pub type FxDashSet = dashmap::DashSet>; /// A map of types that can be sent between threads pub type SendAnyMap = anymap::Map; diff --git a/crates/native-core/src/passes.rs b/crates/native-core/src/passes.rs index a8f84bd2a..33bb9602d 100644 --- a/crates/native-core/src/passes.rs +++ b/crates/native-core/src/passes.rs @@ -33,10 +33,7 @@ use crate::{ NodeMaskBuilder, NodeView, }, - real_dom::{ - DirtyNodesResult, - SendAnyMapWrapper, - }, + real_dom::SendAnyMapWrapper, tree::{ TreeRef, TreeRefView, @@ -212,7 +209,6 @@ fn pass_direction>() -> PassDirection pub struct RunPassView<'a, V: FromAnyValue + Send + Sync = ()> { pub tree: TreeRefView<'a>, pub node_type: View<'a, NodeType>, - dirty_nodes_result: UniqueView<'a, DirtyNodesResult>, node_states: UniqueView<'a, DirtyNodeStates>, any_map: UniqueView<'a, SendAnyMapWrapper>, } @@ -229,7 +225,6 @@ pub fn run_pass( ) { let RunPassView { tree, - dirty_nodes_result: nodes_updated, node_states: dirty, any_map: ctx, .. @@ -239,7 +234,6 @@ pub fn run_pass( PassDirection::ParentToChild => { while let Some((height, id)) = dirty.pop_front(type_id) { if (update_node)(id, ctx, height) { - nodes_updated.insert(id); dependants.mark_dirty(&dirty, id, &tree, height); } } @@ -247,7 +241,6 @@ pub fn run_pass( PassDirection::ChildToParent => { while let Some((height, id)) = dirty.pop_back(type_id) { if (update_node)(id, ctx, height) { - nodes_updated.insert(id); dependants.mark_dirty(&dirty, id, &tree, height); } } @@ -255,7 +248,6 @@ pub fn run_pass( PassDirection::AnyOrder => { while let Some((height, id)) = dirty.pop_back(type_id) { if (update_node)(id, ctx, height) { - nodes_updated.insert(id); dependants.mark_dirty(&dirty, id, &tree, height); } } diff --git a/crates/native-core/src/real_dom.rs b/crates/native-core/src/real_dom.rs index 996b1b7c6..a2d16e841 100644 --- a/crates/native-core/src/real_dom.rs +++ b/crates/native-core/src/real_dom.rs @@ -57,7 +57,6 @@ use crate::{ TreeRef, TreeRefView, }, - FxDashSet, NodeId, SendAnyMap, }; @@ -74,18 +73,6 @@ impl Deref for SendAnyMapWrapper { } } -/// The nodes that were changed when updating the state of the RealDom -#[derive(Unique, Default)] -pub(crate) struct DirtyNodesResult(FxDashSet); - -impl Deref for DirtyNodesResult { - type Target = FxDashSet; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - /// The nodes that have been marked as dirty in the RealDom pub(crate) struct NodesDirty { passes_updated: FxHashMap>, @@ -330,10 +317,7 @@ impl RealDom { } /// Update the state of the dom, after appling some mutations. This will keep the nodes in the dom up to date with their VNode counterparts. - pub fn update_state( - &mut self, - ctx: SendAnyMap, - ) -> (FxDashSet, FxHashMap) { + pub fn update_state(&mut self, ctx: SendAnyMap) -> FxHashMap { let passes = std::mem::take(&mut self.dirty_nodes.passes_updated); let nodes_updated = std::mem::take(&mut self.dirty_nodes.nodes_updated); @@ -353,13 +337,10 @@ impl RealDom { let _ = self.world.remove_unique::(); self.world.add_unique(dirty_nodes); self.world.add_unique(SendAnyMapWrapper(ctx)); - self.world.add_unique(DirtyNodesResult::default()); self.workload.run_with_world(&self.world).unwrap(); - let dirty = self.world.remove_unique::().unwrap(); - - (dirty.0, nodes_updated) + nodes_updated } /// Traverses the dom in a depth first manner, From 91a42d98a249b8eb4d45fb247f520482bcb4c179 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sat, 23 Nov 2024 16:24:34 +0100 Subject: [PATCH 17/36] refactor: Remove `anymap` (#1001) * refactor: Remove `anymap` * small improvement --- crates/native-core-macro/src/lib.rs | 2 +- crates/native-core/Cargo.toml | 1 - crates/native-core/src/lib.rs | 35 +++++++++++++++++++++++++++-- crates/native-core/src/passes.rs | 2 +- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/crates/native-core-macro/src/lib.rs b/crates/native-core-macro/src/lib.rs index 0935dec47..f866deaa3 100644 --- a/crates/native-core-macro/src/lib.rs +++ b/crates/native-core-macro/src/lib.rs @@ -345,7 +345,7 @@ pub fn partial_derive_state(_: TokenStream, input: TokenStream) -> TokenStream { let (#(#split_views,)*) = data; let tree = run_view.tree.clone(); let node_types = run_view.node_type.clone(); - freya_native_core::prelude::run_pass(type_id, dependants.clone(), pass_direction, run_view, |id, context, height| { + freya_native_core::prelude::run_pass(type_id, &dependants, pass_direction, run_view, |id, context, height| { let node_data: &NodeType<_> = node_types.get(id).unwrap_or_else(|err| panic!("Failed to get node type {:?}", err)); if node_data.is_text() { return false; diff --git a/crates/native-core/Cargo.toml b/crates/native-core/Cargo.toml index 072aeed33..9ba0ec154 100644 --- a/crates/native-core/Cargo.toml +++ b/crates/native-core/Cargo.toml @@ -16,7 +16,6 @@ dioxus-core = { workspace = true} smallvec = { workspace = true } rustc-hash = { workspace = true } -anymap = "1.0.0-beta.2" parking_lot = { version = "0.12.1", features = ["send_guard"] } shipyard = { workspace = true } diff --git a/crates/native-core/src/lib.rs b/crates/native-core/src/lib.rs index efd2c6788..0cf2b033b 100644 --- a/crates/native-core/src/lib.rs +++ b/crates/native-core/src/lib.rs @@ -1,4 +1,7 @@ -use std::any::Any; +use std::any::{ + Any, + TypeId, +}; use node_ref::NodeMask; @@ -12,6 +15,7 @@ pub mod real_dom; pub mod tags; pub mod tree; +use rustc_hash::FxHashMap; pub use shipyard::EntityId as NodeId; pub mod exports { @@ -62,4 +66,31 @@ pub mod prelude { } /// A map of types that can be sent between threads -pub type SendAnyMap = anymap::Map; +#[derive(Debug)] +pub struct SendAnyMap { + map: FxHashMap>, +} + +impl Default for SendAnyMap { + fn default() -> Self { + Self::new() + } +} + +impl SendAnyMap { + pub fn new() -> Self { + Self { + map: FxHashMap::default(), + } + } + + pub fn get(&self) -> Option<&T> { + self.map + .get(&TypeId::of::()) + .and_then(|any| any.downcast_ref::()) + } + + pub fn insert(&mut self, value: T) { + self.map.insert(TypeId::of::(), Box::new(value)); + } +} diff --git a/crates/native-core/src/passes.rs b/crates/native-core/src/passes.rs index 33bb9602d..65de22f60 100644 --- a/crates/native-core/src/passes.rs +++ b/crates/native-core/src/passes.rs @@ -218,7 +218,7 @@ pub struct RunPassView<'a, V: FromAnyValue + Send + Sync = ()> { #[doc(hidden)] pub fn run_pass( type_id: TypeId, - dependants: Arc, + dependants: &Dependants, pass_direction: PassDirection, view: RunPassView, mut update_node: impl FnMut(NodeId, &SendAnyMap, u16) -> bool, From c57556c7f01ed09b37a93ffb6edbb2d513587b95 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sat, 23 Nov 2024 16:46:56 +0100 Subject: [PATCH 18/36] fix: Use paragraph's full width if text align is non-start (#998) --- crates/core/src/elements/paragraph.rs | 5 +++-- crates/core/src/render/skia_measurer.rs | 21 ++++++++++----------- crates/core/src/render/utils/label.rs | 13 +++++++++++-- crates/core/src/render/utils/paragraph.rs | 17 +++++++++++++++-- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/crates/core/src/elements/paragraph.rs b/crates/core/src/elements/paragraph.rs index 05effff7e..a637dad03 100644 --- a/crates/core/src/elements/paragraph.rs +++ b/crates/core/src/elements/paragraph.rs @@ -37,6 +37,7 @@ use crate::{ create_paragraph, draw_cursor, draw_cursor_highlights, + ParagraphData, }, }; @@ -139,7 +140,7 @@ impl ElementUtils for ParagraphElement { }; if node_cursor_state.position.is_some() { - let paragraph = create_paragraph( + let ParagraphData { paragraph, .. } = create_paragraph( node_ref, &area.size, font_collection, @@ -177,7 +178,7 @@ impl ElementUtils for ParagraphElement { false } - fn drawing_area( + fn element_drawing_area( &self, layout_node: &LayoutNode, node_ref: &DioxusNode, diff --git a/crates/core/src/render/skia_measurer.rs b/crates/core/src/render/skia_measurer.rs index b3a03a207..55eec4ce1 100644 --- a/crates/core/src/render/skia_measurer.rs +++ b/crates/core/src/render/skia_measurer.rs @@ -27,7 +27,10 @@ use super::{ create_label, create_paragraph, }; -use crate::dom::*; +use crate::{ + dom::*, + render::ParagraphData, +}; /// Provides Text measurements using Skia APIs like SkParagraph pub struct SkiaMeasurer<'a> { @@ -65,21 +68,19 @@ impl<'a> LayoutMeasurer for SkiaMeasurer<'a> { match &*node_type { NodeType::Element(ElementNode { tag, .. }) if tag == &TagName::Label => { - let label = create_label( + let ParagraphData { paragraph, size } = create_label( &node, area_size, self.font_collection, self.default_fonts, self.scale_factor, ); - let height = label.height(); - let res = Size2D::new(label.longest_line(), height); let mut map = SendAnyMap::new(); - map.insert(CachedParagraph(label, height)); - Some((res, Arc::new(map))) + map.insert(CachedParagraph(paragraph, size.height)); + Some((size, Arc::new(map))) } NodeType::Element(ElementNode { tag, .. }) if tag == &TagName::Paragraph => { - let paragraph = create_paragraph( + let ParagraphData { paragraph, size } = create_paragraph( &node, area_size, self.font_collection, @@ -87,11 +88,9 @@ impl<'a> LayoutMeasurer for SkiaMeasurer<'a> { self.default_fonts, self.scale_factor, ); - let height = paragraph.height(); - let res = Size2D::new(paragraph.longest_line(), height); let mut map = SendAnyMap::new(); - map.insert(CachedParagraph(paragraph, height)); - Some((res, Arc::new(map))) + map.insert(CachedParagraph(paragraph, size.height)); + Some((size, Arc::new(map))) } _ => None, } diff --git a/crates/core/src/render/utils/label.rs b/crates/core/src/render/utils/label.rs index 1ed471caa..bc20297a1 100644 --- a/crates/core/src/render/utils/label.rs +++ b/crates/core/src/render/utils/label.rs @@ -6,6 +6,7 @@ use freya_native_core::{ use freya_node_state::FontStyleState; use torin::prelude::Size2D; +use super::ParagraphData; use crate::dom::*; pub fn create_label( @@ -14,7 +15,7 @@ pub fn create_label( font_collection: &FontCollection, default_font_family: &[String], scale_factor: f32, -) -> Paragraph { +) -> ParagraphData { let font_style = &*node.get::().unwrap(); let mut paragraph_style = ParagraphStyle::default(); @@ -48,5 +49,13 @@ pub fn create_label( }, ); - paragraph + let width = match font_style.text_align { + TextAlign::Start | TextAlign::Left => paragraph.longest_line(), + _ => paragraph.max_width(), + }; + + ParagraphData { + size: Size2D::new(width, paragraph.height()), + paragraph, + } } diff --git a/crates/core/src/render/utils/paragraph.rs b/crates/core/src/render/utils/paragraph.rs index c4b84dabf..64c9c966a 100644 --- a/crates/core/src/render/utils/paragraph.rs +++ b/crates/core/src/render/utils/paragraph.rs @@ -19,6 +19,11 @@ use torin::prelude::{ use crate::dom::DioxusNode; +pub struct ParagraphData { + pub paragraph: Paragraph, + pub size: Size2D, +} + /// Compose a new SkParagraph pub fn create_paragraph( node: &DioxusNode, @@ -27,7 +32,7 @@ pub fn create_paragraph( is_rendering: bool, default_font_family: &[String], scale_factor: f32, -) -> Paragraph { +) -> ParagraphData { let font_style = &*node.get::().unwrap(); let mut paragraph_style = ParagraphStyle::default(); @@ -82,7 +87,15 @@ pub fn create_paragraph( }, ); - paragraph + let width = match font_style.text_align { + TextAlign::Start | TextAlign::Left => paragraph.longest_line(), + _ => paragraph.max_width(), + }; + + ParagraphData { + size: Size2D::new(width, paragraph.height()), + paragraph, + } } pub fn draw_cursor_highlights( From 2991c5a05118af380a78c56d6ccdfae53dce63fd Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sat, 23 Nov 2024 17:34:34 +0100 Subject: [PATCH 19/36] hotfix: Remove `text_align` from `Button`, `Tab` and `BottomTab` --- crates/components/src/button.rs | 1 - crates/components/src/tabs.rs | 2 -- 2 files changed, 3 deletions(-) diff --git a/crates/components/src/button.rs b/crates/components/src/button.rs index 9ab309b82..a31f07ba5 100644 --- a/crates/components/src/button.rs +++ b/crates/components/src/button.rs @@ -273,7 +273,6 @@ pub fn ButtonBase( border: "{border}", corner_radius: "{corner_radius}", background: "{background}", - text_align: "center", text_height: "disable-least-ascent", main_align: "center", cross_align: "center", diff --git a/crates/components/src/tabs.rs b/crates/components/src/tabs.rs index b056dcd62..bbcb7d8ef 100644 --- a/crates/components/src/tabs.rs +++ b/crates/components/src/tabs.rs @@ -146,7 +146,6 @@ pub fn Tab( a11y_role:"tab", color: "{font_theme.color}", background: "{background}", - text_align: "center", content: "fit", rect { padding: "{padding}", @@ -257,7 +256,6 @@ pub fn BottomTab(children: Element, theme: Option) -> Elemen a11y_role:"tab", color: "{font_theme.color}", background: "{background}", - text_align: "center", padding: "{padding}", main_align: "center", cross_align: "center", From 73558824d06c401809a2fb52ebc85a803f11d487 Mon Sep 17 00:00:00 2001 From: Savchenko Ivan <73419411+Aiving@users.noreply.github.com> Date: Sun, 24 Nov 2024 15:52:27 +0500 Subject: [PATCH 20/36] enhancement: add support for `fill` in `svg` (#797) * add support for `color` in `svg` * fix svg color support & mocked engine * fix mocked engine * format mocked engine using nightly fmt * replace `color` attribute with `fill` in `svg` * make fill atributte optional * i forgor change svg defintion (rip) * format svg with nightly fmt * an attempt to fix svg rendering without `fill` attribute * fixed svg rendering * chore(elements/svg): cover all `Fill` enum patterns fix(docs/color-syntax): `rect` -> `red` feat(docs/attributes/fill): add docs for fill atribute feat(examples/svg-fill): add example for svg with specified fill color * i forgor * Update crates/elements/src/_docs/attributes/fill.md Co-authored-by: Marc Espin * Update skia.rs * fixes * fmt changes * fix mocked engine * Update crates/state/src/style.rs Co-authored-by: Marc Espin * Update crates/state/src/style.rs Co-authored-by: Marc Espin * Update crates/state/src/style.rs Co-authored-by: Marc Espin * Update crates/core/src/elements/svg.rs Co-authored-by: Marc Espin * Update crates/core/src/elements/svg.rs Co-authored-by: Marc Espin * Update crates/state/src/style.rs Co-authored-by: Marc Espin * chore: Add missing color attribute for svg, add attribute display for svg and stroke in devtools, add color, fill & stroke to the import_svg macro * chore: fmt settings.svg --------- Co-authored-by: Marc Espin --- crates/components/src/svg.rs | 17 ++++- crates/core/src/elements/svg.rs | 13 +++- crates/core/src/node.rs | 9 +++ crates/devtools/src/tabs/style.rs | 19 ++++- .../src/_docs/attributes/fill_stroke.md | 21 ++++++ crates/elements/src/definitions.rs | 5 ++ crates/engine/src/mocked.rs | 70 +++++++++++++++++++ crates/engine/src/skia.rs | 3 + crates/native-core/src/attributes.rs | 4 ++ crates/state/src/style.rs | 21 ++++++ examples/settings.svg | 3 + examples/svg_fill.rs | 23 ++++++ 12 files changed, 203 insertions(+), 5 deletions(-) create mode 100644 crates/elements/src/_docs/attributes/fill_stroke.md create mode 100644 examples/settings.svg create mode 100644 examples/svg_fill.rs diff --git a/crates/components/src/svg.rs b/crates/components/src/svg.rs index 7ff681521..70036bb60 100644 --- a/crates/components/src/svg.rs +++ b/crates/components/src/svg.rs @@ -28,11 +28,17 @@ macro_rules! import_svg { pub fn $component_name( #[props(default = $width.to_string())] width: String, #[props(default = $height.to_string())] height: String, + color: Option, + fill: Option, + stroke: Option, ) -> freya::prelude::Element { use freya::prelude::*; let svg_data = static_bytes(include_bytes!($path)); rsx!(svg { + color, + fill, + stroke, width, height, svg_data @@ -43,11 +49,20 @@ macro_rules! import_svg { // Generate a function with the name derived from the file name #[allow(non_snake_case)] #[dioxus::prelude::component] - pub fn $component_name(width: String, height: String) -> freya::prelude::Element { + pub fn $component_name( + width: String, + height: String, + color: Option, + fill: Option, + stroke: Option, + ) -> freya::prelude::Element { use freya::prelude::*; let svg_data = static_bytes(include_bytes!($path)); rsx!(svg { + color, + fill, + stroke, width, height, svg_data diff --git a/crates/core/src/elements/svg.rs b/crates/core/src/elements/svg.rs index ae2419172..8d6b1c5d7 100644 --- a/crates/core/src/elements/svg.rs +++ b/crates/core/src/elements/svg.rs @@ -1,6 +1,9 @@ use freya_engine::prelude::*; use freya_native_core::real_dom::NodeImmutable; -use freya_node_state::StyleState; +use freya_node_state::{ + FontStyleState, + StyleState, +}; use torin::prelude::LayoutNode; use super::utils::ElementUtils; @@ -21,6 +24,7 @@ impl ElementUtils for SvgElement { ) { let area = layout_node.visible_area(); let node_style = &*node_ref.get::().unwrap(); + let font_style = &*node_ref.get::().unwrap(); let x = area.min_x(); let y = area.min_y(); @@ -34,6 +38,13 @@ impl ElementUtils for SvgElement { let mut root = svg_dom.root(); root.set_width(svg::Length::new(100.0, svg::LengthUnit::Percentage)); root.set_height(svg::Length::new(100.0, svg::LengthUnit::Percentage)); + root.set_color(font_style.color); + if let Some(color) = node_style.svg_stroke.as_ref() { + root.set_fill(svg::Paint::from_color(*color)); + } + if let Some(color) = node_style.svg_fill.as_ref() { + root.set_stroke(svg::Paint::from_color(*color)); + } svg_dom.render(canvas); canvas.restore(); } diff --git a/crates/core/src/node.rs b/crates/core/src/node.rs index ef616509e..c01a2822d 100644 --- a/crates/core/src/node.rs +++ b/crates/core/src/node.rs @@ -137,6 +137,14 @@ impl NodeState { ("offset_x", AttributeType::Measure(self.size.offset_x.get())), ("offset_y", AttributeType::Measure(self.size.offset_y.get())), ("content", AttributeType::Content(&self.size.content)), + ( + "fill", + AttributeType::OptionalColor(self.style.svg_fill.map(|color| color.into())), + ), + ( + "svg_stroke", + AttributeType::OptionalColor(self.style.svg_stroke.map(|color| color.into())), + ), ]; let shadows = &self.style.shadows; @@ -161,6 +169,7 @@ impl NodeState { pub enum AttributeType<'a> { Color(Fill), + OptionalColor(Option), Gradient(Fill), Size(&'a Size), Measure(f32), diff --git a/crates/devtools/src/tabs/style.rs b/crates/devtools/src/tabs/style.rs index b79bcfe03..b802b8b59 100644 --- a/crates/devtools/src/tabs/style.rs +++ b/crates/devtools/src/tabs/style.rs @@ -29,8 +29,8 @@ pub fn NodeInspectorStyle(node_id: String) -> Element { width: "100%", spacing: "6", padding: "8 16", - {node.state.attributes().into_iter().enumerate().map(|(i, (name, attr))| { - match attr { + {node.state.attributes().into_iter().enumerate().filter_map(|(i, (name, attr))| { + Some(match attr { AttributeType::Measure(measure) => { rsx!{ Property { @@ -85,6 +85,19 @@ pub fn NodeInspectorStyle(node_id: String) -> Element { } } } + AttributeType::OptionalColor(fill) => { + if let Some(fill) = fill { + rsx!{ + ColorProperty { + key: "{i}", + name: "{name}", + fill: fill.clone() + } + } + } else { + return None; + } + } AttributeType::Gradient(fill) => { rsx!{ GradientProperty { @@ -184,7 +197,7 @@ pub fn NodeInspectorStyle(node_id: String) -> Element { } } } - } + }) })} } ) diff --git a/crates/elements/src/_docs/attributes/fill_stroke.md b/crates/elements/src/_docs/attributes/fill_stroke.md new file mode 100644 index 000000000..04bfe0e30 --- /dev/null +++ b/crates/elements/src/_docs/attributes/fill_stroke.md @@ -0,0 +1,21 @@ +The `fill` and `stroke` attributes allows you to specify the fill or stroke color for the `svg`. + +You can learn about the syntax of this attribute in [`Color Syntax`](crate::_docs::color_syntax). + +### Example + +```rust, no_run +# use freya::prelude::*; +fn app() -> Element { + let svg_content = include_str!("../../../examples/settings.svg"); + + rsx!( + svg { + fill: "red", + width: "100%", + height: "100%", + svg_content, + } + ) +} +``` diff --git a/crates/elements/src/definitions.rs b/crates/elements/src/definitions.rs index 4616f1ae4..06aa85e47 100644 --- a/crates/elements/src/definitions.rs +++ b/crates/elements/src/definitions.rs @@ -858,8 +858,13 @@ builder_constructors! { opacity: String, // Svg + #[doc = include_str!("_docs/attributes/color.md")] + color: String, svg_data: String, svg_content: String, + #[doc = include_str!("_docs/attributes/fill_stroke.md")] + fill: String, + stroke: String, // Accessibility a11y_id: String, diff --git a/crates/engine/src/mocked.rs b/crates/engine/src/mocked.rs index 27f15a925..608bc7bda 100644 --- a/crates/engine/src/mocked.rs +++ b/crates/engine/src/mocked.rs @@ -9,6 +9,9 @@ use std::ops::*; use bitflags::bitflags; use glutin::context::PossiblyCurrentContext; +#[derive(Default, Debug)] +pub struct SaveLayerRec; + #[derive(Clone, Debug, PartialEq, Copy, Eq)] pub struct Color(u32); @@ -649,6 +652,10 @@ impl Paint { unimplemented!("This is mocked") } + pub fn set_blend_mode(&mut self, _mode: BlendMode) -> &mut Self { + unimplemented!("This is mocked") + } + pub fn set_style(&mut self, _style: PaintStyle) -> &mut Self { unimplemented!("This is mocked") } @@ -1085,6 +1092,10 @@ impl Canvas { unimplemented!("This is mocked") } + pub fn draw_paint(&self, _: &Paint) -> &Self { + unimplemented!("This is mocked") + } + pub fn draw_line(&self, _p1: impl Into, _p2: impl Into, _paint: &Paint) -> &Self { unimplemented!("This is mocked") } @@ -1093,6 +1104,10 @@ impl Canvas { unimplemented!("This is mocked") } + pub fn save_layer(&self, layer_rec: &SaveLayerRec) -> usize { + unimplemented!("This is mocked") + } + pub fn save_layer_alpha_f(&self, bounds: impl Into>, alpha: f32) -> usize { unimplemented!("This is mocked") } @@ -1453,6 +1468,40 @@ impl MaskFilter { } } +#[repr(i32)] +#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] +pub enum BlendMode { + Clear = 0, + Src = 1, + Dst = 2, + SrcOver = 3, + DstOver = 4, + SrcIn = 5, + DstIn = 6, + SrcOut = 7, + DstOut = 8, + SrcATop = 9, + DstATop = 10, + Xor = 11, + Plus = 12, + Modulate = 13, + Screen = 14, + Overlay = 15, + Darken = 16, + Lighten = 17, + ColorDodge = 18, + ColorBurn = 19, + HardLight = 20, + SoftLight = 21, + Difference = 22, + Exclusion = 23, + Multiply = 24, + Hue = 25, + Saturation = 26, + Color = 27, + Luminosity = 28, +} + impl BlurStyle { pub const LastEnum: BlurStyle = BlurStyle::Inner; } @@ -1468,6 +1517,7 @@ pub enum BlurStyle { pub mod svg { use super::{ Canvas, + Color, LocalResourceProvider, Size, }; @@ -1484,6 +1534,14 @@ pub mod svg { } } + pub struct Paint; + + impl Paint { + pub fn from_color(_color: Color) -> Self { + unimplemented!("This is mocked") + } + } + pub struct SvgNode; impl SvgNode { @@ -1494,6 +1552,18 @@ pub mod svg { pub fn set_height(&mut self, _height: Length) { unimplemented!("This is mocked") } + + pub fn set_color(&mut self, _value: Color) { + unimplemented!("This is mocked") + } + + pub fn set_fill(&mut self, _value: Paint) { + unimplemented!("This is mocked") + } + + pub fn set_stroke(&mut self, _value: Paint) { + unimplemented!("This is mocked") + } } pub struct Dom; diff --git a/crates/engine/src/skia.rs b/crates/engine/src/skia.rs index e8eb0ad52..bd50c53e1 100644 --- a/crates/engine/src/skia.rs +++ b/crates/engine/src/skia.rs @@ -1,4 +1,5 @@ pub use skia_safe::{ + canvas::SaveLayerRec, font_style::{ Slant, Weight, @@ -56,7 +57,9 @@ pub use skia_safe::{ TextStyle, TypefaceFontProvider, }, + wrapper::PointerWrapper, Bitmap, + BlendMode, BlurStyle, Canvas, ClipOp, diff --git a/crates/native-core/src/attributes.rs b/crates/native-core/src/attributes.rs index 59526e20c..c30b3de3c 100644 --- a/crates/native-core/src/attributes.rs +++ b/crates/native-core/src/attributes.rs @@ -16,6 +16,8 @@ pub enum AttributeName { CornerRadius, CornerSmoothing, Color, + Fill, + Stroke, FontSize, FontFamily, FontStyle, @@ -237,6 +239,8 @@ impl FromStr for AttributeName { "corner_radius" => Ok(AttributeName::CornerRadius), "corner_smoothing" => Ok(AttributeName::CornerSmoothing), "color" => Ok(AttributeName::Color), + "fill" => Ok(AttributeName::Fill), + "stroke" => Ok(AttributeName::Stroke), "font_size" => Ok(AttributeName::FontSize), "font_family" => Ok(AttributeName::FontFamily), "font_style" => Ok(AttributeName::FontStyle), diff --git a/crates/state/src/style.rs b/crates/state/src/style.rs index 978a57162..576337936 100644 --- a/crates/state/src/style.rs +++ b/crates/state/src/style.rs @@ -4,6 +4,7 @@ use std::sync::{ }; use freya_common::CompositorDirtyNodes; +use freya_engine::prelude::Color; use freya_native_core::{ attributes::AttributeName, exports::shipyard::Component, @@ -36,6 +37,8 @@ use crate::{ #[derive(Default, Debug, Clone, PartialEq, Component)] pub struct StyleState { pub background: Fill, + pub svg_fill: Option, + pub svg_stroke: Option, pub borders: Vec, pub shadows: Vec, pub corner_radius: CornerRadius, @@ -58,6 +61,22 @@ impl ParseAttribute for StyleState { self.background = Fill::parse(value)?; } } + AttributeName::Fill => { + if let Some(value) = attr.value.as_text() { + if value == "none" { + return Ok(()); + } + self.svg_stroke = Some(Color::parse(value)?); + } + } + AttributeName::Stroke => { + if let Some(value) = attr.value.as_text() { + if value == "none" { + return Ok(()); + } + self.svg_fill = Some(Color::parse(value)?); + } + } AttributeName::Border => { if let Some(value) = attr.value.as_text() { self.borders = value @@ -132,6 +151,8 @@ impl State for StyleState { const NODE_MASK: NodeMaskBuilder<'static> = NodeMaskBuilder::new().with_attrs(AttributeMaskBuilder::Some(&[ AttributeName::Background, + AttributeName::Fill, + AttributeName::Stroke, AttributeName::Layer, AttributeName::Border, AttributeName::Shadow, diff --git a/examples/settings.svg b/examples/settings.svg new file mode 100644 index 000000000..cea27111e --- /dev/null +++ b/examples/settings.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/examples/svg_fill.rs b/examples/svg_fill.rs new file mode 100644 index 000000000..1f8d66687 --- /dev/null +++ b/examples/svg_fill.rs @@ -0,0 +1,23 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use freya::prelude::*; + +fn main() { + launch(app); +} + +static SETTINGS: &[u8] = include_bytes!("./settings.svg"); + +fn app() -> Element { + let svg_data = static_bytes(SETTINGS); + + rsx!(svg { + fill: "red", + width: "100%", + height: "100%", + svg_data, + }) +} From 4a23fb7ea8fc6c542af8f98faa49325e3454f16f Mon Sep 17 00:00:00 2001 From: _Robertas <66907345+RobertasJ@users.noreply.github.com> Date: Sun, 24 Nov 2024 12:02:00 +0100 Subject: [PATCH 21/36] Add prefixes and parentheses to calc function (#988) * added parenthesis and term parsing + eval * added prefixes - and + * formatting... and a bit of docs * make sure parentheses get closed * fix typo Co-authored-by: Marc Espin * added some text to the unreachable part * fix typo * forgot parsing lol * redid calc parsing to be a little nicer * fix warnings * chore: Update comment * fmt --------- Co-authored-by: Marc Espin --- crates/state/Cargo.toml | 3 +- crates/state/src/values/size.rs | 62 ++++++++++++++++------------ crates/state/tests/parse_size.rs | 9 +++- crates/torin/src/values/size.rs | 71 ++++++++++++++++++++++++++++---- crates/torin/tests/size.rs | 61 ++++++++++++++++++++++++++- 5 files changed, 167 insertions(+), 39 deletions(-) diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index 998ff2daf..82f152a67 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -29,9 +29,10 @@ dioxus-core = { workspace = true } tokio = { workspace = true } accesskit = { workspace = true } shipyard = { workspace = true } -rustc-hash= { workspace = true } +rustc-hash = { workspace = true } tracing = { workspace = true } uuid = { workspace = true } bytes = "1.5.0" serde_json = "1.0.107" +nom = "7.1.3" diff --git a/crates/state/src/values/size.rs b/crates/state/src/values/size.rs index 12148087a..4caf55ddd 100644 --- a/crates/state/src/values/size.rs +++ b/crates/state/src/values/size.rs @@ -1,3 +1,16 @@ +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::multispace0, + combinator::map, + multi::many1, + number::complete::float, + sequence::{ + preceded, + tuple, + }, + IResult, +}; use torin::{ geometry::Length, size::{ @@ -61,39 +74,34 @@ impl Parse for Size { } pub fn parse_calc(mut value: &str) -> Result, ParseError> { - let mut calcs = Vec::new(); + // No need to parse this using nom value = value .strip_prefix("calc(") .ok_or(ParseError)? .strip_suffix(')') .ok_or(ParseError)?; - - let values = value.split_whitespace(); - - for val in values { - if val.contains('%') { - calcs.push(DynamicCalculation::Percentage( - val.replace('%', "").parse().map_err(|_| ParseError)?, - )); - } else if val.contains('v') { - calcs.push(DynamicCalculation::RootPercentage( - val.replace('v', "").parse().map_err(|_| ParseError)?, - )); - } else if val == "+" { - calcs.push(DynamicCalculation::Add); - } else if val == "-" { - calcs.push(DynamicCalculation::Sub); - } else if val == "/" { - calcs.push(DynamicCalculation::Div); - } else if val == "*" { - calcs.push(DynamicCalculation::Mul); - } else { - calcs.push(DynamicCalculation::Pixels( - val.parse::().map_err(|_| ParseError)?, - )); - } + fn inner_parse(value: &str) -> IResult<&str, Vec> { + many1(preceded( + multispace0, + alt(( + map(tag("+"), |_| DynamicCalculation::Add), + map(tag("-"), |_| DynamicCalculation::Sub), + map(tag("*"), |_| DynamicCalculation::Mul), + map(tag("/"), |_| DynamicCalculation::Div), + map(tag("("), |_| DynamicCalculation::OpenParenthesis), + map(tag(")"), |_| DynamicCalculation::ClosedParenthesis), + map(tuple((float, tag("%"))), |(v, _)| { + DynamicCalculation::Percentage(v) + }), + map(tuple((float, tag("v"))), |(v, _)| { + DynamicCalculation::RootPercentage(v) + }), + map(float, DynamicCalculation::Pixels), + )), + ))(value) } + let tokens = inner_parse(value).map_err(|_| ParseError)?.1; - Ok(calcs) + Ok(tokens) } diff --git a/crates/state/tests/parse_size.rs b/crates/state/tests/parse_size.rs index 4e4a90084..d24129b42 100644 --- a/crates/state/tests/parse_size.rs +++ b/crates/state/tests/parse_size.rs @@ -27,7 +27,7 @@ fn parse_auto_size() { #[test] fn parse_calc_size() { - let size = Size::parse("calc(90% - 5% * 123.6 / 50v)"); + let size = Size::parse("calc(90%- 5%* 123.6/ 50v(5 + 6))"); assert_eq!( size, Ok(Size::DynamicCalculations(Box::new(vec![ @@ -37,7 +37,12 @@ fn parse_calc_size() { DynamicCalculation::Mul, DynamicCalculation::Pixels(123.6), DynamicCalculation::Div, - DynamicCalculation::RootPercentage(50.0) + DynamicCalculation::RootPercentage(50.0), + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(5.0), + DynamicCalculation::Add, + DynamicCalculation::Pixels(6.0), + DynamicCalculation::ClosedParenthesis, ]))) ); } diff --git a/crates/torin/src/values/size.rs b/crates/torin/src/values/size.rs index 066cd97ac..9afce5792 100644 --- a/crates/torin/src/values/size.rs +++ b/crates/torin/src/values/size.rs @@ -179,6 +179,8 @@ pub enum DynamicCalculation { Mul, Div, Add, + OpenParenthesis, + ClosedParenthesis, Percentage(f32), RootPercentage(f32), Pixels(f32), @@ -199,6 +201,8 @@ impl std::fmt::Display for DynamicCalculation { DynamicCalculation::Mul => f.write_str("*"), DynamicCalculation::Div => f.write_str("/"), DynamicCalculation::Add => f.write_str("+"), + DynamicCalculation::OpenParenthesis => f.write_str("("), + DynamicCalculation::ClosedParenthesis => f.write_str(")"), DynamicCalculation::Percentage(p) => f.write_fmt(format_args!("{p}%")), DynamicCalculation::RootPercentage(p) => f.write_fmt(format_args!("{p}v")), DynamicCalculation::Pixels(s) => f.write_fmt(format_args!("{s}")), @@ -243,7 +247,7 @@ impl<'a> DynamicCalculationEvaluator<'a> { fn parse_expression(&mut self, min_precedence: usize) -> Option { // Parse left-hand side value self.current = self.calcs.next(); - let mut lhs = self.parse_value()?; + let mut lhs = self.parse_term()?; while let Some(operator_precedence) = self.operator_precedence() { // Return if minimal precedence is reached. @@ -275,35 +279,88 @@ impl<'a> DynamicCalculationEvaluator<'a> { Some(lhs) } - /// Parse and evaluate the value with the following grammar: + /// Parse and evaluate the term, implements implicit multiplication. only parenthesis count as + /// a seperator, so syntax like 50 50 isnt correct, but 50(50) is because the parenthesis act + /// as a seperator + fn parse_term(&mut self) -> Option { + let prefix = self.parse_prefix()?; + let mut lhs = None; + // set to true so that the first value is multiplied and counts as normal syntax + let mut last_is_separator = true; + + while let Some((rhs, seperator)) = self.parse_value() { + if last_is_separator || seperator { + lhs = Some(lhs.unwrap_or(1.0) * rhs); + } else { + return None; + } + last_is_separator = seperator; + } + if let Some(prefix) = prefix { + match prefix { + DynamicCalculation::Add => lhs, + DynamicCalculation::Sub => lhs.map(|v| v * -1.0), + _ => unreachable!("make sure to add the prefix here"), + } + } else { + lhs + } + } + /// parse and evaluate the value with the following grammar: /// ```ebnf /// value = percentage | pixels ; /// percentage = number, "%" ; /// pixels = number ; - /// ``` - fn parse_value(&mut self) -> Option { + /// ` + fn parse_value(&mut self) -> Option<(f32, bool)> { match self.current? { DynamicCalculation::Percentage(value) => { self.current = self.calcs.next(); - Some((self.parent_value / 100.0 * value).round()) + Some(((self.parent_value / 100.0 * value).round(), false)) } DynamicCalculation::RootPercentage(value) => { self.current = self.calcs.next(); - Some((self.root_value / 100.0 * value).round()) + Some(((self.root_value / 100.0 * value).round(), false)) } DynamicCalculation::Pixels(value) => { self.current = self.calcs.next(); - Some(*value) + Some((*value, false)) + } + DynamicCalculation::OpenParenthesis => { + // function should return on DynamicCalculation::ClosedParenthesis because it does + // not have a precedence, thats how it actually works + let val = self.parse_expression(0); + if self.current != Some(&DynamicCalculation::ClosedParenthesis) { + return None; + } + self.current = self.calcs.next(); + Some((val?, true)) } _ => None, } } + /// parses out the prefix, like a + or - + fn parse_prefix(&mut self) -> Option> { + match self.current? { + DynamicCalculation::Add => { + self.current = self.calcs.next(); + Some(Some(DynamicCalculation::Add)) + } + DynamicCalculation::Sub => { + self.current = self.calcs.next(); + Some(Some(DynamicCalculation::Sub)) + } + _ => Some(None), + } + } + /// Get the precedence of the operator if current token is an operator or None otherwise. fn operator_precedence(&self) -> Option { match self.current? { DynamicCalculation::Add | DynamicCalculation::Sub => Some(1), DynamicCalculation::Mul | DynamicCalculation::Div => Some(2), + DynamicCalculation::OpenParenthesis => Some(0), _ => None, } } diff --git a/crates/torin/tests/size.rs b/crates/torin/tests/size.rs index 1e4750d58..c95343851 100644 --- a/crates/torin/tests/size.rs +++ b/crates/torin/tests/size.rs @@ -863,7 +863,8 @@ pub fn test_calc() { PARENT_VALUE, PARENT_VALUE ), - None + // Because +10 is just 10 + Some(10.0) ); assert_eq!( @@ -871,13 +872,14 @@ pub fn test_calc() { &[ DynamicCalculation::Pixels(10.0), DynamicCalculation::Add, + // counts as a prefix DynamicCalculation::Add, DynamicCalculation::Pixels(10.0) ], PARENT_VALUE, PARENT_VALUE ), - None + Some(20.0) ); assert_eq!( @@ -892,4 +894,59 @@ pub fn test_calc() { ), Some((PARENT_VALUE * 0.5) - (PARENT_VALUE * 0.20)) ); + + assert_eq!( + run_calculations( + &[DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::ClosedParenthesis], + PARENT_VALUE, + PARENT_VALUE + ), + Some(10.0) + ); + + assert_eq!( + run_calculations( + &[DynamicCalculation::Pixels(10.0), + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::Add, + DynamicCalculation::Pixels(20.0), + DynamicCalculation::ClosedParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::Add, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::ClosedParenthesis, + DynamicCalculation::Pixels(10.0)], + PARENT_VALUE, + PARENT_VALUE + ), + Some((10.0 * (10.0 + 20.0) * 10.0) + (10.0 * (10.0) * 10.0)) + ); + + assert_eq!( + run_calculations( + &[DynamicCalculation::Sub, + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::ClosedParenthesis, + DynamicCalculation::Pixels(20.0)], + PARENT_VALUE, + PARENT_VALUE + ), + Some(-1.0 * 10.0 * 20.0) + ); + + assert_eq!( + run_calculations( + &[DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0)], + PARENT_VALUE, + PARENT_VALUE + ), + None + ); } From 8bd52cbb68b55873a16f9f4cb4036ecc83dc27eb Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sun, 24 Nov 2024 12:04:59 +0100 Subject: [PATCH 22/36] chore: Only run the sponsors workflow in `marc2332/freya` --- .github/workflows/sponsors.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml index 8ae389908..7b53d946a 100644 --- a/.github/workflows/sponsors.yml +++ b/.github/workflows/sponsors.yml @@ -5,6 +5,7 @@ on: - cron: 30 15 * * 0-6 jobs: deploy: + if: github.repository == 'marc2332/freya' runs-on: ubuntu-latest steps: - name: Checkout 🛎️ From d7568ad4ef62b28107c5c640b9f45df91ee2880d Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sun, 24 Nov 2024 15:34:01 +0000 Subject: [PATCH 23/36] =?UTF-8?q?Deploying=20to=20main=20from=20@=20marc23?= =?UTF-8?q?32/freya@8bd52cbb68b55873a16f9f4cb4036ecc83dc27eb=20?= =?UTF-8?q?=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a821cb49..c68d77b20 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ If you are interested in supporting the development of this project feel free to Thanks to my sponsors for supporting this project! 😄 -高庆丰Lino Le Van + ### Special thanks 💪 From e8b37eaa91509f3266069a08273b3e3d969adbb3 Mon Sep 17 00:00:00 2001 From: _Robertas <66907345+RobertasJ@users.noreply.github.com> Date: Sat, 30 Nov 2024 10:15:35 +0100 Subject: [PATCH 24/36] Fix scale factor behavior in `calc()` (#1006) * fix calc scaling factor * no more implicit multiplication * add tests --- crates/torin/src/lib.rs | 3 +- crates/torin/src/values/size.rs | 13 ++-- crates/torin/tests/size.rs | 106 +++++++++++++++++++++++++++++--- 3 files changed, 104 insertions(+), 18 deletions(-) diff --git a/crates/torin/src/lib.rs b/crates/torin/src/lib.rs index 0b9f3f996..a192540d4 100644 --- a/crates/torin/src/lib.rs +++ b/crates/torin/src/lib.rs @@ -1,7 +1,7 @@ pub mod custom_measurer; pub mod dom_adapter; pub mod geometry; -mod measure; +pub mod measure; pub mod node; pub mod scaled; pub mod torin; @@ -15,6 +15,7 @@ pub mod prelude { dom_adapter::*, gaps::*, geometry::*, + measure::*, node::*, scaled::*, torin::*, diff --git a/crates/torin/src/values/size.rs b/crates/torin/src/values/size.rs index 9afce5792..867c41755 100644 --- a/crates/torin/src/values/size.rs +++ b/crates/torin/src/values/size.rs @@ -166,7 +166,10 @@ impl Scaled for Size { match self { Size::Pixels(s) => *s *= scale_factor, Size::DynamicCalculations(calcs) => { - calcs.iter_mut().for_each(|calc| calc.scale(scale_factor)); + calcs.insert(0, DynamicCalculation::OpenParenthesis); + calcs.push(DynamicCalculation::ClosedParenthesis); + calcs.push(DynamicCalculation::Mul); + calcs.push(DynamicCalculation::Pixels(scale_factor)); } _ => (), } @@ -186,14 +189,6 @@ pub enum DynamicCalculation { Pixels(f32), } -impl Scaled for DynamicCalculation { - fn scale(&mut self, scale_factor: f32) { - if let DynamicCalculation::Pixels(s) = self { - *s *= scale_factor; - } - } -} - impl std::fmt::Display for DynamicCalculation { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/crates/torin/tests/size.rs b/crates/torin/tests/size.rs index c95343851..82a54c315 100644 --- a/crates/torin/tests/size.rs +++ b/crates/torin/tests/size.rs @@ -897,9 +897,11 @@ pub fn test_calc() { assert_eq!( run_calculations( - &[DynamicCalculation::OpenParenthesis, + &[ + DynamicCalculation::OpenParenthesis, DynamicCalculation::Pixels(10.0), - DynamicCalculation::ClosedParenthesis], + DynamicCalculation::ClosedParenthesis + ], PARENT_VALUE, PARENT_VALUE ), @@ -908,7 +910,8 @@ pub fn test_calc() { assert_eq!( run_calculations( - &[DynamicCalculation::Pixels(10.0), + &[ + DynamicCalculation::Pixels(10.0), DynamicCalculation::OpenParenthesis, DynamicCalculation::Pixels(10.0), DynamicCalculation::Add, @@ -920,7 +923,8 @@ pub fn test_calc() { DynamicCalculation::OpenParenthesis, DynamicCalculation::Pixels(10.0), DynamicCalculation::ClosedParenthesis, - DynamicCalculation::Pixels(10.0)], + DynamicCalculation::Pixels(10.0) + ], PARENT_VALUE, PARENT_VALUE ), @@ -929,11 +933,13 @@ pub fn test_calc() { assert_eq!( run_calculations( - &[DynamicCalculation::Sub, + &[ + DynamicCalculation::Sub, DynamicCalculation::OpenParenthesis, DynamicCalculation::Pixels(10.0), DynamicCalculation::ClosedParenthesis, - DynamicCalculation::Pixels(20.0)], + DynamicCalculation::Pixels(20.0) + ], PARENT_VALUE, PARENT_VALUE ), @@ -942,11 +948,95 @@ pub fn test_calc() { assert_eq!( run_calculations( - &[DynamicCalculation::OpenParenthesis, - DynamicCalculation::Pixels(10.0)], + &[ + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0) + ], PARENT_VALUE, PARENT_VALUE ), None ); } + +#[test] +pub fn test_scaling_factor() { + const PARENT_VALUE: f32 = 500.0; + + assert_eq!( + { + let mut size = + Size::DynamicCalculations(Box::new(vec![DynamicCalculation::Pixels(10.0)])); + size.scale(1.5); + size + } + .eval( + PARENT_VALUE, + PARENT_VALUE, + 0.0, + PARENT_VALUE, + Phase::Initial + ), + Some((10.0) * 1.5) + ); + + assert_eq!( + { + let mut size = Size::DynamicCalculations(Box::new(vec![ + DynamicCalculation::Pixels(10.0), + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::Add, + DynamicCalculation::Pixels(20.0), + DynamicCalculation::ClosedParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::Add, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::ClosedParenthesis, + DynamicCalculation::Pixels(10.0), + ])); + size.scale(1.5); + size + } + .eval( + PARENT_VALUE, + PARENT_VALUE, + 0.0, + PARENT_VALUE, + Phase::Initial + ), + Some(((10.0 * (10.0 + 20.0) * 10.0) + (10.0 * (10.0) * 10.0)) * 1.5) + ); + + assert_eq!( + { + let mut size = Size::DynamicCalculations(Box::new(vec![ + DynamicCalculation::Pixels(10.0), + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::Add, + DynamicCalculation::Pixels(20.0), + DynamicCalculation::ClosedParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::Add, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::OpenParenthesis, + DynamicCalculation::Pixels(10.0), + DynamicCalculation::ClosedParenthesis, + DynamicCalculation::Pixels(10.0), + ])); + size.scale(1.2); + size + } + .eval( + PARENT_VALUE, + PARENT_VALUE, + 0.0, + PARENT_VALUE, + Phase::Initial + ), + Some(((10.0 * (10.0 + 20.0) * 10.0) + (10.0 * (10.0) * 10.0)) * 1.2) + ); +} From af4aa9890a2ff873323c1b9511c47b79bf1ab48c Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sat, 30 Nov 2024 14:14:02 +0100 Subject: [PATCH 25/36] Revert "Fix scale factor behavior in `calc()`" (#1008) * Revert "Fix scale factor behavior in `calc()` (#1006)" This reverts commit e8b37eaa91509f3266069a08273b3e3d969adbb3. * fmt --- crates/torin/src/lib.rs | 3 +- crates/torin/src/values/size.rs | 13 ++++-- crates/torin/tests/size.rs | 82 --------------------------------- 3 files changed, 10 insertions(+), 88 deletions(-) diff --git a/crates/torin/src/lib.rs b/crates/torin/src/lib.rs index a192540d4..0b9f3f996 100644 --- a/crates/torin/src/lib.rs +++ b/crates/torin/src/lib.rs @@ -1,7 +1,7 @@ pub mod custom_measurer; pub mod dom_adapter; pub mod geometry; -pub mod measure; +mod measure; pub mod node; pub mod scaled; pub mod torin; @@ -15,7 +15,6 @@ pub mod prelude { dom_adapter::*, gaps::*, geometry::*, - measure::*, node::*, scaled::*, torin::*, diff --git a/crates/torin/src/values/size.rs b/crates/torin/src/values/size.rs index 867c41755..9afce5792 100644 --- a/crates/torin/src/values/size.rs +++ b/crates/torin/src/values/size.rs @@ -166,10 +166,7 @@ impl Scaled for Size { match self { Size::Pixels(s) => *s *= scale_factor, Size::DynamicCalculations(calcs) => { - calcs.insert(0, DynamicCalculation::OpenParenthesis); - calcs.push(DynamicCalculation::ClosedParenthesis); - calcs.push(DynamicCalculation::Mul); - calcs.push(DynamicCalculation::Pixels(scale_factor)); + calcs.iter_mut().for_each(|calc| calc.scale(scale_factor)); } _ => (), } @@ -189,6 +186,14 @@ pub enum DynamicCalculation { Pixels(f32), } +impl Scaled for DynamicCalculation { + fn scale(&mut self, scale_factor: f32) { + if let DynamicCalculation::Pixels(s) = self { + *s *= scale_factor; + } + } +} + impl std::fmt::Display for DynamicCalculation { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/crates/torin/tests/size.rs b/crates/torin/tests/size.rs index 82a54c315..585dd1d9a 100644 --- a/crates/torin/tests/size.rs +++ b/crates/torin/tests/size.rs @@ -958,85 +958,3 @@ pub fn test_calc() { None ); } - -#[test] -pub fn test_scaling_factor() { - const PARENT_VALUE: f32 = 500.0; - - assert_eq!( - { - let mut size = - Size::DynamicCalculations(Box::new(vec![DynamicCalculation::Pixels(10.0)])); - size.scale(1.5); - size - } - .eval( - PARENT_VALUE, - PARENT_VALUE, - 0.0, - PARENT_VALUE, - Phase::Initial - ), - Some((10.0) * 1.5) - ); - - assert_eq!( - { - let mut size = Size::DynamicCalculations(Box::new(vec![ - DynamicCalculation::Pixels(10.0), - DynamicCalculation::OpenParenthesis, - DynamicCalculation::Pixels(10.0), - DynamicCalculation::Add, - DynamicCalculation::Pixels(20.0), - DynamicCalculation::ClosedParenthesis, - DynamicCalculation::Pixels(10.0), - DynamicCalculation::Add, - DynamicCalculation::Pixels(10.0), - DynamicCalculation::OpenParenthesis, - DynamicCalculation::Pixels(10.0), - DynamicCalculation::ClosedParenthesis, - DynamicCalculation::Pixels(10.0), - ])); - size.scale(1.5); - size - } - .eval( - PARENT_VALUE, - PARENT_VALUE, - 0.0, - PARENT_VALUE, - Phase::Initial - ), - Some(((10.0 * (10.0 + 20.0) * 10.0) + (10.0 * (10.0) * 10.0)) * 1.5) - ); - - assert_eq!( - { - let mut size = Size::DynamicCalculations(Box::new(vec![ - DynamicCalculation::Pixels(10.0), - DynamicCalculation::OpenParenthesis, - DynamicCalculation::Pixels(10.0), - DynamicCalculation::Add, - DynamicCalculation::Pixels(20.0), - DynamicCalculation::ClosedParenthesis, - DynamicCalculation::Pixels(10.0), - DynamicCalculation::Add, - DynamicCalculation::Pixels(10.0), - DynamicCalculation::OpenParenthesis, - DynamicCalculation::Pixels(10.0), - DynamicCalculation::ClosedParenthesis, - DynamicCalculation::Pixels(10.0), - ])); - size.scale(1.2); - size - } - .eval( - PARENT_VALUE, - PARENT_VALUE, - 0.0, - PARENT_VALUE, - Phase::Initial - ), - Some(((10.0 * (10.0 + 20.0) * 10.0) + (10.0 * (10.0) * 10.0)) * 1.2) - ); -} From 79a7b5ca4be2645471d38ef727c623d137732495 Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sat, 14 Dec 2024 10:29:58 +0100 Subject: [PATCH 26/36] docs: New animated virtual scroll view example --- examples/animated_virtual_scroll_view.rs | 68 ++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 examples/animated_virtual_scroll_view.rs diff --git a/examples/animated_virtual_scroll_view.rs b/examples/animated_virtual_scroll_view.rs new file mode 100644 index 000000000..98dcbbe2b --- /dev/null +++ b/examples/animated_virtual_scroll_view.rs @@ -0,0 +1,68 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use freya::prelude::*; + +fn main() { + launch(app) +} + +fn app() -> Element { + let values = use_signal(|| ["Hello, World!"].repeat(150)); + + rsx!(VirtualScrollView { + length: values.read().len(), + item_size: 70.0, + direction: "vertical", + builder: move |index, _: &Option<()>| { + let value = values.read()[index]; + rsx! { + AnimatedContainer { + key: "{index}", + height: 70.0, + rect { + width: "100%", + height: "100%", + background: "rgb(235, 235, 235)", + corner_radius: "16", + padding: "4 10", + label { + height: "25", + "{index} {value}" + } + label { + "Cool!" + } + } + } + } + } + }) +} + +#[component] +fn AnimatedContainer(height: f32, children: Element) -> Element { + let animations = use_animation(|ctx| { + ctx.auto_start(true); + ctx.with( + AnimNum::new(350., 0.) + .time(500) + .ease(Ease::InOut) + .function(Function::Expo), + ) + }); + + let pos = animations.get(); + + rsx!( + rect { + offset_x: "{pos.read().as_f32()}", + height: "{height}", + width: "100%", + padding: "4", + {children} + } + ) +} From 49b30debacf65b03e58d5e366aa7ab09f78f928a Mon Sep 17 00:00:00 2001 From: marc2332 Date: Sun, 15 Dec 2024 16:48:22 +0100 Subject: [PATCH 27/36] docs: New speedometer example --- examples/speedometer.rs | 182 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 182 insertions(+) create mode 100644 examples/speedometer.rs diff --git a/examples/speedometer.rs b/examples/speedometer.rs new file mode 100644 index 000000000..aafe2a1d1 --- /dev/null +++ b/examples/speedometer.rs @@ -0,0 +1,182 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use freya::prelude::*; +use skia_safe::{ + textlayout::{ + FontCollection, + ParagraphBuilder, + ParagraphStyle, + TextAlign, + TextStyle, + }, + Color, + Paint, + Point, +}; + +fn main() { + launch_with_props(app, "Speedometer", (400., 400.)); +} + +fn app() -> Element { + use_init_theme(|| DARK_THEME); + let animations = use_animation(|ctx| { + ctx.with( + AnimNum::new(0., 255.) + .time(1600) + .ease(Ease::Out) + .function(Function::Expo), + ) + }); + + let speed = animations.get(); + let speed = speed.read().as_f32() as u8; + + let min = move |_| { + animations.run(AnimDirection::Reverse); + }; + + let max = move |_| { + animations.run(AnimDirection::Forward); + }; + + rsx!( + rect { + background: "black", + width: "100%", + height: "100%", + main_align: "center", + cross_align: "center", + Speedometer { + width: 200., + height: 200., + speed + } + rect { + direction: "horizontal", + main_align: "center", + cross_align: "center", + spacing: "4", + Button { + onclick: min, + label { + "🛑" + } + } + Button { + onclick: max, + label { + "🏎️" + } + } + } + } + ) +} + +#[component] +fn Speedometer(speed: ReadOnlySignal, width: f32, height: f32) -> Element { + let platform = use_platform(); + let (reference, size) = use_node_signal(); + + let canvas = use_canvas(move || { + platform.invalidate_drawing_area(size.peek().area); + platform.request_animation_frame(); + let speed = speed(); + Box::new(move |ctx| { + ctx.canvas.translate((ctx.area.min_x(), ctx.area.min_y())); + + draw_speedometer(&mut ctx.canvas, &ctx.area, &mut ctx.font_collection, speed); + + ctx.canvas.restore(); + }) + }); + + rsx!(rect { + canvas_reference: canvas.attribute(), + reference, + width: "{width}", + height: "{height}", + }) +} + +fn draw_speedometer( + canvas: &skia_safe::Canvas, + area: &Area, + font_collection: &mut FontCollection, + speed: u8, +) { + let center = Point::new(area.width() * 0.5, area.height() * 0.5); + let radius = 80.0; + + // Draw the outer circle + let mut paint = Paint::default(); + paint.set_anti_alias(true); + paint.set_style(skia_safe::paint::Style::Stroke); + paint.set_stroke_width(2.0); + paint.set_color(Color::from_rgb(245, 245, 245)); + + canvas.draw_circle(center, radius, &paint); + + // Draw the tick marks + paint.set_stroke_width(2.); + for i in (0..=100).step_by(2) { + let angle = std::f32::consts::PI * (1.0 + (i as f32 / 100.0)); + let outer = Point::new( + center.x + radius * angle.cos(), + center.y + radius * angle.sin(), + ); + let inner = Point::new( + center.x + (radius - 20.0) * angle.cos(), + center.y + (radius - 20.0) * angle.sin(), + ); + + canvas.draw_line(inner, outer, &paint); + } + + // Draw the label + draw_text( + &speed.to_string(), + canvas, + font_collection, + 40., + center.x - 20., + center.y + 25., + ); + + // Draw the needle + paint.set_color(Color::RED); + paint.set_stroke_width(3.0); + let needle_angle = std::f32::consts::PI * ((speed as f32 / 255.) + 1.); // Pointing straight up + let needle_end = Point::new( + center.x + (radius - 25.0) * needle_angle.cos(), + center.y + (radius - 25.0) * needle_angle.sin(), + ); + canvas.draw_line(center, needle_end, &paint); +} + +fn draw_text( + text: &str, + canvas: &skia_safe::Canvas, + font_collection: &mut FontCollection, + width: f32, + x: f32, + y: f32, +) { + let mut style = ParagraphStyle::default(); + style.set_text_align(TextAlign::Center); + let mut text_style = TextStyle::new(); + text_style.set_font_families(&["Inter"]); + text_style.set_color(Color::from_rgb(245, 245, 245)); + text_style.set_font_size(20.0); + let mut paragraph_builder = ParagraphBuilder::new(&style, font_collection.clone()); + paragraph_builder.push_style(&text_style); + paragraph_builder.add_text(text); + let mut paragraph = paragraph_builder.build(); + paragraph.layout(width); + + paragraph.paint(canvas, (x, y)); +} From 94e7c19f0f162b54f1180d315f54744f9a1993df Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sun, 15 Dec 2024 19:42:18 +0100 Subject: [PATCH 28/36] fix: Update the `use_editable` tests to match github ci (#1012) * fix: Update the `use_editable` tests to match github ci * update test --- crates/hooks/tests/use_editable.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/hooks/tests/use_editable.rs b/crates/hooks/tests/use_editable.rs index 3e699bcb3..59b05387d 100644 --- a/crates/hooks/tests/use_editable.rs +++ b/crates/hooks/tests/use_editable.rs @@ -546,7 +546,7 @@ pub async fn special_text_editing() { assert_eq!(cursor.text(), Some("0:2")); #[cfg(target_os = "linux")] - assert_eq!(cursor.text(), Some("0:4")); + assert_eq!(cursor.text(), Some("0:3")); // Insert text utils.push_event(PlatformEvent::Keyboard { @@ -569,8 +569,8 @@ pub async fn special_text_editing() { #[cfg(target_os = "linux")] { - assert_eq!(content.text(), Some("你好世界🦀\n👋")); - assert_eq!(cursor.text(), Some("0:6")); + assert_eq!(content.text(), Some("你好世🦀界\n👋")); + assert_eq!(cursor.text(), Some("0:5")); } // Move cursor to the begining From a7c6b7b12694cb29c75ed05032bcf400b01cf36a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 17 Dec 2024 18:02:39 +0100 Subject: [PATCH 29/36] chore(deps): update codecov/codecov-action action to v5 (#992) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 6705e1a46..3c73ae9d9 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -57,7 +57,7 @@ jobs: rustup component add llvm-tools-preview curl -L https://github.com/mozilla/grcov/releases/latest/download/grcov-x86_64-unknown-linux-gnu.tar.bz2 | tar jxf - ./grcov . --binary-path ./target/debug/deps -s . -t lcov --branch --ignore-not-existing --ignore "../*" --ignore "/*" -o cov.lcov - - uses: codecov/codecov-action@v4 + - uses: codecov/codecov-action@v5 if: runner.os == 'Linux' with: token: ${{ secrets.CODECOV_TOKEN }} From 24c1797c643259527e00b0cd25e7b17b7cb98ec9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 19:17:37 +0100 Subject: [PATCH 30/36] fix(deps): update dependency astro to v5 - abandoned (#1010) * fix(deps): update dependency astro to v5 * adapt to astro 5 --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: marc2332 --- website/package.json | 2 +- website/pnpm-lock.yaml | 5150 ++++++++++++---------- website/src/content.config.ts | 17 + website/src/layouts/BlogPostLayout.astro | 11 +- website/src/layouts/Layout.astro | 2 +- website/src/pages/blog.astro | 15 +- website/src/pages/index.astro | 6 +- website/src/pages/posts/[...slug].astro | 27 +- 8 files changed, 2783 insertions(+), 2447 deletions(-) create mode 100644 website/src/content.config.ts diff --git a/website/package.json b/website/package.json index 2a0b87a22..c7b92c755 100644 --- a/website/package.json +++ b/website/package.json @@ -15,7 +15,7 @@ "@astrojs/deno": "^5.0.0", "@astrojs/rss": "^4.0.1", "@astrojs/tailwind": "^5.0.2", - "astro": "4.11.3", + "astro": "5.0.5", "rehype-accessible-emojis": "^0.3.2", "rehype-autolink-headings": "^7.1.0", "rehype-slug": "^6.0.0", diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index db6df0ccb..455cdab9e 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -1,1523 +1,2814 @@ -lockfileVersion: '6.0' +lockfileVersion: '9.0' settings: autoInstallPeers: true excludeLinksFromLockfile: false -dependencies: - '@astrojs/deno': - specifier: ^5.0.0 - version: 5.0.1(astro@4.11.3) - '@astrojs/rss': - specifier: ^4.0.1 - version: 4.0.7 - '@astrojs/tailwind': - specifier: ^5.0.2 - version: 5.1.0(astro@4.11.3)(tailwindcss@3.4.4) - astro: - specifier: 4.11.3 - version: 4.11.3 - rehype-accessible-emojis: - specifier: ^0.3.2 - version: 0.3.2 - rehype-autolink-headings: - specifier: ^7.1.0 - version: 7.1.0 - rehype-slug: - specifier: ^6.0.0 - version: 6.0.0 - tailwindcss: - specifier: ^3.0.24 - version: 3.4.4 - -devDependencies: - '@biomejs/biome': - specifier: ^1.3.3 - version: 1.8.3 +importers: + + .: + dependencies: + '@astrojs/deno': + specifier: ^5.0.0 + version: 5.0.1(astro@5.0.5) + '@astrojs/rss': + specifier: ^4.0.1 + version: 4.0.7 + '@astrojs/tailwind': + specifier: ^5.0.2 + version: 5.1.0(astro@5.0.5)(tailwindcss@3.4.4) + astro: + specifier: 5.0.5 + version: 5.0.5(typescript@5.7.2) + rehype-accessible-emojis: + specifier: ^0.3.2 + version: 0.3.2 + rehype-autolink-headings: + specifier: ^7.1.0 + version: 7.1.0 + rehype-slug: + specifier: ^6.0.0 + version: 6.0.0 + tailwindcss: + specifier: ^3.0.24 + version: 3.4.4 + devDependencies: + '@biomejs/biome': + specifier: ^1.3.3 + version: 1.8.3 packages: - /@alloc/quick-lru@5.2.0: + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} - dev: false - /@ampproject/remapping@2.2.0: - resolution: {integrity: sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.1.1 - '@jridgewell/trace-mapping': 0.3.25 - dev: false - - /@astrojs/compiler@2.8.1: - resolution: {integrity: sha512-NGfPAgU/9rvDEwsXu82RI1AxiivaxtEYBK9saW1f+2fTHUUqCJQ27HYtb2akG2QxCmFikgZ9zk26BEWgiHho1Q==} - dev: false + '@astrojs/compiler@2.10.3': + resolution: {integrity: sha512-bL/O7YBxsFt55YHU021oL+xz+B/9HvGNId3F9xURN16aeqDK9juHGktdkCSXz+U4nqFACq6ZFvWomOzhV+zfPw==} - /@astrojs/deno@5.0.1(astro@4.11.3): + '@astrojs/deno@5.0.1': resolution: {integrity: sha512-nYztGqHqC+q3A9ynjj3gblAkO/ZylDwahjVTx+2DvZgX4U+BJU/gL5BZkNtL+P10opCKJi29NvvVFvk6jwZHmA==} peerDependencies: astro: ^3.1.4 - dependencies: - astro: 4.11.3 - esbuild: 0.19.12 - dev: false - /@astrojs/internal-helpers@0.4.1: - resolution: {integrity: sha512-bMf9jFihO8YP940uD70SI/RDzIhUHJAolWVcO1v5PUivxGKvfLZTLTVVxEYzGYyPsA3ivdLNqMnL5VgmQySa+g==} - dev: false + '@astrojs/internal-helpers@0.4.2': + resolution: {integrity: sha512-EdDWkC3JJVcpGpqJAU/5hSk2LKXyG3mNGkzGoAuyK+xoPHbaVdSuIWoN1QTnmK3N/gGfaaAfM8gO2KDCAW7S3w==} - /@astrojs/markdown-remark@5.1.1: - resolution: {integrity: sha512-rkWWjR9jVo0LAMxQ2+T19RKbQUa7NwBGhFj03bAz3hGf3blqeBIXs1NSPpizshO5kZzcOqKe8OlG6XpYO8esHg==} - dependencies: - '@astrojs/prism': 3.1.0 - github-slugger: 2.0.0 - hast-util-from-html: 2.0.1 - hast-util-to-text: 4.0.2 - import-meta-resolve: 4.1.0 - mdast-util-definitions: 6.0.0 - rehype-raw: 7.0.0 - rehype-stringify: 10.0.0 - remark-gfm: 4.0.0 - remark-parse: 11.0.0 - remark-rehype: 11.1.0 - remark-smartypants: 3.0.1 - shiki: 1.9.1 - unified: 11.0.5 - unist-util-remove-position: 5.0.0 - unist-util-visit: 5.0.0 - unist-util-visit-parents: 6.0.1 - vfile: 6.0.1 - transitivePeerDependencies: - - supports-color - dev: false + '@astrojs/markdown-remark@6.0.1': + resolution: {integrity: sha512-CTSYijj25NfxgZi15TU3CwPwgyD1/7yA3FcdcNmB9p94nydupiUbrIiq3IqeTp2m5kCVzxbPZeC7fTwEOaNyGw==} - /@astrojs/prism@3.1.0: - resolution: {integrity: sha512-Z9IYjuXSArkAUx3N6xj6+Bnvx8OdUSHA8YoOgyepp3+zJmtVYJIl/I18GozdJVW1p5u/CNpl3Km7/gwTJK85cw==} - engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} - dependencies: - prismjs: 1.29.0 - dev: false + '@astrojs/prism@3.2.0': + resolution: {integrity: sha512-GilTHKGCW6HMq7y3BUv9Ac7GMe/MO9gi9GW62GzKtth0SwukCu/qp2wLiGpEujhY+VVhaG9v7kv/5vFzvf4NYw==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} - /@astrojs/rss@4.0.7: + '@astrojs/rss@4.0.7': resolution: {integrity: sha512-ZEG55XFB19l+DplUvBISmz04UbjDtKliRO4Y5+ERRhAMjgCVVobEBNE6ZwWG1h6orWUocy4nfPihKXDyB73x9g==} - dependencies: - fast-xml-parser: 4.4.0 - kleur: 4.1.5 - dev: false - /@astrojs/tailwind@5.1.0(astro@4.11.3)(tailwindcss@3.4.4): + '@astrojs/tailwind@5.1.0': resolution: {integrity: sha512-BJoCDKuWhU9FT2qYg+fr6Nfb3qP4ShtyjXGHKA/4mHN94z7BGcmauQK23iy+YH5qWvTnhqkd6mQPQ1yTZTe9Ig==} peerDependencies: astro: ^3.0.0 || ^4.0.0 tailwindcss: ^3.0.24 - dependencies: - astro: 4.11.3 - autoprefixer: 10.4.19(postcss@8.4.38) - postcss: 8.4.38 - postcss-load-config: 4.0.2(postcss@8.4.38) - tailwindcss: 3.4.4 - transitivePeerDependencies: - - ts-node - dev: false - - /@astrojs/telemetry@3.1.0: - resolution: {integrity: sha512-/ca/+D8MIKEC8/A9cSaPUqQNZm+Es/ZinRv0ZAzvu2ios7POQSsVD+VOj7/hypWNsNM3T7RpfgNq7H2TU1KEHA==} - engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} - dependencies: - ci-info: 4.0.0 - debug: 4.3.5 - dlv: 1.1.3 - dset: 3.1.3 - is-docker: 3.0.0 - is-wsl: 3.1.0 - which-pm-runs: 1.1.0 - transitivePeerDependencies: - - supports-color - dev: false - - /@babel/code-frame@7.24.7: - resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.24.7 - picocolors: 1.0.1 - dev: false - - /@babel/compat-data@7.24.7: - resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==} - engines: {node: '>=6.9.0'} - dev: false - - /@babel/core@7.24.7: - resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.7 - '@babel/helper-compilation-targets': 7.24.7 - '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) - '@babel/helpers': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/template': 7.24.7 - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - convert-source-map: 2.0.0 - debug: 4.3.5 - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: false - - /@babel/generator@7.24.7: - resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 2.5.2 - dev: false - - /@babel/helper-annotate-as-pure@7.24.7: - resolution: {integrity: sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - dev: false - - /@babel/helper-compilation-targets@7.24.7: - resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.24.7 - '@babel/helper-validator-option': 7.24.7 - browserslist: 4.23.1 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: false - - /@babel/helper-environment-visitor@7.24.7: - resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - dev: false - - /@babel/helper-function-name@7.24.7: - resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.7 - dev: false - - /@babel/helper-hoist-variables@7.24.7: - resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - dev: false - - /@babel/helper-module-imports@7.24.7: - resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: false - - /@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-simple-access': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: false - - /@babel/helper-plugin-utils@7.24.7: - resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==} - engines: {node: '>=6.9.0'} - dev: false - - /@babel/helper-simple-access@7.24.7: - resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: false - - /@babel/helper-split-export-declaration@7.24.7: - resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.24.7 - dev: false - - /@babel/helper-string-parser@7.24.7: - resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} - engines: {node: '>=6.9.0'} - dev: false - - /@babel/helper-validator-identifier@7.24.7: - resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} - engines: {node: '>=6.9.0'} - dev: false - /@babel/helper-validator-option@7.24.7: - resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} - engines: {node: '>=6.9.0'} - dev: false + '@astrojs/telemetry@3.2.0': + resolution: {integrity: sha512-wxhSKRfKugLwLlr4OFfcqovk+LIFtKwLyGPqMsv+9/ibqqnW3Gv7tBhtKEb0gAyUAC4G9BTVQeQahqnQAhd6IQ==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0} - /@babel/helpers@7.24.7: - resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==} + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.24.7 - '@babel/types': 7.24.7 - dev: false - /@babel/highlight@7.24.7: - resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.24.7 - chalk: 2.4.2 - js-tokens: 4.0.0 - picocolors: 1.0.1 - dev: false - /@babel/parser@7.24.7: - resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} + '@babel/parser@7.26.3': + resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} engines: {node: '>=6.0.0'} hasBin: true - dependencies: - '@babel/types': 7.24.7 - dev: false - - /@babel/plugin-syntax-jsx@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - dev: false - - /@babel/plugin-transform-react-jsx@7.24.7(@babel/core@7.24.7): - resolution: {integrity: sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.24.7 - '@babel/helper-annotate-as-pure': 7.24.7 - '@babel/helper-module-imports': 7.24.7 - '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.24.7) - '@babel/types': 7.24.7 - transitivePeerDependencies: - - supports-color - dev: false - - /@babel/template@7.24.7: - resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 - dev: false - - /@babel/traverse@7.24.7: - resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.24.7 - '@babel/generator': 7.24.7 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 - debug: 4.3.5 - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: false - /@babel/types@7.24.7: - resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} + '@babel/types@7.26.3': + resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.24.7 - '@babel/helper-validator-identifier': 7.24.7 - to-fast-properties: 2.0.0 - dev: false - /@biomejs/biome@1.8.3: + '@biomejs/biome@1.8.3': resolution: {integrity: sha512-/uUV3MV+vyAczO+vKrPdOW0Iaet7UnJMU4bNMinggGJTAnBPjCoLEYcyYtYHNnUNYlv4xZMH6hVIQCAozq8d5w==} engines: {node: '>=14.21.3'} hasBin: true - requiresBuild: true - optionalDependencies: - '@biomejs/cli-darwin-arm64': 1.8.3 - '@biomejs/cli-darwin-x64': 1.8.3 - '@biomejs/cli-linux-arm64': 1.8.3 - '@biomejs/cli-linux-arm64-musl': 1.8.3 - '@biomejs/cli-linux-x64': 1.8.3 - '@biomejs/cli-linux-x64-musl': 1.8.3 - '@biomejs/cli-win32-arm64': 1.8.3 - '@biomejs/cli-win32-x64': 1.8.3 - dev: true - /@biomejs/cli-darwin-arm64@1.8.3: + '@biomejs/cli-darwin-arm64@1.8.3': resolution: {integrity: sha512-9DYOjclFpKrH/m1Oz75SSExR8VKvNSSsLnVIqdnKexj6NwmiMlKk94Wa1kZEdv6MCOHGHgyyoV57Cw8WzL5n3A==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@biomejs/cli-darwin-x64@1.8.3: + '@biomejs/cli-darwin-x64@1.8.3': resolution: {integrity: sha512-UeW44L/AtbmOF7KXLCoM+9PSgPo0IDcyEUfIoOXYeANaNXXf9mLUwV1GeF2OWjyic5zj6CnAJ9uzk2LT3v/wAw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: true - optional: true - /@biomejs/cli-linux-arm64-musl@1.8.3: + '@biomejs/cli-linux-arm64-musl@1.8.3': resolution: {integrity: sha512-9yjUfOFN7wrYsXt/T/gEWfvVxKlnh3yBpnScw98IF+oOeCYb5/b/+K7YNqKROV2i1DlMjg9g/EcN9wvj+NkMuQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@biomejs/cli-linux-arm64@1.8.3: + '@biomejs/cli-linux-arm64@1.8.3': resolution: {integrity: sha512-fed2ji8s+I/m8upWpTJGanqiJ0rnlHOK3DdxsyVLZQ8ClY6qLuPc9uehCREBifRJLl/iJyQpHIRufLDeotsPtw==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@biomejs/cli-linux-x64-musl@1.8.3: + '@biomejs/cli-linux-x64-musl@1.8.3': resolution: {integrity: sha512-UHrGJX7PrKMKzPGoEsooKC9jXJMa28TUSMjcIlbDnIO4EAavCoVmNQaIuUSH0Ls2mpGMwUIf+aZJv657zfWWjA==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@biomejs/cli-linux-x64@1.8.3: + '@biomejs/cli-linux-x64@1.8.3': resolution: {integrity: sha512-I8G2QmuE1teISyT8ie1HXsjFRz9L1m5n83U1O6m30Kw+kPMPSKjag6QGUn+sXT8V+XWIZxFFBoTDEDZW2KPDDw==} engines: {node: '>=14.21.3'} cpu: [x64] os: [linux] - requiresBuild: true - dev: true - optional: true - /@biomejs/cli-win32-arm64@1.8.3: + '@biomejs/cli-win32-arm64@1.8.3': resolution: {integrity: sha512-J+Hu9WvrBevfy06eU1Na0lpc7uR9tibm9maHynLIoAjLZpQU3IW+OKHUtyL8p6/3pT2Ju5t5emReeIS2SAxhkQ==} engines: {node: '>=14.21.3'} cpu: [arm64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@biomejs/cli-win32-x64@1.8.3: + '@biomejs/cli-win32-x64@1.8.3': resolution: {integrity: sha512-/PJ59vA1pnQeKahemaQf4Nyj7IKUvGQSc3Ze1uIGi+Wvr1xF7rGobSrAAG01T/gUDG21vkDsZYM03NAmPiVkqg==} engines: {node: '>=14.21.3'} cpu: [x64] os: [win32] - requiresBuild: true - dev: true - optional: true - /@emnapi/runtime@1.2.0: + '@emnapi/runtime@1.2.0': resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==} - requiresBuild: true - dependencies: - tslib: 2.6.3 - dev: false - optional: true - /@esbuild/aix-ppc64@0.19.12: + '@esbuild/aix-ppc64@0.19.12': resolution: {integrity: sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] - requiresBuild: true - dev: false - optional: true - /@esbuild/aix-ppc64@0.21.5: + '@esbuild/aix-ppc64@0.21.5': resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] - requiresBuild: true - dev: false - optional: true - /@esbuild/android-arm64@0.19.12: + '@esbuild/aix-ppc64@0.24.0': + resolution: {integrity: sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.19.12': resolution: {integrity: sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==} engines: {node: '>=12'} cpu: [arm64] os: [android] - requiresBuild: true - dev: false - optional: true - /@esbuild/android-arm64@0.21.5: + '@esbuild/android-arm64@0.21.5': resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] - requiresBuild: true - dev: false - optional: true - /@esbuild/android-arm@0.19.12: + '@esbuild/android-arm64@0.24.0': + resolution: {integrity: sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.19.12': resolution: {integrity: sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==} engines: {node: '>=12'} cpu: [arm] os: [android] - requiresBuild: true - dev: false - optional: true - /@esbuild/android-arm@0.21.5: + '@esbuild/android-arm@0.21.5': resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] - requiresBuild: true - dev: false - optional: true - /@esbuild/android-x64@0.19.12: + '@esbuild/android-arm@0.24.0': + resolution: {integrity: sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.19.12': resolution: {integrity: sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==} engines: {node: '>=12'} cpu: [x64] os: [android] - requiresBuild: true - dev: false - optional: true - /@esbuild/android-x64@0.21.5: + '@esbuild/android-x64@0.21.5': resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] - requiresBuild: true - dev: false - optional: true - /@esbuild/darwin-arm64@0.19.12: + '@esbuild/android-x64@0.24.0': + resolution: {integrity: sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.19.12': resolution: {integrity: sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: false - optional: true - /@esbuild/darwin-arm64@0.21.5: + '@esbuild/darwin-arm64@0.21.5': resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: false - optional: true - /@esbuild/darwin-x64@0.19.12: + '@esbuild/darwin-arm64@0.24.0': + resolution: {integrity: sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.19.12': resolution: {integrity: sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: false - optional: true - /@esbuild/darwin-x64@0.21.5: + '@esbuild/darwin-x64@0.21.5': resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: false - optional: true - /@esbuild/freebsd-arm64@0.19.12: + '@esbuild/darwin-x64@0.24.0': + resolution: {integrity: sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.19.12': resolution: {integrity: sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - requiresBuild: true - dev: false - optional: true - /@esbuild/freebsd-arm64@0.21.5: + '@esbuild/freebsd-arm64@0.21.5': resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] - requiresBuild: true - dev: false - optional: true - /@esbuild/freebsd-x64@0.19.12: + '@esbuild/freebsd-arm64@0.24.0': + resolution: {integrity: sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.19.12': resolution: {integrity: sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - requiresBuild: true - dev: false - optional: true - /@esbuild/freebsd-x64@0.21.5: + '@esbuild/freebsd-x64@0.21.5': resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-arm64@0.19.12: + '@esbuild/freebsd-x64@0.24.0': + resolution: {integrity: sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.19.12': resolution: {integrity: sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-arm64@0.21.5: + '@esbuild/linux-arm64@0.21.5': resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-arm@0.19.12: + '@esbuild/linux-arm64@0.24.0': + resolution: {integrity: sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.19.12': resolution: {integrity: sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==} engines: {node: '>=12'} cpu: [arm] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-arm@0.21.5: + '@esbuild/linux-arm@0.21.5': resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-ia32@0.19.12: + '@esbuild/linux-arm@0.24.0': + resolution: {integrity: sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.19.12': resolution: {integrity: sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-ia32@0.21.5: + '@esbuild/linux-ia32@0.21.5': resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-loong64@0.19.12: + '@esbuild/linux-ia32@0.24.0': + resolution: {integrity: sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.19.12': resolution: {integrity: sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-loong64@0.21.5: + '@esbuild/linux-loong64@0.21.5': resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-mips64el@0.19.12: + '@esbuild/linux-loong64@0.24.0': + resolution: {integrity: sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.19.12': resolution: {integrity: sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-mips64el@0.21.5: + '@esbuild/linux-mips64el@0.21.5': resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-ppc64@0.19.12: + '@esbuild/linux-mips64el@0.24.0': + resolution: {integrity: sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.19.12': resolution: {integrity: sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-ppc64@0.21.5: + '@esbuild/linux-ppc64@0.21.5': resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-riscv64@0.19.12: + '@esbuild/linux-ppc64@0.24.0': + resolution: {integrity: sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.19.12': resolution: {integrity: sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-riscv64@0.21.5: + '@esbuild/linux-riscv64@0.21.5': resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-s390x@0.19.12: + '@esbuild/linux-riscv64@0.24.0': + resolution: {integrity: sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.19.12': resolution: {integrity: sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-s390x@0.21.5: + '@esbuild/linux-s390x@0.21.5': resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-x64@0.19.12: + '@esbuild/linux-s390x@0.24.0': + resolution: {integrity: sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.19.12': resolution: {integrity: sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==} engines: {node: '>=12'} cpu: [x64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/linux-x64@0.21.5: + '@esbuild/linux-x64@0.21.5': resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@esbuild/netbsd-x64@0.19.12: + '@esbuild/linux-x64@0.24.0': + resolution: {integrity: sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-x64@0.19.12': resolution: {integrity: sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - requiresBuild: true - dev: false - optional: true - /@esbuild/netbsd-x64@0.21.5: + '@esbuild/netbsd-x64@0.21.5': resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] - requiresBuild: true - dev: false - optional: true - /@esbuild/openbsd-x64@0.19.12: + '@esbuild/netbsd-x64@0.24.0': + resolution: {integrity: sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.24.0': + resolution: {integrity: sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.19.12': resolution: {integrity: sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - requiresBuild: true - dev: false - optional: true - /@esbuild/openbsd-x64@0.21.5: + '@esbuild/openbsd-x64@0.21.5': resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] - requiresBuild: true - dev: false - optional: true - /@esbuild/sunos-x64@0.19.12: + '@esbuild/openbsd-x64@0.24.0': + resolution: {integrity: sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.19.12': resolution: {integrity: sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - requiresBuild: true - dev: false - optional: true - /@esbuild/sunos-x64@0.21.5: + '@esbuild/sunos-x64@0.21.5': resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] - requiresBuild: true - dev: false - optional: true - /@esbuild/win32-arm64@0.19.12: + '@esbuild/sunos-x64@0.24.0': + resolution: {integrity: sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.19.12': resolution: {integrity: sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - requiresBuild: true - dev: false - optional: true - /@esbuild/win32-arm64@0.21.5: + '@esbuild/win32-arm64@0.21.5': resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] - requiresBuild: true - dev: false - optional: true - /@esbuild/win32-ia32@0.19.12: + '@esbuild/win32-arm64@0.24.0': + resolution: {integrity: sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.19.12': resolution: {integrity: sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - requiresBuild: true - dev: false - optional: true - /@esbuild/win32-ia32@0.21.5: + '@esbuild/win32-ia32@0.21.5': resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] - requiresBuild: true - dev: false - optional: true - /@esbuild/win32-x64@0.19.12: + '@esbuild/win32-ia32@0.24.0': + resolution: {integrity: sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.19.12': resolution: {integrity: sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==} engines: {node: '>=12'} cpu: [x64] os: [win32] - requiresBuild: true - dev: false - optional: true - /@esbuild/win32-x64@0.21.5: + '@esbuild/win32-x64@0.21.5': resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] - requiresBuild: true - dev: false - optional: true - /@img/sharp-darwin-arm64@0.33.4: + '@esbuild/win32-x64@0.24.0': + resolution: {integrity: sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@img/sharp-darwin-arm64@0.33.4': resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [darwin] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.0.2 - dev: false - optional: true - /@img/sharp-darwin-x64@0.33.4: + '@img/sharp-darwin-x64@0.33.4': resolution: {integrity: sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [darwin] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.0.2 - dev: false - optional: true - /@img/sharp-libvips-darwin-arm64@1.0.2: + '@img/sharp-libvips-darwin-arm64@1.0.2': resolution: {integrity: sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==} engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [darwin] - requiresBuild: true - dev: false - optional: true - /@img/sharp-libvips-darwin-x64@1.0.2: + '@img/sharp-libvips-darwin-x64@1.0.2': resolution: {integrity: sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==} engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [darwin] - requiresBuild: true - dev: false - optional: true - /@img/sharp-libvips-linux-arm64@1.0.2: + '@img/sharp-libvips-linux-arm64@1.0.2': resolution: {integrity: sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==} engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@img/sharp-libvips-linux-arm@1.0.2: + '@img/sharp-libvips-linux-arm@1.0.2': resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==} engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm] os: [linux] - requiresBuild: true - dev: false - optional: true - /@img/sharp-libvips-linux-s390x@1.0.2: + '@img/sharp-libvips-linux-s390x@1.0.2': resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==} engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [s390x] os: [linux] - requiresBuild: true - dev: false - optional: true - /@img/sharp-libvips-linux-x64@1.0.2: + '@img/sharp-libvips-linux-x64@1.0.2': resolution: {integrity: sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==} engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@img/sharp-libvips-linuxmusl-arm64@1.0.2: + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': resolution: {integrity: sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==} engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@img/sharp-libvips-linuxmusl-x64@1.0.2: + '@img/sharp-libvips-linuxmusl-x64@1.0.2': resolution: {integrity: sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==} engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] - requiresBuild: true - dev: false - optional: true - /@img/sharp-linux-arm64@0.33.4: + '@img/sharp-linux-arm64@0.33.4': resolution: {integrity: sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linux-arm64': 1.0.2 - dev: false - optional: true - /@img/sharp-linux-arm@0.33.4: + '@img/sharp-linux-arm@0.33.4': resolution: {integrity: sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==} engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm] os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linux-arm': 1.0.2 - dev: false - optional: true - /@img/sharp-linux-s390x@0.33.4: + '@img/sharp-linux-s390x@0.33.4': resolution: {integrity: sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==} engines: {glibc: '>=2.31', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [s390x] os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linux-s390x': 1.0.2 - dev: false - optional: true - /@img/sharp-linux-x64@0.33.4: + '@img/sharp-linux-x64@0.33.4': resolution: {integrity: sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linux-x64': 1.0.2 - dev: false - optional: true - /@img/sharp-linuxmusl-arm64@0.33.4: + '@img/sharp-linuxmusl-arm64@0.33.4': resolution: {integrity: sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 - dev: false - optional: true - /@img/sharp-linuxmusl-x64@0.33.4: + '@img/sharp-linuxmusl-x64@0.33.4': resolution: {integrity: sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.0.2 - dev: false - optional: true - /@img/sharp-wasm32@0.33.4: + '@img/sharp-wasm32@0.33.4': resolution: {integrity: sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [wasm32] - requiresBuild: true - dependencies: - '@emnapi/runtime': 1.2.0 - dev: false - optional: true - /@img/sharp-win32-ia32@0.33.4: + '@img/sharp-win32-ia32@0.33.4': resolution: {integrity: sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [ia32] os: [win32] - requiresBuild: true - dev: false - optional: true - /@img/sharp-win32-x64@0.33.4: + '@img/sharp-win32-x64@0.33.4': resolution: {integrity: sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [win32] - requiresBuild: true - dev: false - optional: true - /@isaacs/cliui@8.0.2: + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.4.15': + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@oslojs/encoding@1.1.0': + resolution: {integrity: sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@rollup/pluginutils@5.1.3': + resolution: {integrity: sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + + '@rollup/rollup-android-arm-eabi@4.28.1': + resolution: {integrity: sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.28.1': + resolution: {integrity: sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.28.1': + resolution: {integrity: sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.28.1': + resolution: {integrity: sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.28.1': + resolution: {integrity: sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.28.1': + resolution: {integrity: sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.28.1': + resolution: {integrity: sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.28.1': + resolution: {integrity: sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.28.1': + resolution: {integrity: sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.28.1': + resolution: {integrity: sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.28.1': + resolution: {integrity: sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.28.1': + resolution: {integrity: sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.28.1': + resolution: {integrity: sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.28.1': + resolution: {integrity: sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.28.1': + resolution: {integrity: sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.28.1': + resolution: {integrity: sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.28.1': + resolution: {integrity: sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.28.1': + resolution: {integrity: sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.28.1': + resolution: {integrity: sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==} + cpu: [x64] + os: [win32] + + '@shikijs/core@1.24.2': + resolution: {integrity: sha512-BpbNUSKIwbKrRRA+BQj0BEWSw+8kOPKDJevWeSE/xIqGX7K0xrCZQ9kK0nnEQyrzsUoka1l81ZtJ2mGaCA32HQ==} + + '@shikijs/engine-javascript@1.24.2': + resolution: {integrity: sha512-EqsmYBJdLEwEiO4H+oExz34a5GhhnVp+jH9Q/XjPjmBPc6TE/x4/gD0X3i0EbkKKNqXYHHJTJUpOLRQNkEzS9Q==} + + '@shikijs/engine-oniguruma@1.24.2': + resolution: {integrity: sha512-ZN6k//aDNWRJs1uKB12pturKHh7GejKugowOFGAuG7TxDRLod1Bd5JhpOikOiFqPmKjKEPtEA6mRCf7q3ulDyQ==} + + '@shikijs/types@1.24.2': + resolution: {integrity: sha512-bdeWZiDtajGLG9BudI0AHet0b6e7FbR0EsE4jpGaI0YwHm/XJunI9+3uZnzFtX65gsyJ6ngCIWUfA4NWRPnBkQ==} + + '@shikijs/vscode-textmate@9.3.1': + resolution: {integrity: sha512-79QfK1393x9Ho60QFyLti+QfdJzRQCVLFb97kOIV7Eo9vQU/roINgk7m24uv0a7AUvN//RDH36FLjjK48v0s9g==} + + '@types/cookie@0.6.0': + resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + + '@types/debug@4.1.7': + resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} + + '@types/estree@1.0.5': + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/hast@3.0.1': + resolution: {integrity: sha512-hs/iBJx2aydugBQx5ETV3ZgeSS0oIreQrFJ4bjBl0XvM4wAmDjFEALY7p0rTSLt2eL+ibjRAAs9dTPiCLtmbqQ==} + + '@types/hast@3.0.4': + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + + '@types/mdast@4.0.1': + resolution: {integrity: sha512-IlKct1rUTJ1T81d8OHzyop15kGv9A/ff7Gz7IJgrk6jDb4Udw77pCJ+vq8oxZf4Ghpm+616+i1s/LNg/Vh7d+g==} + + '@types/ms@0.7.31': + resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + + '@types/nlcst@2.0.3': + resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + + '@types/unist@3.0.0': + resolution: {integrity: sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==} + + '@ungap/structured-clone@1.2.0': + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + + acorn@8.14.0: + resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} + engines: {node: '>=0.4.0'} + hasBin: true + + ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-iterate@2.0.1: + resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} + + astro@5.0.5: + resolution: {integrity: sha512-xfptdmurDsQcj/Anc7mU+eKlcyV7ppJIlmaSwhX3ZWwK5N/0rGKVmUqnuILgR6MB0XVJiIfublNzDGoyj4Q6BQ==} + engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} + hasBin: true + + autoprefixer@10.4.19: + resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + bail@2.0.2: + resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + base-64@1.0.0: + resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} + + binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + + boxen@8.0.1: + resolution: {integrity: sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==} + engines: {node: '>=18'} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.23.1: + resolution: {integrity: sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + camelcase@8.0.0: + resolution: {integrity: sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==} + engines: {node: '>=16'} + + caniuse-lite@1.0.30001634: + resolution: {integrity: sha512-fbBYXQ9q3+yp1q1gBk86tOFs4pyn/yxFm5ZNP18OXJDfA3txImOY9PhfxVggZ4vRHDqoU8NrKU81eN0OtzOgRA==} + + ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + + character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + + character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + + character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + ci-info@4.1.0: + resolution: {integrity: sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==} + engines: {node: '>=8'} + + cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@4.2.3: + resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} + engines: {node: '>=12.5.0'} + + comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + common-ancestor-path@1.0.1: + resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + + cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + detect-libc@2.0.3: + resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} + engines: {node: '>=8'} + + deterministic-object-hash@2.0.2: + resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} + engines: {node: '>=18'} + + devalue@5.1.1: + resolution: {integrity: sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==} + + devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + electron-to-chromium@1.4.803: + resolution: {integrity: sha512-61H9mLzGOCLLVsnLiRzCbc63uldP0AniRYPV3hbGVtONA1pI7qSGILdbofR7A8TMbOypDocEAjH/e+9k1QIe3g==} + + emoji-regex-xs@1.0.0: + resolution: {integrity: sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg==} + + emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} + + esbuild@0.19.12: + resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} + engines: {node: '>=12'} + hasBin: true + + esbuild@0.24.0: + resolution: {integrity: sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.1.2: + resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + engines: {node: '>=6'} + + escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + + extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + + fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + + fast-xml-parser@4.4.0: + resolution: {integrity: sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==} + hasBin: true + + fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up-simple@1.0.0: + resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} + engines: {node: '>=18'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-yarn-workspace-root2@1.2.16: + resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + + flattie@1.1.1: + resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} + engines: {node: '>=8'} + + foreground-child@3.2.1: + resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} + engines: {node: '>=14'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.1: + resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} + + gemoji@4.2.1: + resolution: {integrity: sha512-V9lUpRSn+KQGavZx8Pk+6mxG3kaz21ae2kTCXuT36KaRPNgYU8eHtj/RcUCNFVvmwppsYYz3nnNS9lmcP5kTsg==} + + get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + + github-slugger@2.0.0: + resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob@10.4.1: + resolution: {integrity: sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==} + engines: {node: '>=16 || 14 >=14.18'} + hasBin: true + + graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + + has@1.0.3: + resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} + engines: {node: '>= 0.4.0'} + + hast-util-from-html@2.0.1: + resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} + + hast-util-from-html@2.0.3: + resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} + + hast-util-from-parse5@8.0.1: + resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} + + hast-util-heading-rank@3.0.0: + resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} + + hast-util-is-element@1.1.0: + resolution: {integrity: sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==} + + hast-util-is-element@3.0.0: + resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + + hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + + hast-util-raw@9.0.1: + resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==} + + hast-util-to-html@9.0.0: + resolution: {integrity: sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==} + + hast-util-to-html@9.0.4: + resolution: {integrity: sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==} + + hast-util-to-parse5@8.0.0: + resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + + hast-util-to-string@3.0.0: + resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==} + + hast-util-to-text@4.0.2: + resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} + + hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + + hastscript@8.0.0: + resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + + html-escaper@3.0.3: + resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} + + html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + + http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-core-module@2.13.0: + resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} + + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@4.1.0: + resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} + engines: {node: '>=12'} + + is-wsl@3.1.0: + resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} + engines: {node: '>=16'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@3.4.0: + resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} + engines: {node: '>=14'} + + jiti@1.21.6: + resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} + hasBin: true + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + kleur@4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.2: + resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + load-yaml-file@0.2.0: + resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} + engines: {node: '>=6'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + + lru-cache@10.2.2: + resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} + engines: {node: 14 || >=16.14} + + magic-string@0.30.15: + resolution: {integrity: sha512-zXeaYRgZ6ldS1RJJUrMrYgNJ4fdwnyI6tVqoiIhyCyv5IVTK9BU8Ic2l253GGETQHxI4HNUwhJ3fjDhKqEoaAw==} + + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + + markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + + mdast-util-definitions@6.0.0: + resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} + + mdast-util-find-and-replace@3.0.1: + resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + + mdast-util-from-markdown@2.0.0: + resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + + mdast-util-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} + + mdast-util-gfm-footnote@2.0.0: + resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + + mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + + mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + + mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + + mdast-util-gfm@3.0.0: + resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + + mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + + mdast-util-to-hast@13.0.2: + resolution: {integrity: sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==} + + mdast-util-to-markdown@2.1.0: + resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + + mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromark-core-commonmark@2.0.1: + resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} + + micromark-extension-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==} + + micromark-extension-gfm-footnote@2.0.0: + resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==} + + micromark-extension-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==} + + micromark-extension-gfm-table@2.0.0: + resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==} + + micromark-extension-gfm-tagfilter@2.0.0: + resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + + micromark-extension-gfm-task-list-item@2.0.1: + resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==} + + micromark-extension-gfm@3.0.0: + resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + + micromark-factory-destination@2.0.0: + resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} + + micromark-factory-label@2.0.0: + resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + + micromark-factory-space@2.0.0: + resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} + + micromark-factory-title@2.0.0: + resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} + + micromark-factory-whitespace@2.0.0: + resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} + + micromark-util-character@2.0.1: + resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==} + + micromark-util-chunked@2.0.0: + resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} + + micromark-util-classify-character@2.0.0: + resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} + + micromark-util-combine-extensions@2.0.0: + resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} + + micromark-util-decode-numeric-character-reference@2.0.1: + resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} + + micromark-util-decode-string@2.0.0: + resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} + + micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + + micromark-util-html-tag-name@2.0.0: + resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} + + micromark-util-normalize-identifier@2.0.0: + resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} + + micromark-util-resolve-all@2.0.0: + resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} + + micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + + micromark-util-subtokenize@2.0.1: + resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==} + + micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + + micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + + micromark@4.0.0: + resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} + + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} + engines: {node: '>=8.6'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + minimatch@9.0.4: + resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + engines: {node: '>=16 || 14 >=14.17'} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mrmime@2.0.0: + resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + neotraverse@0.6.18: + resolution: {integrity: sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==} + engines: {node: '>= 10'} + + nlcst-to-string@4.0.0: + resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} + + node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + oniguruma-to-es@0.7.0: + resolution: {integrity: sha512-HRaRh09cE0gRS3+wi2zxekB+I5L8C/gN60S+vb11eADHUaB/q4u8wGGOX3GvwvitG8ixaeycZfeoyruKQzUgNg==} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@6.1.0: + resolution: {integrity: sha512-H0jc0q1vOzlEk0TqAKXKZxdl7kX3OFUzCnNVUnq5Pc3DGo0kpeaMuPqxQn235HibwBEb0/pm9dgKTjXy66fBkg==} + engines: {node: '>=18'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-queue@8.0.1: + resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} + engines: {node: '>=18'} + + p-timeout@6.1.2: + resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} + engines: {node: '>=14.16'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + parse-latin@7.0.0: + resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} + + parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + picocolors@1.0.1: + resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pify@4.0.1: + resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} + engines: {node: '>=6'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-nested@6.0.1: + resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-selector-parser@6.1.0: + resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.4.38: + resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} + engines: {node: ^10 || ^12 || >=14} + + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} + engines: {node: ^10 || ^12 || >=14} + + preferred-pm@4.0.0: + resolution: {integrity: sha512-gYBeFTZLu055D8Vv3cSPox/0iTPtkzxpLroSYYA7WXgRi31WCJ51Uyl8ZiPeUUjyvs2MBzK+S8v9JVUgHU/Sqw==} + engines: {node: '>=18.12'} + + prismjs@1.29.0: + resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} + engines: {node: '>=6'} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + property-information@6.2.0: + resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + regex-recursion@4.3.0: + resolution: {integrity: sha512-5LcLnizwjcQ2ALfOj95MjcatxyqF5RPySx9yT+PaXu3Gox2vyAtLDjHB8NTJLtMGkvyau6nI3CfpwFCjPUIs/A==} + + regex-utilities@2.3.0: + resolution: {integrity: sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==} + + regex@5.0.2: + resolution: {integrity: sha512-/pczGbKIQgfTMRV0XjABvc5RzLqQmwqxLHdQao2RTXPk+pmTXB2P0IaUHYdYyk412YLwUIkaeMd5T+RzVgTqnQ==} + + rehype-accessible-emojis@0.3.2: + resolution: {integrity: sha512-kChZo+EZsuFQYHUPu6kOZFjDrG7UtQdGxkrCvHBVo9ariKPL6S68QdPVxLxwcAtZSRZIXZhDuTJHgIM8KW24Qw==} + + rehype-autolink-headings@7.1.0: + resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==} + + rehype-parse@9.0.0: + resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==} + + rehype-raw@7.0.0: + resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + + rehype-slug@6.0.0: + resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} + + rehype-stringify@10.0.0: + resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==} + + rehype-stringify@10.0.1: + resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==} + + rehype@13.0.2: + resolution: {integrity: sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==} + + remark-gfm@4.0.0: + resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} + + remark-parse@11.0.0: + resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + + remark-rehype@11.1.1: + resolution: {integrity: sha512-g/osARvjkBXb6Wo0XvAeXQohVta8i84ACbenPpoSsxTOQH/Ae0/RGP4WZgnMH5pMLpsj4FG7OHmcIcXxpza8eQ==} + + remark-smartypants@3.0.2: + resolution: {integrity: sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==} + engines: {node: '>=16.0.0'} + + remark-stringify@11.0.0: + resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + + resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + + retext-latin@4.0.0: + resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==} + + retext-smartypants@6.1.0: + resolution: {integrity: sha512-LDPXg95346bqFZnDMHo0S7Rq5p64+B+N8Vz733+wPMDtwb9rCOs9LIdIEhrUOU+TAywX9St+ocQWJt8wrzivcQ==} + + retext-stringify@4.0.0: + resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==} + + retext@9.0.0: + resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} + + reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.28.1: + resolution: {integrity: sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + + sharp@0.33.4: + resolution: {integrity: sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==} + engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shiki@1.24.2: + resolution: {integrity: sha512-TR1fi6mkRrzW+SKT5G6uKuc32Dj2EEa7Kj0k8kGqiBINb+C1TiflVOiT9ta6GqOJtC4fraxO5SLUaKBcSY38Fg==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + source-map-js@1.2.0: + resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} + engines: {node: '>=0.10.0'} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string-width@7.2.0: + resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} + engines: {node: '>=18'} + + stringify-entities@4.0.3: + resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strnum@1.0.5: + resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tailwindcss@3.4.4: + resolution: {integrity: sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==} + engines: {node: '>=14.0.0'} + hasBin: true + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + + trough@2.1.0: + resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + tsconfck@3.1.4: + resolution: {integrity: sha512-kdqWFGVJqe+KGYvlSO9NIaWn9jT1Ny4oKVzAJsKii5eoE9snzTJzL4+MMVOMn+fikWGFmKEylcXL710V/kIPJQ==} + engines: {node: ^18 || >=20} + hasBin: true + peerDependencies: + typescript: ^5.0.0 + peerDependenciesMeta: + typescript: + optional: true + + tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + + type-fest@4.30.1: + resolution: {integrity: sha512-ojFL7eDMX2NF0xMbDwPZJ8sb7ckqtlAi1GsmgsFXvErT9kFTk1r0DuQKvrCh73M6D4nngeHJmvogF9OluXs7Hw==} + engines: {node: '>=16'} + + typescript@5.7.2: + resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} + engines: {node: '>=14.17'} + hasBin: true + + ultrahtml@1.5.3: + resolution: {integrity: sha512-GykOvZwgDWZlTQMtp5jrD4BVL+gNn2NVlVafjcFUJ7taY20tqYdwdoWBFy6GBJsNTZe1GkGPkSl5knQAjtgceg==} + + unified@11.0.4: + resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} + + unified@11.0.5: + resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + + unist-util-find-after@5.0.0: + resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + + unist-util-flatmap@1.0.0: + resolution: {integrity: sha512-IG32jcKJlhARCYT2LsYPJWdoXYkzz3ESAdl1aa2hn9Auh+cgUmU6wgkII4yCc/1GgeWibRdELdCZh/p3QKQ1dQ==} + + unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + + unist-util-modify-children@4.0.0: + resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==} + + unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + + unist-util-remove-position@5.0.0: + resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + + unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + + unist-util-visit-children@3.0.0: + resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==} + + unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + + unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + + update-browserslist-db@1.0.16: + resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vfile-location@5.0.2: + resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} + + vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + + vfile@6.0.1: + resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} + + vfile@6.0.3: + resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==} + + vite@6.0.3: + resolution: {integrity: sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitefu@1.0.4: + resolution: {integrity: sha512-y6zEE3PQf6uu/Mt6DTJ9ih+kyJLr4XcSgHR2zUkM8SWDhuixEJxfJ6CZGMHh1Ec3vPLoEA0IHU5oWzVqw8ulow==} + peerDependencies: + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + vite: + optional: true + + web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + + which-pm-runs@1.1.0: + resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} + engines: {node: '>=4'} + + which-pm@3.0.0: + resolution: {integrity: sha512-ysVYmw6+ZBhx3+ZkcPwRuJi38ZOTLJJ33PSHaitLxSKUMsh0LkKd0nC69zZCwt5D+AYUcMK2hhw4yWny20vSGg==} + engines: {node: '>=18.12'} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + widest-line@5.0.0: + resolution: {integrity: sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==} + engines: {node: '>=18'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + + xxhash-wasm@1.1.0: + resolution: {integrity: sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==} + + yaml@2.4.5: + resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yocto-queue@1.1.1: + resolution: {integrity: sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==} + engines: {node: '>=12.20'} + + yocto-spinner@0.1.2: + resolution: {integrity: sha512-VfmLIh/ZSZOJnVRQZc/dvpPP90lWL4G0bmxQMP0+U/2vKBA8GSpcBuWv17y7F+CZItRuO97HN1wdbb4p10uhOg==} + engines: {node: '>=18.19'} + + yoctocolors@2.1.1: + resolution: {integrity: sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==} + engines: {node: '>=18'} + + zod-to-json-schema@3.24.1: + resolution: {integrity: sha512-3h08nf3Vw3Wl3PK+q3ow/lIil81IT2Oa7YpQyUUDsEWbXveMesdfK1xBd2RhCkynwZndAxixji/7SYJJowr62w==} + peerDependencies: + zod: ^3.24.1 + + zod-to-ts@1.2.0: + resolution: {integrity: sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==} + peerDependencies: + typescript: ^4.9.4 || ^5.0.2 + zod: ^3 + + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + + zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + +snapshots: + + '@alloc/quick-lru@5.2.0': {} + + '@astrojs/compiler@2.10.3': {} + + '@astrojs/deno@5.0.1(astro@5.0.5)': + dependencies: + astro: 5.0.5(typescript@5.7.2) + esbuild: 0.19.12 + + '@astrojs/internal-helpers@0.4.2': {} + + '@astrojs/markdown-remark@6.0.1': + dependencies: + '@astrojs/prism': 3.2.0 + github-slugger: 2.0.0 + hast-util-from-html: 2.0.3 + hast-util-to-text: 4.0.2 + import-meta-resolve: 4.1.0 + js-yaml: 4.1.0 + mdast-util-definitions: 6.0.0 + rehype-raw: 7.0.0 + rehype-stringify: 10.0.1 + remark-gfm: 4.0.0 + remark-parse: 11.0.0 + remark-rehype: 11.1.1 + remark-smartypants: 3.0.2 + shiki: 1.24.2 + unified: 11.0.5 + unist-util-remove-position: 5.0.0 + unist-util-visit: 5.0.0 + unist-util-visit-parents: 6.0.1 + vfile: 6.0.3 + transitivePeerDependencies: + - supports-color + + '@astrojs/prism@3.2.0': + dependencies: + prismjs: 1.29.0 + + '@astrojs/rss@4.0.7': + dependencies: + fast-xml-parser: 4.4.0 + kleur: 4.1.5 + + '@astrojs/tailwind@5.1.0(astro@5.0.5)(tailwindcss@3.4.4)': + dependencies: + astro: 5.0.5(typescript@5.7.2) + autoprefixer: 10.4.19(postcss@8.4.38) + postcss: 8.4.38 + postcss-load-config: 4.0.2(postcss@8.4.38) + tailwindcss: 3.4.4 + transitivePeerDependencies: + - ts-node + + '@astrojs/telemetry@3.2.0': + dependencies: + ci-info: 4.1.0 + debug: 4.4.0 + dlv: 1.1.3 + dset: 3.1.4 + is-docker: 3.0.0 + is-wsl: 3.1.0 + which-pm-runs: 1.1.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/parser@7.26.3': + dependencies: + '@babel/types': 7.26.3 + + '@babel/types@7.26.3': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@biomejs/biome@1.8.3': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 1.8.3 + '@biomejs/cli-darwin-x64': 1.8.3 + '@biomejs/cli-linux-arm64': 1.8.3 + '@biomejs/cli-linux-arm64-musl': 1.8.3 + '@biomejs/cli-linux-x64': 1.8.3 + '@biomejs/cli-linux-x64-musl': 1.8.3 + '@biomejs/cli-win32-arm64': 1.8.3 + '@biomejs/cli-win32-x64': 1.8.3 + + '@biomejs/cli-darwin-arm64@1.8.3': + optional: true + + '@biomejs/cli-darwin-x64@1.8.3': + optional: true + + '@biomejs/cli-linux-arm64-musl@1.8.3': + optional: true + + '@biomejs/cli-linux-arm64@1.8.3': + optional: true + + '@biomejs/cli-linux-x64-musl@1.8.3': + optional: true + + '@biomejs/cli-linux-x64@1.8.3': + optional: true + + '@biomejs/cli-win32-arm64@1.8.3': + optional: true + + '@biomejs/cli-win32-x64@1.8.3': + optional: true + + '@emnapi/runtime@1.2.0': + dependencies: + tslib: 2.6.3 + optional: true + + '@esbuild/aix-ppc64@0.19.12': + optional: true + + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.24.0': + optional: true + + '@esbuild/android-arm64@0.19.12': + optional: true + + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.24.0': + optional: true + + '@esbuild/android-arm@0.19.12': + optional: true + + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.24.0': + optional: true + + '@esbuild/android-x64@0.19.12': + optional: true + + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.24.0': + optional: true + + '@esbuild/darwin-arm64@0.19.12': + optional: true + + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.24.0': + optional: true + + '@esbuild/darwin-x64@0.19.12': + optional: true + + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.24.0': + optional: true + + '@esbuild/freebsd-arm64@0.19.12': + optional: true + + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.24.0': + optional: true + + '@esbuild/freebsd-x64@0.19.12': + optional: true + + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.24.0': + optional: true + + '@esbuild/linux-arm64@0.19.12': + optional: true + + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.24.0': + optional: true + + '@esbuild/linux-arm@0.19.12': + optional: true + + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.24.0': + optional: true + + '@esbuild/linux-ia32@0.19.12': + optional: true + + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.24.0': + optional: true + + '@esbuild/linux-loong64@0.19.12': + optional: true + + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.24.0': + optional: true + + '@esbuild/linux-mips64el@0.19.12': + optional: true + + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.24.0': + optional: true + + '@esbuild/linux-ppc64@0.19.12': + optional: true + + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.24.0': + optional: true + + '@esbuild/linux-riscv64@0.19.12': + optional: true + + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.24.0': + optional: true + + '@esbuild/linux-s390x@0.19.12': + optional: true + + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.24.0': + optional: true + + '@esbuild/linux-x64@0.19.12': + optional: true + + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.24.0': + optional: true + + '@esbuild/netbsd-x64@0.19.12': + optional: true + + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.24.0': + optional: true + + '@esbuild/openbsd-arm64@0.24.0': + optional: true + + '@esbuild/openbsd-x64@0.19.12': + optional: true + + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.24.0': + optional: true + + '@esbuild/sunos-x64@0.19.12': + optional: true + + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.24.0': + optional: true + + '@esbuild/win32-arm64@0.19.12': + optional: true + + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.24.0': + optional: true + + '@esbuild/win32-ia32@0.19.12': + optional: true + + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.24.0': + optional: true + + '@esbuild/win32-x64@0.19.12': + optional: true + + '@esbuild/win32-x64@0.21.5': + optional: true + + '@esbuild/win32-x64@0.24.0': + optional: true + + '@img/sharp-darwin-arm64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.2 + optional: true + + '@img/sharp-darwin-x64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.2 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-darwin-x64@1.0.2': + optional: true + + '@img/sharp-libvips-linux-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-linux-arm@1.0.2': + optional: true + + '@img/sharp-libvips-linux-s390x@1.0.2': + optional: true + + '@img/sharp-libvips-linux-x64@1.0.2': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.0.2': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.0.2': + optional: true + + '@img/sharp-linux-arm64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.0.2 + optional: true + + '@img/sharp-linux-arm@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.0.2 + optional: true + + '@img/sharp-linux-s390x@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.0.2 + optional: true + + '@img/sharp-linux-x64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.0.2 + optional: true + + '@img/sharp-linuxmusl-arm64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 + optional: true + + '@img/sharp-linuxmusl-x64@0.33.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.0.2 + optional: true + + '@img/sharp-wasm32@0.33.4': + dependencies: + '@emnapi/runtime': 1.2.0 + optional: true + + '@img/sharp-win32-ia32@0.33.4': + optional: true + + '@img/sharp-win32-x64@0.33.4': + optional: true + + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 + string-width-cjs: string-width@4.2.3 strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 + strip-ansi-cjs: strip-ansi@6.0.1 wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: false + wrap-ansi-cjs: wrap-ansi@7.0.0 - /@jridgewell/gen-mapping@0.1.1: - resolution: {integrity: sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.4.15 - dev: false - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.5': dependencies: '@jridgewell/set-array': 1.2.1 '@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/trace-mapping': 0.3.25 - dev: false - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: false + '@jridgewell/resolve-uri@3.1.2': {} - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: false + '@jridgewell/set-array@1.2.1': {} - /@jridgewell/sourcemap-codec@1.4.15: - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: false + '@jridgewell/sourcemap-codec@1.4.15': {} - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - dev: false - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: false - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: false + '@nodelib/fs.stat@2.0.5': {} - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} + '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.15.0 - dev: false - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: false + '@oslojs/encoding@1.1.0': {} + + '@pkgjs/parseargs@0.11.0': optional: true - /@rollup/rollup-android-arm-eabi@4.17.2: - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} - cpu: [arm] - os: [android] - requiresBuild: true - dev: false + '@rollup/pluginutils@5.1.3': + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 4.0.2 + + '@rollup/rollup-android-arm-eabi@4.28.1': optional: true - /@rollup/rollup-android-arm64@4.17.2: - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} - cpu: [arm64] - os: [android] - requiresBuild: true - dev: false + '@rollup/rollup-android-arm64@4.28.1': optional: true - /@rollup/rollup-darwin-arm64@4.17.2: - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: false + '@rollup/rollup-darwin-arm64@4.28.1': optional: true - /@rollup/rollup-darwin-x64@4.17.2: - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: false + '@rollup/rollup-darwin-x64@4.28.1': optional: true - /@rollup/rollup-linux-arm-gnueabihf@4.17.2: - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: false + '@rollup/rollup-freebsd-arm64@4.28.1': optional: true - /@rollup/rollup-linux-arm-musleabihf@4.17.2: - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} - cpu: [arm] - os: [linux] - requiresBuild: true - dev: false + '@rollup/rollup-freebsd-x64@4.28.1': optional: true - /@rollup/rollup-linux-arm64-gnu@4.17.2: - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false + '@rollup/rollup-linux-arm-gnueabihf@4.28.1': optional: true - /@rollup/rollup-linux-arm64-musl@4.17.2: - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: false + '@rollup/rollup-linux-arm-musleabihf@4.28.1': optional: true - /@rollup/rollup-linux-powerpc64le-gnu@4.17.2: - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} - cpu: [ppc64] - os: [linux] - requiresBuild: true - dev: false + '@rollup/rollup-linux-arm64-gnu@4.28.1': optional: true - /@rollup/rollup-linux-riscv64-gnu@4.17.2: - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} - cpu: [riscv64] - os: [linux] - requiresBuild: true - dev: false + '@rollup/rollup-linux-arm64-musl@4.28.1': optional: true - /@rollup/rollup-linux-s390x-gnu@4.17.2: - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} - cpu: [s390x] - os: [linux] - requiresBuild: true - dev: false + '@rollup/rollup-linux-loongarch64-gnu@4.28.1': optional: true - /@rollup/rollup-linux-x64-gnu@4.17.2: - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false + '@rollup/rollup-linux-powerpc64le-gnu@4.28.1': optional: true - /@rollup/rollup-linux-x64-musl@4.17.2: - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: false + '@rollup/rollup-linux-riscv64-gnu@4.28.1': optional: true - /@rollup/rollup-win32-arm64-msvc@4.17.2: - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: false + '@rollup/rollup-linux-s390x-gnu@4.28.1': optional: true - /@rollup/rollup-win32-ia32-msvc@4.17.2: - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: false + '@rollup/rollup-linux-x64-gnu@4.28.1': optional: true - /@rollup/rollup-win32-x64-msvc@4.17.2: - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: false + '@rollup/rollup-linux-x64-musl@4.28.1': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.28.1': optional: true - /@shikijs/core@1.9.1: - resolution: {integrity: sha512-EmUful2MQtY8KgCF1OkBtOuMcvaZEvmdubhW0UHCGXi21O9dRLeADVCj+k6ZS+de7Mz9d2qixOXJ+GLhcK3pXg==} - dev: false + '@rollup/rollup-win32-ia32-msvc@4.28.1': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.28.1': + optional: true - /@types/babel__core@7.20.5: - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + '@shikijs/core@1.24.2': dependencies: - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 - '@types/babel__generator': 7.6.4 - '@types/babel__template': 7.4.1 - '@types/babel__traverse': 7.18.3 - dev: false + '@shikijs/engine-javascript': 1.24.2 + '@shikijs/engine-oniguruma': 1.24.2 + '@shikijs/types': 1.24.2 + '@shikijs/vscode-textmate': 9.3.1 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.4 - /@types/babel__generator@7.6.4: - resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} + '@shikijs/engine-javascript@1.24.2': dependencies: - '@babel/types': 7.24.7 - dev: false + '@shikijs/types': 1.24.2 + '@shikijs/vscode-textmate': 9.3.1 + oniguruma-to-es: 0.7.0 - /@types/babel__template@7.4.1: - resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} + '@shikijs/engine-oniguruma@1.24.2': dependencies: - '@babel/parser': 7.24.7 - '@babel/types': 7.24.7 - dev: false + '@shikijs/types': 1.24.2 + '@shikijs/vscode-textmate': 9.3.1 - /@types/babel__traverse@7.18.3: - resolution: {integrity: sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==} + '@shikijs/types@1.24.2': dependencies: - '@babel/types': 7.24.7 - dev: false + '@shikijs/vscode-textmate': 9.3.1 + '@types/hast': 3.0.4 - /@types/cookie@0.6.0: - resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} - dev: false + '@shikijs/vscode-textmate@9.3.1': {} - /@types/debug@4.1.7: - resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} + '@types/cookie@0.6.0': {} + + '@types/debug@4.1.7': dependencies: '@types/ms': 0.7.31 - dev: false - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - dev: false + '@types/estree@1.0.5': {} - /@types/hast@3.0.1: - resolution: {integrity: sha512-hs/iBJx2aydugBQx5ETV3ZgeSS0oIreQrFJ4bjBl0XvM4wAmDjFEALY7p0rTSLt2eL+ibjRAAs9dTPiCLtmbqQ==} + '@types/estree@1.0.6': {} + + '@types/hast@3.0.1': dependencies: '@types/unist': 3.0.0 - dev: false - /@types/mdast@4.0.1: - resolution: {integrity: sha512-IlKct1rUTJ1T81d8OHzyop15kGv9A/ff7Gz7IJgrk6jDb4Udw77pCJ+vq8oxZf4Ghpm+616+i1s/LNg/Vh7d+g==} + '@types/hast@3.0.4': dependencies: '@types/unist': 3.0.0 - dev: false - /@types/ms@0.7.31: - resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} - dev: false + '@types/mdast@4.0.1': + dependencies: + '@types/unist': 3.0.0 - /@types/nlcst@2.0.3: - resolution: {integrity: sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==} + '@types/ms@0.7.31': {} + + '@types/nlcst@2.0.3': dependencies: '@types/unist': 3.0.0 - dev: false - /@types/unist@3.0.0: - resolution: {integrity: sha512-MFETx3tbTjE7Uk6vvnWINA/1iJ7LuMdO4fcq8UfF0pRbj01aGLduVvQcRyswuACJdpnHgg8E3rQLhaRdNEJS0w==} - dev: false + '@types/unist@3.0.0': {} - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: false + '@ungap/structured-clone@1.2.0': {} - /acorn@8.12.0: - resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: false + acorn@8.14.0: {} - /ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + ansi-align@3.0.1: dependencies: string-width: 4.2.3 - dev: false - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - dev: false - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: false + ansi-regex@5.0.1: {} - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: false + ansi-regex@6.0.1: {} - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} + ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 - dev: false - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: false + ansi-styles@6.2.1: {} - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: false + any-promise@1.3.0: {} - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} + anymatch@3.1.3: dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 - dev: false - /arg@5.0.2: - resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} - dev: false + arg@5.0.2: {} - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@1.0.10: dependencies: sprintf-js: 1.0.3 - dev: false - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: false + argparse@2.0.1: {} - /aria-query@5.3.0: - resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - dependencies: - dequal: 2.0.3 - dev: false + aria-query@5.3.2: {} - /array-iterate@2.0.1: - resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} - dev: false + array-iterate@2.0.1: {} - /astro@4.11.3: - resolution: {integrity: sha512-SuZbB/71XVn+WqWNCe7XOfHuqhS+k4gj8+A3wluTZQrORGaHUFRn/f8F9Tu5yESQZB1q8UKhahvHwkTV3AdVsg==} - engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} - hasBin: true + astro@5.0.5(typescript@5.7.2): dependencies: - '@astrojs/compiler': 2.8.1 - '@astrojs/internal-helpers': 0.4.1 - '@astrojs/markdown-remark': 5.1.1 - '@astrojs/telemetry': 3.1.0 - '@babel/core': 7.24.7 - '@babel/generator': 7.24.7 - '@babel/parser': 7.24.7 - '@babel/plugin-transform-react-jsx': 7.24.7(@babel/core@7.24.7) - '@babel/traverse': 7.24.7 - '@babel/types': 7.24.7 - '@types/babel__core': 7.20.5 + '@astrojs/compiler': 2.10.3 + '@astrojs/internal-helpers': 0.4.2 + '@astrojs/markdown-remark': 6.0.1 + '@astrojs/telemetry': 3.2.0 + '@oslojs/encoding': 1.1.0 + '@rollup/pluginutils': 5.1.3 '@types/cookie': 0.6.0 - acorn: 8.12.0 - aria-query: 5.3.0 - axobject-query: 4.0.0 - boxen: 7.1.1 - chokidar: 3.6.0 - ci-info: 4.0.0 + acorn: 8.14.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + boxen: 8.0.1 + ci-info: 4.1.0 clsx: 2.1.1 common-ancestor-path: 1.0.1 - cookie: 0.6.0 + cookie: 0.7.2 cssesc: 3.0.0 - debug: 4.3.5 + debug: 4.4.0 deterministic-object-hash: 2.0.2 - devalue: 5.0.0 + devalue: 5.1.1 diff: 5.2.0 dlv: 1.1.3 - dset: 3.1.3 + dset: 3.1.4 es-module-lexer: 1.5.4 esbuild: 0.21.5 estree-walker: 3.0.3 - execa: 8.0.1 fast-glob: 3.3.2 flattie: 1.1.1 github-slugger: 2.0.0 - gray-matter: 4.0.3 html-escaper: 3.0.3 http-cache-semantics: 4.1.1 js-yaml: 4.1.0 kleur: 4.1.5 - magic-string: 0.30.10 + magic-string: 0.30.15 + magicast: 0.3.5 + micromatch: 4.0.8 mrmime: 2.0.0 - ora: 8.0.1 - p-limit: 5.0.0 + neotraverse: 0.6.18 + p-limit: 6.1.0 p-queue: 8.0.1 - path-to-regexp: 6.2.2 - preferred-pm: 3.1.3 + preferred-pm: 4.0.0 prompts: 2.4.2 - rehype: 13.0.1 - semver: 7.6.2 - shiki: 1.9.1 - string-width: 7.1.0 - strip-ansi: 7.1.0 - tsconfck: 3.1.0 + rehype: 13.0.2 + semver: 7.6.3 + shiki: 1.24.2 + tinyexec: 0.3.1 + tsconfck: 3.1.4(typescript@5.7.2) + ultrahtml: 1.5.3 unist-util-visit: 5.0.0 - vfile: 6.0.1 - vite: 5.3.1 - vitefu: 0.2.5(vite@5.3.1) - which-pm: 2.2.0 + vfile: 6.0.3 + vite: 6.0.3 + vitefu: 1.0.4(vite@6.0.3) + which-pm: 3.0.0 + xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 + yocto-spinner: 0.1.2 zod: 3.23.8 - zod-to-json-schema: 3.23.1(zod@3.23.8) + zod-to-json-schema: 3.24.1(zod@3.23.8) + zod-to-ts: 1.2.0(typescript@5.7.2)(zod@3.23.8) optionalDependencies: sharp: 0.33.4 transitivePeerDependencies: - '@types/node' + - jiti - less - lightningcss + - rollup - sass + - sass-embedded - stylus - sugarss - supports-color - terser + - tsx - typescript - dev: false + - yaml - /autoprefixer@10.4.19(postcss@8.4.38): - resolution: {integrity: sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==} - engines: {node: ^10 || ^12 || >=14} - hasBin: true - peerDependencies: - postcss: ^8.1.0 + autoprefixer@10.4.19(postcss@8.4.38): dependencies: browserslist: 4.23.1 caniuse-lite: 1.0.30001634 @@ -1526,123 +2817,64 @@ packages: picocolors: 1.0.1 postcss: 8.4.38 postcss-value-parser: 4.2.0 - dev: false - /axobject-query@4.0.0: - resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} - dependencies: - dequal: 2.0.3 - dev: false + axobject-query@4.1.0: {} - /bail@2.0.2: - resolution: {integrity: sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==} - dev: false + bail@2.0.2: {} - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: false + balanced-match@1.0.2: {} - /base-64@1.0.0: - resolution: {integrity: sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==} - dev: false + base-64@1.0.0: {} - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: false + binary-extensions@2.2.0: {} - /boxen@7.1.1: - resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} - engines: {node: '>=14.16'} + boxen@8.0.1: dependencies: ansi-align: 3.0.1 - camelcase: 7.0.1 + camelcase: 8.0.0 chalk: 5.3.0 cli-boxes: 3.0.0 - string-width: 5.1.2 - type-fest: 2.19.0 - widest-line: 4.0.1 - wrap-ansi: 8.1.0 - dev: false + string-width: 7.2.0 + type-fest: 4.30.1 + widest-line: 5.0.0 + wrap-ansi: 9.0.0 - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + brace-expansion@2.0.1: dependencies: balanced-match: 1.0.2 - dev: false - /braces@3.0.2: - resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} - engines: {node: '>=8'} + braces@3.0.2: dependencies: fill-range: 7.1.1 - dev: false - /braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} + braces@3.0.3: dependencies: fill-range: 7.1.1 - dev: false - /browserslist@4.23.1: - resolution: {integrity: sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true + browserslist@4.23.1: dependencies: caniuse-lite: 1.0.30001634 electron-to-chromium: 1.4.803 node-releases: 2.0.14 update-browserslist-db: 1.0.16(browserslist@4.23.1) - dev: false - - /camelcase-css@2.0.1: - resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} - engines: {node: '>= 6'} - dev: false - /camelcase@7.0.1: - resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} - engines: {node: '>=14.16'} - dev: false + camelcase-css@2.0.1: {} - /caniuse-lite@1.0.30001634: - resolution: {integrity: sha512-fbBYXQ9q3+yp1q1gBk86tOFs4pyn/yxFm5ZNP18OXJDfA3txImOY9PhfxVggZ4vRHDqoU8NrKU81eN0OtzOgRA==} - dev: false + camelcase@8.0.0: {} - /ccount@2.0.1: - resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} - dev: false + caniuse-lite@1.0.30001634: {} - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: false + ccount@2.0.1: {} - /chalk@5.3.0: - resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} - engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} - dev: false + chalk@5.3.0: {} - /character-entities-html4@2.1.0: - resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} - dev: false + character-entities-html4@2.1.0: {} - /character-entities-legacy@3.0.0: - resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} - dev: false + character-entities-legacy@3.0.0: {} - /character-entities@2.0.2: - resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} - dev: false + character-entities@2.0.2: {} - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 braces: 3.0.2 @@ -1653,213 +2885,95 @@ packages: readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.3 - dev: false - - /ci-info@4.0.0: - resolution: {integrity: sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==} - engines: {node: '>=8'} - dev: false - /cli-boxes@3.0.0: - resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} - engines: {node: '>=10'} - dev: false - - /cli-cursor@4.0.0: - resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - restore-cursor: 4.0.0 - dev: false - - /cli-spinners@2.9.2: - resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} - engines: {node: '>=6'} - dev: false + ci-info@4.1.0: {} - /clsx@2.1.1: - resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} - engines: {node: '>=6'} - dev: false + cli-boxes@3.0.0: {} - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: false + clsx@2.1.1: {} - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - requiresBuild: true + color-convert@2.0.1: dependencies: color-name: 1.1.4 - dev: false - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: false + color-name@1.1.4: {} - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - requiresBuild: true - dev: false - - /color-string@1.9.1: - resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} - requiresBuild: true + color-string@1.9.1: dependencies: color-name: 1.1.4 simple-swizzle: 0.2.2 - dev: false optional: true - /color@4.2.3: - resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} - engines: {node: '>=12.5.0'} - requiresBuild: true + color@4.2.3: dependencies: color-convert: 2.0.1 color-string: 1.9.1 - dev: false optional: true - /comma-separated-tokens@2.0.3: - resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} - dev: false - - /commander@4.1.1: - resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} - engines: {node: '>= 6'} - dev: false + comma-separated-tokens@2.0.3: {} - /common-ancestor-path@1.0.1: - resolution: {integrity: sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==} - dev: false + commander@4.1.1: {} - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: false + common-ancestor-path@1.0.1: {} - /cookie@0.6.0: - resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} - engines: {node: '>= 0.6'} - dev: false + cookie@0.7.2: {} - /cross-spawn@7.0.3: - resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} - engines: {node: '>= 8'} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: false - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: false + cssesc@3.0.0: {} - /debug@4.3.5: - resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true + debug@4.4.0: dependencies: - ms: 2.1.2 - dev: false + ms: 2.1.3 - /decode-named-character-reference@1.0.2: - resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + decode-named-character-reference@1.0.2: dependencies: character-entities: 2.0.2 - dev: false - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: false + dequal@2.0.3: {} - /detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - requiresBuild: true - dev: false + detect-libc@2.0.3: optional: true - /deterministic-object-hash@2.0.2: - resolution: {integrity: sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==} - engines: {node: '>=18'} + deterministic-object-hash@2.0.2: dependencies: base-64: 1.0.0 - dev: false - /devalue@5.0.0: - resolution: {integrity: sha512-gO+/OMXF7488D+u3ue+G7Y4AA3ZmUnB3eHJXmBTgNHvr4ZNzl36A0ZtG+XCRNYCkYx/bFmw4qtkoFLa+wSrwAA==} - dev: false + devalue@5.1.1: {} - /devlop@1.1.0: - resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + devlop@1.1.0: dependencies: dequal: 2.0.3 - dev: false - /didyoumean@1.2.2: - resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} - dev: false + didyoumean@1.2.2: {} - /diff@5.2.0: - resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} - engines: {node: '>=0.3.1'} - dev: false + diff@5.2.0: {} - /dlv@1.1.3: - resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} - dev: false + dlv@1.1.3: {} - /dset@3.1.3: - resolution: {integrity: sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==} - engines: {node: '>=4'} - dev: false + dset@3.1.4: {} - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: false + eastasianwidth@0.2.0: {} - /electron-to-chromium@1.4.803: - resolution: {integrity: sha512-61H9mLzGOCLLVsnLiRzCbc63uldP0AniRYPV3hbGVtONA1pI7qSGILdbofR7A8TMbOypDocEAjH/e+9k1QIe3g==} - dev: false + electron-to-chromium@1.4.803: {} - /emoji-regex@10.3.0: - resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} - dev: false + emoji-regex-xs@1.0.0: {} - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false + emoji-regex@10.3.0: {} - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: false + emoji-regex@8.0.0: {} - /entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - dev: false + emoji-regex@9.2.2: {} - /es-module-lexer@1.5.4: - resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} - dev: false + entities@4.5.0: {} - /esbuild@0.19.12: - resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + es-module-lexer@1.5.4: {} + + esbuild@0.19.12: optionalDependencies: '@esbuild/aix-ppc64': 0.19.12 '@esbuild/android-arm': 0.19.12 @@ -1884,13 +2998,8 @@ packages: '@esbuild/win32-arm64': 0.19.12 '@esbuild/win32-ia32': 0.19.12 '@esbuild/win32-x64': 0.19.12 - dev: false - /esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true + esbuild@0.21.5: optionalDependencies: '@esbuild/aix-ppc64': 0.21.5 '@esbuild/android-arm': 0.21.5 @@ -1915,276 +3024,168 @@ packages: '@esbuild/win32-arm64': 0.21.5 '@esbuild/win32-ia32': 0.21.5 '@esbuild/win32-x64': 0.21.5 - dev: false - - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} - engines: {node: '>=6'} - dev: false - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: false - - /escape-string-regexp@5.0.0: - resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} - engines: {node: '>=12'} - dev: false - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: false - /estree-walker@3.0.3: - resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esbuild@0.24.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.24.0 + '@esbuild/android-arm': 0.24.0 + '@esbuild/android-arm64': 0.24.0 + '@esbuild/android-x64': 0.24.0 + '@esbuild/darwin-arm64': 0.24.0 + '@esbuild/darwin-x64': 0.24.0 + '@esbuild/freebsd-arm64': 0.24.0 + '@esbuild/freebsd-x64': 0.24.0 + '@esbuild/linux-arm': 0.24.0 + '@esbuild/linux-arm64': 0.24.0 + '@esbuild/linux-ia32': 0.24.0 + '@esbuild/linux-loong64': 0.24.0 + '@esbuild/linux-mips64el': 0.24.0 + '@esbuild/linux-ppc64': 0.24.0 + '@esbuild/linux-riscv64': 0.24.0 + '@esbuild/linux-s390x': 0.24.0 + '@esbuild/linux-x64': 0.24.0 + '@esbuild/netbsd-x64': 0.24.0 + '@esbuild/openbsd-arm64': 0.24.0 + '@esbuild/openbsd-x64': 0.24.0 + '@esbuild/sunos-x64': 0.24.0 + '@esbuild/win32-arm64': 0.24.0 + '@esbuild/win32-ia32': 0.24.0 + '@esbuild/win32-x64': 0.24.0 + + escalade@3.1.2: {} + + escape-string-regexp@5.0.0: {} + + esprima@4.0.1: {} + + estree-walker@2.0.2: {} + + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.5 - dev: false - - /eventemitter3@5.0.1: - resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} - dev: false - - /execa@8.0.1: - resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} - engines: {node: '>=16.17'} - dependencies: - cross-spawn: 7.0.3 - get-stream: 8.0.1 - human-signals: 5.0.0 - is-stream: 3.0.0 - merge-stream: 2.0.0 - npm-run-path: 5.1.0 - onetime: 6.0.0 - signal-exit: 4.1.0 - strip-final-newline: 3.0.0 - dev: false - /extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - dependencies: - is-extendable: 0.1.1 - dev: false + eventemitter3@5.0.1: {} - /extend@3.0.2: - resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} - dev: false + extend@3.0.2: {} - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} + fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.7 - dev: false - /fast-xml-parser@4.4.0: - resolution: {integrity: sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==} - hasBin: true + fast-xml-parser@4.4.0: dependencies: strnum: 1.0.5 - dev: false - /fastq@1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + fastq@1.15.0: dependencies: reusify: 1.0.4 - dev: false - /fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 - dev: false - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: false + find-up-simple@1.0.0: {} - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} + find-up@4.1.0: dependencies: - locate-path: 6.0.0 + locate-path: 5.0.0 path-exists: 4.0.0 - dev: false - /find-yarn-workspace-root2@1.2.16: - resolution: {integrity: sha512-hr6hb1w8ePMpPVUK39S4RlwJzi+xPLuVuG8XlwXU3KD5Yn3qgBWVfy3AzNlDhWvE1EORCE65/Qm26rFQt3VLVA==} + find-yarn-workspace-root2@1.2.16: dependencies: - micromatch: 4.0.7 + micromatch: 4.0.8 pkg-dir: 4.2.0 - dev: false - /flattie@1.1.1: - resolution: {integrity: sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==} - engines: {node: '>=8'} - dev: false + flattie@1.1.1: {} - /foreground-child@3.2.1: - resolution: {integrity: sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==} - engines: {node: '>=14'} + foreground-child@3.2.1: dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 - dev: false - /fraction.js@4.3.7: - resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - dev: false - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: false - optional: true - - /function-bind@1.1.1: - resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} - dev: false + fraction.js@4.3.7: {} - /gemoji@4.2.1: - resolution: {integrity: sha512-V9lUpRSn+KQGavZx8Pk+6mxG3kaz21ae2kTCXuT36KaRPNgYU8eHtj/RcUCNFVvmwppsYYz3nnNS9lmcP5kTsg==} - dev: false + fsevents@2.3.3: + optional: true - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: false + function-bind@1.1.1: {} - /get-east-asian-width@1.2.0: - resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} - engines: {node: '>=18'} - dev: false + gemoji@4.2.1: {} - /get-stream@8.0.1: - resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} - engines: {node: '>=16'} - dev: false + get-east-asian-width@1.2.0: {} - /github-slugger@2.0.0: - resolution: {integrity: sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==} - dev: false + github-slugger@2.0.0: {} - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 - dev: false - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} + glob-parent@6.0.2: dependencies: is-glob: 4.0.3 - dev: false - /glob@10.4.1: - resolution: {integrity: sha512-2jelhlq3E4ho74ZyVLN03oKdAZVUa6UDZzFLVH1H7dnoax+y9qyaq8zBkfDIggjniU19z0wU18y16jMB2eyVIw==} - engines: {node: '>=16 || 14 >=14.18'} - hasBin: true + glob@10.4.1: dependencies: foreground-child: 3.2.1 jackspeak: 3.4.0 minimatch: 9.0.4 minipass: 7.1.2 path-scurry: 1.11.1 - dev: false - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: false - /graceful-fs@4.2.10: - resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} - dev: false + graceful-fs@4.2.10: {} - /gray-matter@4.0.3: - resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} - engines: {node: '>=6.0'} + has@1.0.3: dependencies: - js-yaml: 3.14.1 - kind-of: 6.0.3 - section-matter: 1.0.0 - strip-bom-string: 1.0.0 - dev: false - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: false + function-bind: 1.1.1 - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} + hast-util-from-html@2.0.1: dependencies: - function-bind: 1.1.1 - dev: false + '@types/hast': 3.0.1 + devlop: 1.1.0 + hast-util-from-parse5: 8.0.1 + parse5: 7.1.2 + vfile: 6.0.3 + vfile-message: 4.0.2 - /hast-util-from-html@2.0.1: - resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} + hast-util-from-html@2.0.3: dependencies: '@types/hast': 3.0.1 devlop: 1.1.0 hast-util-from-parse5: 8.0.1 parse5: 7.1.2 - vfile: 6.0.1 + vfile: 6.0.3 vfile-message: 4.0.2 - dev: false - /hast-util-from-parse5@8.0.1: - resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} + hast-util-from-parse5@8.0.1: dependencies: '@types/hast': 3.0.1 '@types/unist': 3.0.0 devlop: 1.1.0 hastscript: 8.0.0 property-information: 6.2.0 - vfile: 6.0.1 + vfile: 6.0.3 vfile-location: 5.0.2 web-namespaces: 2.0.1 - dev: false - /hast-util-heading-rank@3.0.0: - resolution: {integrity: sha512-EJKb8oMUXVHcWZTDepnr+WNbfnXKFNf9duMesmr4S8SXTJBJ9M4Yok08pu9vxdJwdlGRhVumk9mEhkEvKGifwA==} + hast-util-heading-rank@3.0.0: dependencies: '@types/hast': 3.0.1 - dev: false - /hast-util-is-element@1.1.0: - resolution: {integrity: sha512-oUmNua0bFbdrD/ELDSSEadRVtWZOf3iF6Lbv81naqsIV99RnSCieTbWuWCY8BAeEfKJTKl0gRdokv+dELutHGQ==} - dev: false + hast-util-is-element@1.1.0: {} - /hast-util-is-element@3.0.0: - resolution: {integrity: sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==} + hast-util-is-element@3.0.0: dependencies: '@types/hast': 3.0.1 - dev: false - /hast-util-parse-selector@4.0.0: - resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + hast-util-parse-selector@4.0.0: dependencies: '@types/hast': 3.0.1 - dev: false - /hast-util-raw@9.0.1: - resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==} + hast-util-raw@9.0.1: dependencies: '@types/hast': 3.0.1 '@types/unist': 3.0.0 @@ -2196,13 +3197,11 @@ packages: parse5: 7.1.2 unist-util-position: 5.0.0 unist-util-visit: 5.0.0 - vfile: 6.0.1 + vfile: 6.0.3 web-namespaces: 2.0.1 zwitch: 2.0.4 - dev: false - /hast-util-to-html@9.0.0: - resolution: {integrity: sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==} + hast-util-to-html@9.0.0: dependencies: '@types/hast': 3.0.1 '@types/unist': 3.0.0 @@ -2216,10 +3215,22 @@ packages: space-separated-tokens: 2.0.2 stringify-entities: 4.0.3 zwitch: 2.0.4 - dev: false - /hast-util-to-parse5@8.0.0: - resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + hast-util-to-html@9.0.4: + dependencies: + '@types/hast': 3.0.4 + '@types/unist': 3.0.0 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.0.2 + property-information: 6.2.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.3 + zwitch: 2.0.4 + + hast-util-to-parse5@8.0.0: dependencies: '@types/hast': 3.0.1 comma-separated-tokens: 2.0.3 @@ -2228,306 +3239,141 @@ packages: space-separated-tokens: 2.0.2 web-namespaces: 2.0.1 zwitch: 2.0.4 - dev: false - /hast-util-to-string@3.0.0: - resolution: {integrity: sha512-OGkAxX1Ua3cbcW6EJ5pT/tslVb90uViVkcJ4ZZIMW/R33DX/AkcJcRrPebPwJkHYwlDHXz4aIwvAAaAdtrACFA==} + hast-util-to-string@3.0.0: dependencies: '@types/hast': 3.0.1 - dev: false - /hast-util-to-text@4.0.2: - resolution: {integrity: sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==} + hast-util-to-text@4.0.2: dependencies: '@types/hast': 3.0.1 '@types/unist': 3.0.0 hast-util-is-element: 3.0.0 unist-util-find-after: 5.0.0 - dev: false - /hast-util-whitespace@3.0.0: - resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + hast-util-whitespace@3.0.0: dependencies: - '@types/hast': 3.0.1 - dev: false + '@types/hast': 3.0.4 - /hastscript@8.0.0: - resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + hastscript@8.0.0: dependencies: '@types/hast': 3.0.1 comma-separated-tokens: 2.0.3 hast-util-parse-selector: 4.0.0 property-information: 6.2.0 space-separated-tokens: 2.0.2 - dev: false - - /html-escaper@3.0.3: - resolution: {integrity: sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==} - dev: false - /html-void-elements@3.0.0: - resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} - dev: false + html-escaper@3.0.3: {} - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: false + html-void-elements@3.0.0: {} - /human-signals@5.0.0: - resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} - engines: {node: '>=16.17.0'} - dev: false + http-cache-semantics@4.1.1: {} - /import-meta-resolve@4.1.0: - resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} - dev: false + import-meta-resolve@4.1.0: {} - /is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - requiresBuild: true - dev: false + is-arrayish@0.3.2: optional: true - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.2.0 - dev: false - /is-core-module@2.13.0: - resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} + is-core-module@2.13.0: dependencies: has: 1.0.3 - dev: false - - /is-docker@3.0.0: - resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - hasBin: true - dev: false - /is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} - dev: false + is-docker@3.0.0: {} - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: false + is-extglob@2.1.1: {} - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: false + is-fullwidth-code-point@3.0.0: {} - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} + is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - dev: false - /is-inside-container@1.0.0: - resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} - engines: {node: '>=14.16'} - hasBin: true + is-inside-container@1.0.0: dependencies: is-docker: 3.0.0 - dev: false - - /is-interactive@2.0.0: - resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} - engines: {node: '>=12'} - dev: false - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: false - - /is-plain-obj@4.1.0: - resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} - engines: {node: '>=12'} - dev: false - - /is-stream@3.0.0: - resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dev: false - /is-unicode-supported@1.3.0: - resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} - engines: {node: '>=12'} - dev: false + is-number@7.0.0: {} - /is-unicode-supported@2.0.0: - resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} - engines: {node: '>=18'} - dev: false + is-plain-obj@4.1.0: {} - /is-wsl@3.1.0: - resolution: {integrity: sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==} - engines: {node: '>=16'} + is-wsl@3.1.0: dependencies: is-inside-container: 1.0.0 - dev: false - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: false + isexe@2.0.0: {} - /jackspeak@3.4.0: - resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} - engines: {node: '>=14'} + jackspeak@3.4.0: dependencies: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - dev: false - - /jiti@1.21.6: - resolution: {integrity: sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==} - hasBin: true - dev: false - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: false + jiti@1.21.6: {} - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true + js-yaml@3.14.1: dependencies: argparse: 1.0.10 esprima: 4.0.1 - dev: false - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true + js-yaml@4.1.0: dependencies: argparse: 2.0.1 - dev: false - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: false - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: false - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: false - - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: false + kleur@3.0.3: {} - /kleur@4.1.5: - resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} - engines: {node: '>=6'} - dev: false + kleur@4.1.5: {} - /lilconfig@2.1.0: - resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} - engines: {node: '>=10'} - dev: false + lilconfig@2.1.0: {} - /lilconfig@3.1.2: - resolution: {integrity: sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==} - engines: {node: '>=14'} - dev: false + lilconfig@3.1.2: {} - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: false + lines-and-columns@1.2.4: {} - /load-yaml-file@0.2.0: - resolution: {integrity: sha512-OfCBkGEw4nN6JLtgRidPX6QxjBQGQf72q3si2uvqyFEMbycSFFHwAZeXx6cJgFM9wmLrf9zBwCP3Ivqa+LLZPw==} - engines: {node: '>=6'} + load-yaml-file@0.2.0: dependencies: graceful-fs: 4.2.10 js-yaml: 3.14.1 pify: 4.0.1 strip-bom: 3.0.0 - dev: false - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} + locate-path@5.0.0: dependencies: p-locate: 4.1.0 - dev: false - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: false - - /log-symbols@6.0.0: - resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} - engines: {node: '>=18'} - dependencies: - chalk: 5.3.0 - is-unicode-supported: 1.3.0 - dev: false - /longest-streak@3.1.0: - resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} - dev: false + longest-streak@3.1.0: {} - /lru-cache@10.2.2: - resolution: {integrity: sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==} - engines: {node: 14 || >=16.14} - dev: false + lru-cache@10.2.2: {} - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + magic-string@0.30.15: dependencies: - yallist: 3.1.1 - dev: false + '@jridgewell/sourcemap-codec': 1.5.0 - /magic-string@0.30.10: - resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} + magicast@0.3.5: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - dev: false + '@babel/parser': 7.26.3 + '@babel/types': 7.26.3 + source-map-js: 1.2.0 - /markdown-table@3.0.3: - resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} - dev: false + markdown-table@3.0.3: {} - /mdast-util-definitions@6.0.0: - resolution: {integrity: sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==} + mdast-util-definitions@6.0.0: dependencies: '@types/mdast': 4.0.1 '@types/unist': 3.0.0 unist-util-visit: 5.0.0 - dev: false - /mdast-util-find-and-replace@3.0.1: - resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + mdast-util-find-and-replace@3.0.1: dependencies: '@types/mdast': 4.0.1 escape-string-regexp: 5.0.0 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - dev: false - /mdast-util-from-markdown@2.0.0: - resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + mdast-util-from-markdown@2.0.0: dependencies: '@types/mdast': 4.0.1 '@types/unist': 3.0.0 @@ -2543,20 +3389,16 @@ packages: unist-util-stringify-position: 4.0.0 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-gfm-autolink-literal@2.0.0: - resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} + mdast-util-gfm-autolink-literal@2.0.0: dependencies: '@types/mdast': 4.0.1 ccount: 2.0.1 devlop: 1.1.0 mdast-util-find-and-replace: 3.0.1 micromark-util-character: 2.0.1 - dev: false - /mdast-util-gfm-footnote@2.0.0: - resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + mdast-util-gfm-footnote@2.0.0: dependencies: '@types/mdast': 4.0.1 devlop: 1.1.0 @@ -2565,20 +3407,16 @@ packages: micromark-util-normalize-identifier: 2.0.0 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + mdast-util-gfm-strikethrough@2.0.0: dependencies: '@types/mdast': 4.0.1 mdast-util-from-markdown: 2.0.0 mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-gfm-table@2.0.0: - resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + mdast-util-gfm-table@2.0.0: dependencies: '@types/mdast': 4.0.1 devlop: 1.1.0 @@ -2587,10 +3425,8 @@ packages: mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-gfm-task-list-item@2.0.0: - resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + mdast-util-gfm-task-list-item@2.0.0: dependencies: '@types/mdast': 4.0.1 devlop: 1.1.0 @@ -2598,10 +3434,8 @@ packages: mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-gfm@3.0.0: - resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + mdast-util-gfm@3.0.0: dependencies: mdast-util-from-markdown: 2.0.0 mdast-util-gfm-autolink-literal: 2.0.0 @@ -2612,17 +3446,13 @@ packages: mdast-util-to-markdown: 2.1.0 transitivePeerDependencies: - supports-color - dev: false - /mdast-util-phrasing@4.1.0: - resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + mdast-util-phrasing@4.1.0: dependencies: '@types/mdast': 4.0.1 unist-util-is: 6.0.0 - dev: false - /mdast-util-to-hast@13.0.2: - resolution: {integrity: sha512-U5I+500EOOw9e3ZrclN3Is3fRpw8c19SMyNZlZ2IS+7vLsNzb2Om11VpIVOR+/0137GhZsFEF6YiKD5+0Hr2Og==} + mdast-util-to-hast@13.0.2: dependencies: '@types/hast': 3.0.1 '@types/mdast': 4.0.1 @@ -2632,10 +3462,8 @@ packages: trim-lines: 3.0.1 unist-util-position: 5.0.0 unist-util-visit: 5.0.0 - dev: false - /mdast-util-to-markdown@2.1.0: - resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + mdast-util-to-markdown@2.1.0: dependencies: '@types/mdast': 4.0.1 '@types/unist': 3.0.0 @@ -2645,25 +3473,14 @@ packages: micromark-util-decode-string: 2.0.0 unist-util-visit: 5.0.0 zwitch: 2.0.4 - dev: false - /mdast-util-to-string@4.0.0: - resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + mdast-util-to-string@4.0.0: dependencies: '@types/mdast': 4.0.1 - dev: false - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: false - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: false + merge2@1.4.1: {} - /micromark-core-commonmark@2.0.1: - resolution: {integrity: sha512-CUQyKr1e///ZODyD1U3xit6zXwy1a8q2a1S1HKtIlmgvurrEpaw/Y9y6KSIbF8P59cn/NjzHyO+Q2fAyYLQrAA==} + micromark-core-commonmark@2.0.1: dependencies: decode-named-character-reference: 1.0.2 devlop: 1.1.0 @@ -2681,19 +3498,15 @@ packages: micromark-util-subtokenize: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-extension-gfm-autolink-literal@2.0.0: - resolution: {integrity: sha512-rTHfnpt/Q7dEAK1Y5ii0W8bhfJlVJFnJMHIPisfPK3gpVNuOP0VnRl96+YJ3RYWV/P4gFeQoGKNlT3RhuvpqAg==} + micromark-extension-gfm-autolink-literal@2.0.0: dependencies: micromark-util-character: 2.0.1 micromark-util-sanitize-uri: 2.0.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-extension-gfm-footnote@2.0.0: - resolution: {integrity: sha512-6Rzu0CYRKDv3BfLAUnZsSlzx3ak6HAoI85KTiijuKIz5UxZxbUI+pD6oHgw+6UtQuiRwnGRhzMmPRv4smcz0fg==} + micromark-extension-gfm-footnote@2.0.0: dependencies: devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -2703,10 +3516,8 @@ packages: micromark-util-sanitize-uri: 2.0.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-extension-gfm-strikethrough@2.0.0: - resolution: {integrity: sha512-c3BR1ClMp5fxxmwP6AoOY2fXO9U8uFMKs4ADD66ahLTNcwzSCyRVU4k7LPV5Nxo/VJiR4TdzxRQY2v3qIUceCw==} + micromark-extension-gfm-strikethrough@2.0.0: dependencies: devlop: 1.1.0 micromark-util-chunked: 2.0.0 @@ -2714,36 +3525,28 @@ packages: micromark-util-resolve-all: 2.0.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-extension-gfm-table@2.0.0: - resolution: {integrity: sha512-PoHlhypg1ItIucOaHmKE8fbin3vTLpDOUg8KAr8gRCF1MOZI9Nquq2i/44wFvviM4WuxJzc3demT8Y3dkfvYrw==} + micromark-extension-gfm-table@2.0.0: dependencies: devlop: 1.1.0 micromark-factory-space: 2.0.0 micromark-util-character: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-extension-gfm-tagfilter@2.0.0: - resolution: {integrity: sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==} + micromark-extension-gfm-tagfilter@2.0.0: dependencies: micromark-util-types: 2.0.0 - dev: false - /micromark-extension-gfm-task-list-item@2.0.1: - resolution: {integrity: sha512-cY5PzGcnULaN5O7T+cOzfMoHjBW7j+T9D2sucA5d/KbsBTPcYdebm9zUd9zzdgJGCwahV+/W78Z3nbulBYVbTw==} + micromark-extension-gfm-task-list-item@2.0.1: dependencies: devlop: 1.1.0 micromark-factory-space: 2.0.0 micromark-util-character: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-extension-gfm@3.0.0: - resolution: {integrity: sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==} + micromark-extension-gfm@3.0.0: dependencies: micromark-extension-gfm-autolink-literal: 2.0.0 micromark-extension-gfm-footnote: 2.0.0 @@ -2753,143 +3556,103 @@ packages: micromark-extension-gfm-task-list-item: 2.0.1 micromark-util-combine-extensions: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-factory-destination@2.0.0: - resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} + micromark-factory-destination@2.0.0: dependencies: micromark-util-character: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-factory-label@2.0.0: - resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + micromark-factory-label@2.0.0: dependencies: devlop: 1.1.0 micromark-util-character: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-factory-space@2.0.0: - resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} + micromark-factory-space@2.0.0: dependencies: micromark-util-character: 2.0.1 micromark-util-types: 2.0.0 - dev: false - /micromark-factory-title@2.0.0: - resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} + micromark-factory-title@2.0.0: dependencies: micromark-factory-space: 2.0.0 micromark-util-character: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-factory-whitespace@2.0.0: - resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} + micromark-factory-whitespace@2.0.0: dependencies: micromark-factory-space: 2.0.0 micromark-util-character: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-util-character@2.0.1: - resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==} + micromark-util-character@2.0.1: dependencies: micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-util-chunked@2.0.0: - resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} + micromark-util-chunked@2.0.0: dependencies: micromark-util-symbol: 2.0.0 - dev: false - /micromark-util-classify-character@2.0.0: - resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} + micromark-util-classify-character@2.0.0: dependencies: micromark-util-character: 2.0.1 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-util-combine-extensions@2.0.0: - resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} + micromark-util-combine-extensions@2.0.0: dependencies: micromark-util-chunked: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-util-decode-numeric-character-reference@2.0.1: - resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} + micromark-util-decode-numeric-character-reference@2.0.1: dependencies: micromark-util-symbol: 2.0.0 - dev: false - /micromark-util-decode-string@2.0.0: - resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} + micromark-util-decode-string@2.0.0: dependencies: decode-named-character-reference: 1.0.2 micromark-util-character: 2.0.1 micromark-util-decode-numeric-character-reference: 2.0.1 micromark-util-symbol: 2.0.0 - dev: false - /micromark-util-encode@2.0.0: - resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} - dev: false + micromark-util-encode@2.0.0: {} - /micromark-util-html-tag-name@2.0.0: - resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} - dev: false + micromark-util-html-tag-name@2.0.0: {} - /micromark-util-normalize-identifier@2.0.0: - resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} + micromark-util-normalize-identifier@2.0.0: dependencies: micromark-util-symbol: 2.0.0 - dev: false - /micromark-util-resolve-all@2.0.0: - resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} + micromark-util-resolve-all@2.0.0: dependencies: micromark-util-types: 2.0.0 - dev: false - /micromark-util-sanitize-uri@2.0.0: - resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + micromark-util-sanitize-uri@2.0.0: dependencies: micromark-util-character: 2.0.1 micromark-util-encode: 2.0.0 micromark-util-symbol: 2.0.0 - dev: false - /micromark-util-subtokenize@2.0.1: - resolution: {integrity: sha512-jZNtiFl/1aY73yS3UGQkutD0UbhTt68qnRpw2Pifmz5wV9h8gOVsN70v+Lq/f1rKaU/W8pxRe8y8Q9FX1AOe1Q==} + micromark-util-subtokenize@2.0.1: dependencies: devlop: 1.1.0 micromark-util-chunked: 2.0.0 micromark-util-symbol: 2.0.0 micromark-util-types: 2.0.0 - dev: false - /micromark-util-symbol@2.0.0: - resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} - dev: false + micromark-util-symbol@2.0.0: {} - /micromark-util-types@2.0.0: - resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} - dev: false + micromark-util-types@2.0.0: {} - /micromark@4.0.0: - resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} + micromark@4.0.0: dependencies: '@types/debug': 4.1.7 - debug: 4.3.5 + debug: 4.4.0 decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -2907,384 +3670,205 @@ packages: micromark-util-types: 2.0.0 transitivePeerDependencies: - supports-color - dev: false - /micromatch@4.0.7: - resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} - engines: {node: '>=8.6'} + micromatch@4.0.7: dependencies: braces: 3.0.3 picomatch: 2.3.1 - dev: false - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: false - /mimic-fn@4.0.0: - resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} - engines: {node: '>=12'} - dev: false + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 - /minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} - engines: {node: '>=16 || 14 >=14.17'} + minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 - dev: false - /minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - dev: false + minipass@7.1.2: {} - /mrmime@2.0.0: - resolution: {integrity: sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==} - engines: {node: '>=10'} - dev: false + mrmime@2.0.0: {} - /ms@2.1.2: - resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: false + ms@2.1.3: {} - /mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + mz@2.7.0: dependencies: any-promise: 1.3.0 object-assign: 4.1.1 thenify-all: 1.6.0 - dev: false - /nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - dev: false + nanoid@3.3.7: {} - /nlcst-to-string@4.0.0: - resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==} + neotraverse@0.6.18: {} + + nlcst-to-string@4.0.0: dependencies: '@types/nlcst': 2.0.3 - dev: false - - /node-releases@2.0.14: - resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - dev: false - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: false - - /normalize-range@0.1.2: - resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} - engines: {node: '>=0.10.0'} - dev: false - /npm-run-path@5.1.0: - resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - path-key: 4.0.0 - dev: false + node-releases@2.0.14: {} - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: false + normalize-path@3.0.0: {} - /object-hash@3.0.0: - resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} - engines: {node: '>= 6'} - dev: false + normalize-range@0.1.2: {} - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: false + object-assign@4.1.1: {} - /onetime@6.0.0: - resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} - engines: {node: '>=12'} - dependencies: - mimic-fn: 4.0.0 - dev: false + object-hash@3.0.0: {} - /ora@8.0.1: - resolution: {integrity: sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==} - engines: {node: '>=18'} + oniguruma-to-es@0.7.0: dependencies: - chalk: 5.3.0 - cli-cursor: 4.0.0 - cli-spinners: 2.9.2 - is-interactive: 2.0.0 - is-unicode-supported: 2.0.0 - log-symbols: 6.0.0 - stdin-discarder: 0.2.2 - string-width: 7.1.0 - strip-ansi: 7.1.0 - dev: false + emoji-regex-xs: 1.0.0 + regex: 5.0.2 + regex-recursion: 4.3.0 - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} + p-limit@2.3.0: dependencies: p-try: 2.2.0 - dev: false - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: false - /p-limit@5.0.0: - resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} - engines: {node: '>=18'} + p-limit@6.1.0: dependencies: - yocto-queue: 1.0.0 - dev: false + yocto-queue: 1.1.1 - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} + p-locate@4.1.0: dependencies: p-limit: 2.3.0 - dev: false - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: false - /p-queue@8.0.1: - resolution: {integrity: sha512-NXzu9aQJTAzbBqOt2hwsR63ea7yvxJc0PwN/zobNAudYfb1B7R08SzB4TsLeSbUCuG467NhnoT0oO6w1qRO+BA==} - engines: {node: '>=18'} + p-queue@8.0.1: dependencies: eventemitter3: 5.0.1 p-timeout: 6.1.2 - dev: false - /p-timeout@6.1.2: - resolution: {integrity: sha512-UbD77BuZ9Bc9aABo74gfXhNvzC9Tx7SxtHSh1fxvx3jTLLYvmVhiQZZrJzqqU0jKbN32kb5VOKiLEQI/3bIjgQ==} - engines: {node: '>=14.16'} - dev: false + p-timeout@6.1.2: {} - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: false + p-try@2.2.0: {} - /parse-latin@7.0.0: - resolution: {integrity: sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==} + parse-latin@7.0.0: dependencies: '@types/nlcst': 2.0.3 '@types/unist': 3.0.0 nlcst-to-string: 4.0.0 unist-util-modify-children: 4.0.0 unist-util-visit-children: 3.0.0 - vfile: 6.0.1 - dev: false + vfile: 6.0.3 - /parse5@7.1.2: - resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + parse5@7.1.2: dependencies: entities: 4.5.0 - dev: false - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: false - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: false + path-exists@4.0.0: {} - /path-key@4.0.0: - resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} - engines: {node: '>=12'} - dev: false + path-key@3.1.1: {} - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: false + path-parse@1.0.7: {} - /path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} + path-scurry@1.11.1: dependencies: lru-cache: 10.2.2 minipass: 7.1.2 - dev: false - /path-to-regexp@6.2.2: - resolution: {integrity: sha512-GQX3SSMokngb36+whdpRXE+3f9V8UzyAorlYvOGx87ufGHehNTn5lCxrKtLyZ4Yl/wEKnNnr98ZzOwwDZV5ogw==} - dev: false + picocolors@1.0.1: {} - /picocolors@1.0.1: - resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} - dev: false + picocolors@1.1.1: {} + + picomatch@2.3.1: {} - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: false + picomatch@4.0.2: {} - /pify@2.3.0: - resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} - engines: {node: '>=0.10.0'} - dev: false + pify@2.3.0: {} - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: false + pify@4.0.1: {} - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - dev: false + pirates@4.0.6: {} - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 - dev: false - /postcss-import@15.1.0(postcss@8.4.38): - resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} - engines: {node: '>=14.0.0'} - peerDependencies: - postcss: ^8.0.0 + postcss-import@15.1.0(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-value-parser: 4.2.0 read-cache: 1.0.0 resolve: 1.22.8 - dev: false - /postcss-js@4.0.1(postcss@8.4.38): - resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} - engines: {node: ^12 || ^14 || >= 16} - peerDependencies: - postcss: ^8.4.21 + postcss-js@4.0.1(postcss@8.4.38): dependencies: camelcase-css: 2.0.1 postcss: 8.4.38 - dev: false - /postcss-load-config@4.0.2(postcss@8.4.38): - resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} - engines: {node: '>= 14'} - peerDependencies: - postcss: '>=8.0.9' - ts-node: '>=9.0.0' - peerDependenciesMeta: - postcss: - optional: true - ts-node: - optional: true + postcss-load-config@4.0.2(postcss@8.4.38): dependencies: lilconfig: 3.1.2 postcss: 8.4.38 yaml: 2.4.5 - dev: false - /postcss-nested@6.0.1(postcss@8.4.38): - resolution: {integrity: sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==} - engines: {node: '>=12.0'} - peerDependencies: - postcss: ^8.2.14 + postcss-nested@6.0.1(postcss@8.4.38): dependencies: postcss: 8.4.38 postcss-selector-parser: 6.1.0 - dev: false - /postcss-selector-parser@6.1.0: - resolution: {integrity: sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==} - engines: {node: '>=4'} + postcss-selector-parser@6.1.0: dependencies: cssesc: 3.0.0 util-deprecate: 1.0.2 - dev: false - /postcss-value-parser@4.2.0: - resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} - dev: false + postcss-value-parser@4.2.0: {} - /postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} - engines: {node: ^10 || ^12 || >=14} + postcss@8.4.38: dependencies: nanoid: 3.3.7 picocolors: 1.0.1 source-map-js: 1.2.0 - dev: false - /preferred-pm@3.1.3: - resolution: {integrity: sha512-MkXsENfftWSRpzCzImcp4FRsCc3y1opwB73CfCNWyzMqArju2CrlMHlqB7VexKiPEOjGMbttv1r9fSCn5S610w==} - engines: {node: '>=10'} + postcss@8.4.49: + dependencies: + nanoid: 3.3.7 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + preferred-pm@4.0.0: dependencies: - find-up: 5.0.0 + find-up-simple: 1.0.0 find-yarn-workspace-root2: 1.2.16 - path-exists: 4.0.0 - which-pm: 2.0.0 - dev: false + which-pm: 3.0.0 - /prismjs@1.29.0: - resolution: {integrity: sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==} - engines: {node: '>=6'} - dev: false + prismjs@1.29.0: {} - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} + prompts@2.4.2: dependencies: kleur: 3.0.3 sisteransi: 1.0.5 - dev: false - /property-information@6.2.0: - resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} - dev: false + property-information@6.2.0: {} - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: false + queue-microtask@1.2.3: {} - /read-cache@1.0.0: - resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + read-cache@1.0.0: dependencies: pify: 2.3.0 - dev: false - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + readdirp@3.6.0: dependencies: picomatch: 2.3.1 - dev: false - /rehype-accessible-emojis@0.3.2: - resolution: {integrity: sha512-kChZo+EZsuFQYHUPu6kOZFjDrG7UtQdGxkrCvHBVo9ariKPL6S68QdPVxLxwcAtZSRZIXZhDuTJHgIM8KW24Qw==} + regex-recursion@4.3.0: + dependencies: + regex-utilities: 2.3.0 + + regex-utilities@2.3.0: {} + + regex@5.0.2: + dependencies: + regex-utilities: 2.3.0 + + rehype-accessible-emojis@0.3.2: dependencies: emoji-regex: 8.0.0 gemoji: 4.2.1 hast-util-is-element: 1.1.0 unist-util-flatmap: 1.0.0 - dev: false - /rehype-autolink-headings@7.1.0: - resolution: {integrity: sha512-rItO/pSdvnvsP4QRB1pmPiNHUskikqtPojZKJPPPAVx9Hj8i8TwMBhofrrAYRhYOOBZH9tgmG5lPqDLuIWPWmw==} + rehype-autolink-headings@7.1.0: dependencies: '@types/hast': 3.0.1 '@ungap/structured-clone': 1.2.0 @@ -3292,53 +3876,47 @@ packages: hast-util-is-element: 3.0.0 unified: 11.0.4 unist-util-visit: 5.0.0 - dev: false - /rehype-parse@9.0.0: - resolution: {integrity: sha512-WG7nfvmWWkCR++KEkZevZb/uw41E8TsH4DsY9UxsTbIXCVGbAs4S+r8FrQ+OtH5EEQAs+5UxKC42VinkmpA1Yw==} + rehype-parse@9.0.0: dependencies: '@types/hast': 3.0.1 hast-util-from-html: 2.0.1 - unified: 11.0.4 - dev: false + unified: 11.0.5 - /rehype-raw@7.0.0: - resolution: {integrity: sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==} + rehype-raw@7.0.0: dependencies: '@types/hast': 3.0.1 hast-util-raw: 9.0.1 - vfile: 6.0.1 - dev: false + vfile: 6.0.3 - /rehype-slug@6.0.0: - resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} + rehype-slug@6.0.0: dependencies: '@types/hast': 3.0.1 github-slugger: 2.0.0 hast-util-heading-rank: 3.0.0 hast-util-to-string: 3.0.0 unist-util-visit: 5.0.0 - dev: false - /rehype-stringify@10.0.0: - resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==} + rehype-stringify@10.0.0: dependencies: '@types/hast': 3.0.1 hast-util-to-html: 9.0.0 - unified: 11.0.4 - dev: false + unified: 11.0.5 + + rehype-stringify@10.0.1: + dependencies: + '@types/hast': 3.0.1 + hast-util-to-html: 9.0.0 + unified: 11.0.5 - /rehype@13.0.1: - resolution: {integrity: sha512-AcSLS2mItY+0fYu9xKxOu1LhUZeBZZBx8//5HKzF+0XP+eP8+6a5MXn2+DW2kfXR6Dtp1FEXMVrjyKAcvcU8vg==} + rehype@13.0.2: dependencies: '@types/hast': 3.0.1 rehype-parse: 9.0.0 rehype-stringify: 10.0.0 - unified: 11.0.4 - dev: false + unified: 11.0.5 - /remark-gfm@4.0.0: - resolution: {integrity: sha512-U92vJgBPkbw4Zfu/IiW2oTZLSL3Zpv+uI7My2eq8JxKgqraFdU8YUGicEJCEgSbeaG+QDFqIcwwfMTOEelPxuA==} + remark-gfm@4.0.0: dependencies: '@types/mdast': 4.0.1 mdast-util-gfm: 3.0.0 @@ -3348,10 +3926,8 @@ packages: unified: 11.0.5 transitivePeerDependencies: - supports-color - dev: false - /remark-parse@11.0.0: - resolution: {integrity: sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==} + remark-parse@11.0.0: dependencies: '@types/mdast': 4.0.1 mdast-util-from-markdown: 2.0.0 @@ -3359,150 +3935,97 @@ packages: unified: 11.0.5 transitivePeerDependencies: - supports-color - dev: false - /remark-rehype@11.1.0: - resolution: {integrity: sha512-z3tJrAs2kIs1AqIIy6pzHmAHlF1hWQ+OdY4/hv+Wxe35EhyLKcajL33iUEn3ScxtFox9nUvRufR/Zre8Q08H/g==} + remark-rehype@11.1.1: dependencies: '@types/hast': 3.0.1 '@types/mdast': 4.0.1 mdast-util-to-hast: 13.0.2 unified: 11.0.5 - vfile: 6.0.1 - dev: false + vfile: 6.0.3 - /remark-smartypants@3.0.1: - resolution: {integrity: sha512-qyshfCl2eLO0i0558e79ZJsfojC5wjnYLByjt0FmjJQN6aYwcRxpoj784LZJSoWCdnA2ubh5rLNGb8Uur/wDng==} - engines: {node: '>=16.0.0'} + remark-smartypants@3.0.2: dependencies: retext: 9.0.0 retext-smartypants: 6.1.0 unified: 11.0.5 unist-util-visit: 5.0.0 - dev: false - /remark-stringify@11.0.0: - resolution: {integrity: sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==} + remark-stringify@11.0.0: dependencies: '@types/mdast': 4.0.1 mdast-util-to-markdown: 2.1.0 unified: 11.0.5 - dev: false - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true + resolve@1.22.8: dependencies: is-core-module: 2.13.0 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 - dev: false - - /restore-cursor@4.0.0: - resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - dependencies: - onetime: 5.1.2 - signal-exit: 3.0.7 - dev: false - /retext-latin@4.0.0: - resolution: {integrity: sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==} + retext-latin@4.0.0: dependencies: '@types/nlcst': 2.0.3 parse-latin: 7.0.0 unified: 11.0.5 - dev: false - /retext-smartypants@6.1.0: - resolution: {integrity: sha512-LDPXg95346bqFZnDMHo0S7Rq5p64+B+N8Vz733+wPMDtwb9rCOs9LIdIEhrUOU+TAywX9St+ocQWJt8wrzivcQ==} + retext-smartypants@6.1.0: dependencies: '@types/nlcst': 2.0.3 nlcst-to-string: 4.0.0 unist-util-visit: 5.0.0 - dev: false - /retext-stringify@4.0.0: - resolution: {integrity: sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==} + retext-stringify@4.0.0: dependencies: '@types/nlcst': 2.0.3 nlcst-to-string: 4.0.0 unified: 11.0.5 - dev: false - /retext@9.0.0: - resolution: {integrity: sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==} + retext@9.0.0: dependencies: '@types/nlcst': 2.0.3 retext-latin: 4.0.0 retext-stringify: 4.0.0 unified: 11.0.5 - dev: false - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: false + reusify@1.0.4: {} - /rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true + rollup@4.28.1: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.28.1 + '@rollup/rollup-android-arm64': 4.28.1 + '@rollup/rollup-darwin-arm64': 4.28.1 + '@rollup/rollup-darwin-x64': 4.28.1 + '@rollup/rollup-freebsd-arm64': 4.28.1 + '@rollup/rollup-freebsd-x64': 4.28.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.28.1 + '@rollup/rollup-linux-arm-musleabihf': 4.28.1 + '@rollup/rollup-linux-arm64-gnu': 4.28.1 + '@rollup/rollup-linux-arm64-musl': 4.28.1 + '@rollup/rollup-linux-loongarch64-gnu': 4.28.1 + '@rollup/rollup-linux-powerpc64le-gnu': 4.28.1 + '@rollup/rollup-linux-riscv64-gnu': 4.28.1 + '@rollup/rollup-linux-s390x-gnu': 4.28.1 + '@rollup/rollup-linux-x64-gnu': 4.28.1 + '@rollup/rollup-linux-x64-musl': 4.28.1 + '@rollup/rollup-win32-arm64-msvc': 4.28.1 + '@rollup/rollup-win32-ia32-msvc': 4.28.1 + '@rollup/rollup-win32-x64-msvc': 4.28.1 fsevents: 2.3.3 - dev: false - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 - dev: false - - /section-matter@1.0.0: - resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} - engines: {node: '>=4'} - dependencies: - extend-shallow: 2.0.1 - kind-of: 6.0.3 - dev: false - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: false - /semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true - dev: false + semver@7.6.3: {} - /sharp@0.33.4: - resolution: {integrity: sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==} - engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} - requiresBuild: true + sharp@0.33.4: dependencies: color: 4.2.3 detect-libc: 2.0.3 - semver: 7.6.2 + semver: 7.6.3 optionalDependencies: '@img/sharp-darwin-arm64': 0.33.4 '@img/sharp-darwin-x64': 0.33.4 @@ -3523,137 +4046,76 @@ packages: '@img/sharp-wasm32': 0.33.4 '@img/sharp-win32-ia32': 0.33.4 '@img/sharp-win32-x64': 0.33.4 - dev: false optional: true - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 - dev: false - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: false + shebang-regex@3.0.0: {} - /shiki@1.9.1: - resolution: {integrity: sha512-8PDkgb5ja3nfujTjvC4VytL6wGOGCtFAClUb2r3QROevYXxcq+/shVJK5s6gy0HZnjaJgFxd6BpPqpRfqne5rA==} + shiki@1.24.2: dependencies: - '@shikijs/core': 1.9.1 - dev: false - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - dev: false + '@shikijs/core': 1.24.2 + '@shikijs/engine-javascript': 1.24.2 + '@shikijs/engine-oniguruma': 1.24.2 + '@shikijs/types': 1.24.2 + '@shikijs/vscode-textmate': 9.3.1 + '@types/hast': 3.0.4 - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: false + signal-exit@4.1.0: {} - /simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - requiresBuild: true + simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 - dev: false optional: true - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: false + sisteransi@1.0.5: {} - /source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - dev: false + source-map-js@1.2.0: {} - /space-separated-tokens@2.0.2: - resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} - dev: false + source-map-js@1.2.1: {} - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: false + space-separated-tokens@2.0.2: {} - /stdin-discarder@0.2.2: - resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} - engines: {node: '>=18'} - dev: false + sprintf-js@1.0.3: {} - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 - dev: false - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + string-width@5.1.2: dependencies: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: false - /string-width@7.1.0: - resolution: {integrity: sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==} - engines: {node: '>=18'} + string-width@7.2.0: dependencies: emoji-regex: 10.3.0 get-east-asian-width: 1.2.0 strip-ansi: 7.1.0 - dev: false - /stringify-entities@4.0.3: - resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + stringify-entities@4.0.3: dependencies: character-entities-html4: 2.1.0 character-entities-legacy: 3.0.0 - dev: false - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 - dev: false - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} + strip-ansi@7.1.0: dependencies: ansi-regex: 6.0.1 - dev: false - - /strip-bom-string@1.0.0: - resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} - engines: {node: '>=0.10.0'} - dev: false - - /strip-bom@3.0.0: - resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} - engines: {node: '>=4'} - dev: false - /strip-final-newline@3.0.0: - resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} - engines: {node: '>=12'} - dev: false + strip-bom@3.0.0: {} - /strnum@1.0.5: - resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==} - dev: false + strnum@1.0.5: {} - /sucrase@3.35.0: - resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true + sucrase@3.35.0: dependencies: '@jridgewell/gen-mapping': 0.3.5 commander: 4.1.1 @@ -3662,24 +4124,10 @@ packages: mz: 2.7.0 pirates: 4.0.6 ts-interface-checker: 0.1.13 - dev: false - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: false - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: false + supports-preserve-symlinks-flag@1.0.0: {} - /tailwindcss@3.4.4: - resolution: {integrity: sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==} - engines: {node: '>=14.0.0'} - hasBin: true + tailwindcss@3.4.4: dependencies: '@alloc/quick-lru': 5.2.0 arg: 5.0.2 @@ -3705,69 +4153,41 @@ packages: sucrase: 3.35.0 transitivePeerDependencies: - ts-node - dev: false - /thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} + thenify-all@1.6.0: dependencies: thenify: 3.3.1 - dev: false - /thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + thenify@3.3.1: dependencies: any-promise: 1.3.0 - dev: false - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: false + tinyexec@0.3.1: {} - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 - dev: false - /trim-lines@3.0.1: - resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} - dev: false + trim-lines@3.0.1: {} - /trough@2.1.0: - resolution: {integrity: sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g==} - dev: false + trough@2.1.0: {} - /ts-interface-checker@0.1.13: - resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} - dev: false + ts-interface-checker@0.1.13: {} - /tsconfck@3.1.0: - resolution: {integrity: sha512-CMjc5zMnyAjcS9sPLytrbFmj89st2g+JYtY/c02ug4Q+CZaAtCgbyviI0n1YvjZE/pzoc6FbNsINS13DOL1B9w==} - engines: {node: ^18 || >=20} - hasBin: true - peerDependencies: - typescript: ^5.0.0 - peerDependenciesMeta: - typescript: - optional: true - dev: false + tsconfck@3.1.4(typescript@5.7.2): + dependencies: + typescript: 5.7.2 - /tslib@2.6.3: - resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} - requiresBuild: true - dev: false + tslib@2.6.3: optional: true - /type-fest@2.19.0: - resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} - engines: {node: '>=12.20'} - dev: false + type-fest@4.30.1: {} - /unified@11.0.4: - resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} + typescript@5.7.2: {} + + ultrahtml@1.5.3: {} + + unified@11.0.4: dependencies: '@types/unist': 3.0.0 bail: 2.0.2 @@ -3776,10 +4196,8 @@ packages: is-plain-obj: 4.1.0 trough: 2.1.0 vfile: 6.0.1 - dev: false - /unified@11.0.5: - resolution: {integrity: sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==} + unified@11.0.5: dependencies: '@types/unist': 3.0.0 bail: 2.0.2 @@ -3787,252 +4205,150 @@ packages: extend: 3.0.2 is-plain-obj: 4.1.0 trough: 2.1.0 - vfile: 6.0.1 - dev: false + vfile: 6.0.3 - /unist-util-find-after@5.0.0: - resolution: {integrity: sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==} + unist-util-find-after@5.0.0: dependencies: '@types/unist': 3.0.0 unist-util-is: 6.0.0 - dev: false - /unist-util-flatmap@1.0.0: - resolution: {integrity: sha512-IG32jcKJlhARCYT2LsYPJWdoXYkzz3ESAdl1aa2hn9Auh+cgUmU6wgkII4yCc/1GgeWibRdELdCZh/p3QKQ1dQ==} - dev: false + unist-util-flatmap@1.0.0: {} - /unist-util-is@6.0.0: - resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + unist-util-is@6.0.0: dependencies: '@types/unist': 3.0.0 - dev: false - /unist-util-modify-children@4.0.0: - resolution: {integrity: sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==} + unist-util-modify-children@4.0.0: dependencies: '@types/unist': 3.0.0 array-iterate: 2.0.1 - dev: false - /unist-util-position@5.0.0: - resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + unist-util-position@5.0.0: dependencies: '@types/unist': 3.0.0 - dev: false - /unist-util-remove-position@5.0.0: - resolution: {integrity: sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==} + unist-util-remove-position@5.0.0: dependencies: '@types/unist': 3.0.0 unist-util-visit: 5.0.0 - dev: false - /unist-util-stringify-position@4.0.0: - resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + unist-util-stringify-position@4.0.0: dependencies: '@types/unist': 3.0.0 - dev: false - /unist-util-visit-children@3.0.0: - resolution: {integrity: sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==} + unist-util-visit-children@3.0.0: dependencies: '@types/unist': 3.0.0 - dev: false - /unist-util-visit-parents@6.0.1: - resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + unist-util-visit-parents@6.0.1: dependencies: '@types/unist': 3.0.0 unist-util-is: 6.0.0 - dev: false - /unist-util-visit@5.0.0: - resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + unist-util-visit@5.0.0: dependencies: '@types/unist': 3.0.0 unist-util-is: 6.0.0 unist-util-visit-parents: 6.0.1 - dev: false - /update-browserslist-db@1.0.16(browserslist@4.23.1): - resolution: {integrity: sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' + update-browserslist-db@1.0.16(browserslist@4.23.1): dependencies: browserslist: 4.23.1 escalade: 3.1.2 picocolors: 1.0.1 - dev: false - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - requiresBuild: true - dev: false + util-deprecate@1.0.2: {} - /vfile-location@5.0.2: - resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} + vfile-location@5.0.2: dependencies: '@types/unist': 3.0.0 - vfile: 6.0.1 - dev: false + vfile: 6.0.3 - /vfile-message@4.0.2: - resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + vfile-message@4.0.2: dependencies: '@types/unist': 3.0.0 unist-util-stringify-position: 4.0.0 - dev: false - /vfile@6.0.1: - resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} + vfile@6.0.1: dependencies: '@types/unist': 3.0.0 unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - dev: false - /vite@5.3.1: - resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true + vfile@6.0.3: dependencies: - esbuild: 0.21.5 - postcss: 8.4.38 - rollup: 4.17.2 + '@types/unist': 3.0.0 + vfile-message: 4.0.2 + + vite@6.0.3: + dependencies: + esbuild: 0.24.0 + postcss: 8.4.49 + rollup: 4.28.1 optionalDependencies: fsevents: 2.3.3 - dev: false - /vitefu@0.2.5(vite@5.3.1): - resolution: {integrity: sha512-SgHtMLoqaeeGnd2evZ849ZbACbnwQCIwRH57t18FxcXoZop0uQu0uzlIhJBlF/eWVzuce0sHeqPcDo+evVcg8Q==} - peerDependencies: - vite: ^3.0.0 || ^4.0.0 || ^5.0.0 - peerDependenciesMeta: - vite: - optional: true + vitefu@1.0.4(vite@6.0.3): dependencies: - vite: 5.3.1 - dev: false + vite: 6.0.3 - /web-namespaces@2.0.1: - resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} - dev: false - - /which-pm-runs@1.1.0: - resolution: {integrity: sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==} - engines: {node: '>=4'} - dev: false + web-namespaces@2.0.1: {} - /which-pm@2.0.0: - resolution: {integrity: sha512-Lhs9Pmyph0p5n5Z3mVnN0yWcbQYUAD7rbQUiMsQxOJ3T57k7RFe35SUwWMf7dsbDZks1uOmw4AecB/JMDj3v/w==} - engines: {node: '>=8.15'} - dependencies: - load-yaml-file: 0.2.0 - path-exists: 4.0.0 - dev: false + which-pm-runs@1.1.0: {} - /which-pm@2.2.0: - resolution: {integrity: sha512-MOiaDbA5ZZgUjkeMWM5EkJp4loW5ZRoa5bc3/aeMox/PJelMhE6t7S/mLuiY43DBupyxH+S0U1bTui9kWUlmsw==} - engines: {node: '>=8.15'} + which-pm@3.0.0: dependencies: load-yaml-file: 0.2.0 - path-exists: 4.0.0 - dev: false - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true + which@2.0.2: dependencies: isexe: 2.0.0 - dev: false - /widest-line@4.0.1: - resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} - engines: {node: '>=12'} + widest-line@5.0.0: dependencies: - string-width: 5.1.2 - dev: false + string-width: 7.2.0 - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 - dev: false - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} + wrap-ansi@8.1.0: dependencies: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - dev: false - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: false + wrap-ansi@9.0.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 7.2.0 + strip-ansi: 7.1.0 + + xxhash-wasm@1.1.0: {} - /yaml@2.4.5: - resolution: {integrity: sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==} - engines: {node: '>= 14'} - hasBin: true - dev: false + yaml@2.4.5: {} - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: false + yargs-parser@21.1.1: {} - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: false + yocto-queue@1.1.1: {} - /yocto-queue@1.0.0: - resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} - engines: {node: '>=12.20'} - dev: false + yocto-spinner@0.1.2: + dependencies: + yoctocolors: 2.1.1 - /zod-to-json-schema@3.23.1(zod@3.23.8): - resolution: {integrity: sha512-oT9INvydob1XV0v1d2IadrR74rLtDInLvDFfAa1CG0Pmg/vxATk7I2gSelfj271mbzeM4Da0uuDQE/Nkj3DWNw==} - peerDependencies: - zod: ^3.23.3 + yoctocolors@2.1.1: {} + + zod-to-json-schema@3.24.1(zod@3.23.8): dependencies: zod: 3.23.8 - dev: false - /zod@3.23.8: - resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - dev: false + zod-to-ts@1.2.0(typescript@5.7.2)(zod@3.23.8): + dependencies: + typescript: 5.7.2 + zod: 3.23.8 - /zwitch@2.0.4: - resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} - dev: false + zod@3.23.8: {} + + zwitch@2.0.4: {} diff --git a/website/src/content.config.ts b/website/src/content.config.ts new file mode 100644 index 000000000..555eaa124 --- /dev/null +++ b/website/src/content.config.ts @@ -0,0 +1,17 @@ +import { z, defineCollection } from "astro:content"; +import { glob } from "astro/loaders"; + +const blog = defineCollection({ + loader: glob({ pattern: "**/*.md", base: "./src/content" }), + schema: z.object({ + title: z.string(), + date: z.date(), + description: z.string(), + author: z.string(), + slug: z.string(), + }), +}); + +// Expose your defined collection to Astro +// with the `collections` export +export const collections = { blog }; diff --git a/website/src/layouts/BlogPostLayout.astro b/website/src/layouts/BlogPostLayout.astro index 6a08b67d3..0574ed613 100644 --- a/website/src/layouts/BlogPostLayout.astro +++ b/website/src/layouts/BlogPostLayout.astro @@ -1,10 +1,9 @@ --- -import Layout from "./Layout.astro"; -import BlogPostTOC from "../components/BlogPostTOC.astro" -const { frontmatter, headings } = Astro.props; - -const formattedDate = (new Date(frontmatter.date)).toLocaleString().split(',')[0] - +import Layout from "./Layout.astro"; +import BlogPostTOC from "../components/BlogPostTOC.astro"; +const { frontmatter, headings } = Astro.props; + +const formattedDate = new Date(frontmatter.date).toLocaleString().split(",")[0]; --- diff --git a/website/src/layouts/Layout.astro b/website/src/layouts/Layout.astro index b96eeacdc..b5207690f 100644 --- a/website/src/layouts/Layout.astro +++ b/website/src/layouts/Layout.astro @@ -2,7 +2,7 @@ import Navbar from "../components/Navbar.astro"; export interface Props { - title: string; + title: string; } const { title } = Astro.props; diff --git a/website/src/pages/blog.astro b/website/src/pages/blog.astro index 374216eca..78928ab3d 100644 --- a/website/src/pages/blog.astro +++ b/website/src/pages/blog.astro @@ -1,16 +1,17 @@ --- -const posts = await Astro.glob('../content/blog/*.md'); -import Layout from '../layouts/Layout.astro'; +import { getCollection } from "astro:content"; +const posts = await getCollection("blog"); +import Layout from "../layouts/Layout.astro"; --- {posts.map((post) => { - const formattedDate = (new Date(post.frontmatter.date)).toLocaleString().split(',')[0]; + const formattedDate = post.data.date.toLocaleString().split(',')[0]; return ( - -

{post.frontmatter.title}

- {formattedDate} - {post.frontmatter.author} -

{post.frontmatter.description}

+
+

{post.data.title}

+ {formattedDate} - {post.data.author} +

{post.data.description}

) })} diff --git a/website/src/pages/index.astro b/website/src/pages/index.astro index 7fb494534..2e3e94f5b 100644 --- a/website/src/pages/index.astro +++ b/website/src/pages/index.astro @@ -1,6 +1,6 @@ --- -import { Code } from 'astro:components'; -import Layout from '../layouts/Layout.astro'; +import { Code } from "astro:components"; +import Layout from "../layouts/Layout.astro"; const EXAMPLE_CODE = ` fn app() -> Element { @@ -38,7 +38,7 @@ fn app() -> Element { } ) } -`.trim() +`.trim(); --- diff --git a/website/src/pages/posts/[...slug].astro b/website/src/pages/posts/[...slug].astro index 125be8a67..1079b9617 100644 --- a/website/src/pages/posts/[...slug].astro +++ b/website/src/pages/posts/[...slug].astro @@ -1,14 +1,17 @@ --- -import { getEntry } from "astro:content"; - -const { slug = "" } = Astro.params; - -const entry = await getEntry("blog", slug); - -if (entry === undefined) { - return Astro.redirect("/404"); -} - -let { Content } = await entry.render(); +import { getEntry, render } from "astro:content"; +import BlogPostLayout from "../../layouts/BlogPostLayout.astro"; + +const { slug = "" } = Astro.params; + +const entry = await getEntry("blog", slug); + +if (entry === undefined) { + return Astro.redirect("/404"); +} + +const { Content, remarkPluginFrontmatter, headings } = await render(entry); --- - \ No newline at end of file + + + From 59915b592f9faf3c90cf6793e8b88145c1f83db0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 19 Dec 2024 19:18:50 +0100 Subject: [PATCH 31/36] fix(deps): update dependency astro to v5.0.8 [security] (#984) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- website/package.json | 2 +- website/pnpm-lock.yaml | 135 +++++++++++++++-------------------------- 2 files changed, 49 insertions(+), 88 deletions(-) diff --git a/website/package.json b/website/package.json index c7b92c755..eeda5ae12 100644 --- a/website/package.json +++ b/website/package.json @@ -15,7 +15,7 @@ "@astrojs/deno": "^5.0.0", "@astrojs/rss": "^4.0.1", "@astrojs/tailwind": "^5.0.2", - "astro": "5.0.5", + "astro": "5.0.8", "rehype-accessible-emojis": "^0.3.2", "rehype-autolink-headings": "^7.1.0", "rehype-slug": "^6.0.0", diff --git a/website/pnpm-lock.yaml b/website/pnpm-lock.yaml index 455cdab9e..7ab964b8e 100644 --- a/website/pnpm-lock.yaml +++ b/website/pnpm-lock.yaml @@ -10,16 +10,16 @@ importers: dependencies: '@astrojs/deno': specifier: ^5.0.0 - version: 5.0.1(astro@5.0.5) + version: 5.0.1(astro@5.0.8(jiti@1.21.6)(rollup@4.28.1)(typescript@5.7.2)(yaml@2.4.5)) '@astrojs/rss': specifier: ^4.0.1 version: 4.0.7 '@astrojs/tailwind': specifier: ^5.0.2 - version: 5.1.0(astro@5.0.5)(tailwindcss@3.4.4) + version: 5.1.0(astro@5.0.8(jiti@1.21.6)(rollup@4.28.1)(typescript@5.7.2)(yaml@2.4.5))(tailwindcss@3.4.4) astro: - specifier: 5.0.5 - version: 5.0.5(typescript@5.7.2) + specifier: 5.0.8 + version: 5.0.8(jiti@1.21.6)(rollup@4.28.1)(typescript@5.7.2)(yaml@2.4.5) rehype-accessible-emojis: specifier: ^0.3.2 version: 0.3.2 @@ -849,9 +849,6 @@ packages: '@types/debug@4.1.7': resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -923,8 +920,8 @@ packages: array-iterate@2.0.1: resolution: {integrity: sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==} - astro@5.0.5: - resolution: {integrity: sha512-xfptdmurDsQcj/Anc7mU+eKlcyV7ppJIlmaSwhX3ZWwK5N/0rGKVmUqnuILgR6MB0XVJiIfublNzDGoyj4Q6BQ==} + astro@5.0.8: + resolution: {integrity: sha512-nW4TmRCeG3t2iDmm91KPvYpYNljNfjeaneN4BX463DKAZ3MPmUn92aKefOXC0bjMHQ2Gamc8MIZ6sORS2EhyAQ==} engines: {node: ^18.17.1 || ^20.3.0 || >=22.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0'} hasBin: true @@ -1236,9 +1233,6 @@ packages: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} - hast-util-from-html@2.0.1: - resolution: {integrity: sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==} - hast-util-from-html@2.0.3: resolution: {integrity: sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==} @@ -1260,9 +1254,6 @@ packages: hast-util-raw@9.0.1: resolution: {integrity: sha512-5m1gmba658Q+lO5uqL5YNGQWeh1MYWZbZmWrM5lncdcuiXuo5E2HT/CIOp0rLF8ksfSwiCVJ3twlgVRyTGThGA==} - hast-util-to-html@9.0.0: - resolution: {integrity: sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==} - hast-util-to-html@9.0.4: resolution: {integrity: sha512-wxQzXtdbhiwGAUKrnQJXlOPmHnEehzphwkK7aluUPQ+lEc1xefC8pblMgpp2w5ldBTEfveRIrADcrhGIWrlTDA==} @@ -1755,9 +1746,6 @@ packages: rehype-slug@6.0.0: resolution: {integrity: sha512-lWyvf/jwu+oS5+hL5eClVd3hNdmwM1kAC0BUvEGD19pajQMIzcNUd/k9GsfQ+FfECvX+JE+e9/btsKH0EjJT6A==} - rehype-stringify@10.0.0: - resolution: {integrity: sha512-1TX1i048LooI9QoecrXy7nGFFbFSufxVRAfc6Y9YMRAi56l+oB0zP51mLSV312uRuvVLPV1opSlJmslozR1XHQ==} - rehype-stringify@10.0.1: resolution: {integrity: sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==} @@ -2128,9 +2116,9 @@ snapshots: '@astrojs/compiler@2.10.3': {} - '@astrojs/deno@5.0.1(astro@5.0.5)': + '@astrojs/deno@5.0.1(astro@5.0.8(jiti@1.21.6)(rollup@4.28.1)(typescript@5.7.2)(yaml@2.4.5))': dependencies: - astro: 5.0.5(typescript@5.7.2) + astro: 5.0.8(jiti@1.21.6)(rollup@4.28.1)(typescript@5.7.2)(yaml@2.4.5) esbuild: 0.19.12 '@astrojs/internal-helpers@0.4.2': {} @@ -2168,9 +2156,9 @@ snapshots: fast-xml-parser: 4.4.0 kleur: 4.1.5 - '@astrojs/tailwind@5.1.0(astro@5.0.5)(tailwindcss@3.4.4)': + '@astrojs/tailwind@5.1.0(astro@5.0.8(jiti@1.21.6)(rollup@4.28.1)(typescript@5.7.2)(yaml@2.4.5))(tailwindcss@3.4.4)': dependencies: - astro: 5.0.5(typescript@5.7.2) + astro: 5.0.8(jiti@1.21.6)(rollup@4.28.1)(typescript@5.7.2)(yaml@2.4.5) autoprefixer: 10.4.19(postcss@8.4.38) postcss: 8.4.38 postcss-load-config: 4.0.2(postcss@8.4.38) @@ -2554,7 +2542,7 @@ snapshots: '@jridgewell/trace-mapping@0.3.25': dependencies: '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/sourcemap-codec': 1.5.0 '@nodelib/fs.scandir@2.1.5': dependencies: @@ -2573,11 +2561,13 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@rollup/pluginutils@5.1.3': + '@rollup/pluginutils@5.1.3(rollup@4.28.1)': dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 estree-walker: 2.0.2 picomatch: 4.0.2 + optionalDependencies: + rollup: 4.28.1 '@rollup/rollup-android-arm-eabi@4.28.1': optional: true @@ -2669,8 +2659,6 @@ snapshots: dependencies: '@types/ms': 0.7.31 - '@types/estree@1.0.5': {} - '@types/estree@1.0.6': {} '@types/hast@3.0.1': @@ -2730,14 +2718,14 @@ snapshots: array-iterate@2.0.1: {} - astro@5.0.5(typescript@5.7.2): + astro@5.0.8(jiti@1.21.6)(rollup@4.28.1)(typescript@5.7.2)(yaml@2.4.5): dependencies: '@astrojs/compiler': 2.10.3 '@astrojs/internal-helpers': 0.4.2 '@astrojs/markdown-remark': 6.0.1 '@astrojs/telemetry': 3.2.0 '@oslojs/encoding': 1.1.0 - '@rollup/pluginutils': 5.1.3 + '@rollup/pluginutils': 5.1.3(rollup@4.28.1) '@types/cookie': 0.6.0 acorn: 8.14.0 aria-query: 5.3.2 @@ -2781,8 +2769,8 @@ snapshots: ultrahtml: 1.5.3 unist-util-visit: 5.0.0 vfile: 6.0.3 - vite: 6.0.3 - vitefu: 1.0.4(vite@6.0.3) + vite: 6.0.3(jiti@1.21.6)(yaml@2.4.5) + vitefu: 1.0.4(vite@6.0.3(jiti@1.21.6)(yaml@2.4.5)) which-pm: 3.0.0 xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 @@ -3062,7 +3050,7 @@ snapshots: estree-walker@3.0.3: dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 eventemitter3@5.0.1: {} @@ -3074,7 +3062,7 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.7 + micromatch: 4.0.8 fast-xml-parser@4.4.0: dependencies: @@ -3142,18 +3130,9 @@ snapshots: dependencies: function-bind: 1.1.1 - hast-util-from-html@2.0.1: - dependencies: - '@types/hast': 3.0.1 - devlop: 1.1.0 - hast-util-from-parse5: 8.0.1 - parse5: 7.1.2 - vfile: 6.0.3 - vfile-message: 4.0.2 - hast-util-from-html@2.0.3: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 devlop: 1.1.0 hast-util-from-parse5: 8.0.1 parse5: 7.1.2 @@ -3162,7 +3141,7 @@ snapshots: hast-util-from-parse5@8.0.1: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 '@types/unist': 3.0.0 devlop: 1.1.0 hastscript: 8.0.0 @@ -3183,11 +3162,11 @@ snapshots: hast-util-parse-selector@4.0.0: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 hast-util-raw@9.0.1: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 '@types/unist': 3.0.0 '@ungap/structured-clone': 1.2.0 hast-util-from-parse5: 8.0.1 @@ -3201,21 +3180,6 @@ snapshots: web-namespaces: 2.0.1 zwitch: 2.0.4 - hast-util-to-html@9.0.0: - dependencies: - '@types/hast': 3.0.1 - '@types/unist': 3.0.0 - ccount: 2.0.1 - comma-separated-tokens: 2.0.3 - hast-util-raw: 9.0.1 - hast-util-whitespace: 3.0.0 - html-void-elements: 3.0.0 - mdast-util-to-hast: 13.0.2 - property-information: 6.2.0 - space-separated-tokens: 2.0.2 - stringify-entities: 4.0.3 - zwitch: 2.0.4 - hast-util-to-html@9.0.4: dependencies: '@types/hast': 3.0.4 @@ -3232,7 +3196,7 @@ snapshots: hast-util-to-parse5@8.0.0: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 devlop: 1.1.0 property-information: 6.2.0 @@ -3246,7 +3210,7 @@ snapshots: hast-util-to-text@4.0.2: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 '@types/unist': 3.0.0 hast-util-is-element: 3.0.0 unist-util-find-after: 5.0.0 @@ -3257,7 +3221,7 @@ snapshots: hastscript@8.0.0: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 comma-separated-tokens: 2.0.3 hast-util-parse-selector: 4.0.0 property-information: 6.2.0 @@ -3356,7 +3320,7 @@ snapshots: dependencies: '@babel/parser': 7.26.3 '@babel/types': 7.26.3 - source-map-js: 1.2.0 + source-map-js: 1.2.1 markdown-table@3.0.3: {} @@ -3454,7 +3418,7 @@ snapshots: mdast-util-to-hast@13.0.2: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 '@types/mdast': 4.0.1 '@ungap/structured-clone': 1.2.0 devlop: 1.1.0 @@ -3799,8 +3763,9 @@ snapshots: postcss-load-config@4.0.2(postcss@8.4.38): dependencies: lilconfig: 3.1.2 - postcss: 8.4.38 yaml: 2.4.5 + optionalDependencies: + postcss: 8.4.38 postcss-nested@6.0.1(postcss@8.4.38): dependencies: @@ -3879,13 +3844,13 @@ snapshots: rehype-parse@9.0.0: dependencies: - '@types/hast': 3.0.1 - hast-util-from-html: 2.0.1 + '@types/hast': 3.0.4 + hast-util-from-html: 2.0.3 unified: 11.0.5 rehype-raw@7.0.0: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 hast-util-raw: 9.0.1 vfile: 6.0.3 @@ -3897,23 +3862,17 @@ snapshots: hast-util-to-string: 3.0.0 unist-util-visit: 5.0.0 - rehype-stringify@10.0.0: - dependencies: - '@types/hast': 3.0.1 - hast-util-to-html: 9.0.0 - unified: 11.0.5 - rehype-stringify@10.0.1: dependencies: - '@types/hast': 3.0.1 - hast-util-to-html: 9.0.0 + '@types/hast': 3.0.4 + hast-util-to-html: 9.0.4 unified: 11.0.5 rehype@13.0.2: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 rehype-parse: 9.0.0 - rehype-stringify: 10.0.0 + rehype-stringify: 10.0.1 unified: 11.0.5 remark-gfm@4.0.0: @@ -3938,7 +3897,7 @@ snapshots: remark-rehype@11.1.1: dependencies: - '@types/hast': 3.0.1 + '@types/hast': 3.0.4 '@types/mdast': 4.0.1 mdast-util-to-hast: 13.0.2 unified: 11.0.5 @@ -4175,7 +4134,7 @@ snapshots: ts-interface-checker@0.1.13: {} tsconfck@3.1.4(typescript@5.7.2): - dependencies: + optionalDependencies: typescript: 5.7.2 tslib@2.6.3: @@ -4255,7 +4214,7 @@ snapshots: dependencies: browserslist: 4.23.1 escalade: 3.1.2 - picocolors: 1.0.1 + picocolors: 1.1.1 util-deprecate@1.0.2: {} @@ -4280,17 +4239,19 @@ snapshots: '@types/unist': 3.0.0 vfile-message: 4.0.2 - vite@6.0.3: + vite@6.0.3(jiti@1.21.6)(yaml@2.4.5): dependencies: esbuild: 0.24.0 postcss: 8.4.49 rollup: 4.28.1 optionalDependencies: fsevents: 2.3.3 + jiti: 1.21.6 + yaml: 2.4.5 - vitefu@1.0.4(vite@6.0.3): - dependencies: - vite: 6.0.3 + vitefu@1.0.4(vite@6.0.3(jiti@1.21.6)(yaml@2.4.5)): + optionalDependencies: + vite: 6.0.3(jiti@1.21.6)(yaml@2.4.5) web-namespaces@2.0.1: {} From 3bc36986d7b69e8cbec7aefe5d25456b00728cd4 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Thu, 19 Dec 2024 21:29:22 +0100 Subject: [PATCH 32/36] fix: Handle reordedering of keyed children (#1015) * fix: Handle reoderdering of keyed children * fmt * comment out some compositor tests * feat: Add invalidation reasons in torin * adapt tests * test reordering of nodes in torin * test reordering of nodes in freya-core * update --- crates/core/src/dom/mutations_writer.rs | 27 ++++- crates/core/src/layout.rs | 2 +- crates/core/tests/nodes_reorder.rs | 47 ++++++++ crates/native-core/src/dioxus.rs | 2 +- crates/native-core/src/tree.rs | 31 ++++- crates/torin/src/measure.rs | 2 +- crates/torin/src/torin.rs | 46 ++++--- crates/torin/tests/other.rs | 152 ++++++++++++++++++++++-- 8 files changed, 278 insertions(+), 31 deletions(-) create mode 100644 crates/core/tests/nodes_reorder.rs diff --git a/crates/core/src/dom/mutations_writer.rs b/crates/core/src/dom/mutations_writer.rs index 84ccf29ba..e682fb1ce 100644 --- a/crates/core/src/dom/mutations_writer.rs +++ b/crates/core/src/dom/mutations_writer.rs @@ -21,7 +21,10 @@ use freya_node_state::{ CustomAttributeValues, LayerState, }; -use torin::torin::Torin; +use torin::torin::{ + DirtyReason, + Torin, +}; use crate::prelude::{ Compositor, @@ -160,12 +163,34 @@ impl<'a> WriteMutations for MutationsWriter<'a> { fn insert_nodes_after(&mut self, id: dioxus_core::ElementId, m: usize) { if m > 0 { + self.layout.invalidate_with_reason( + self.native_writer.state.element_to_node_id(id), + DirtyReason::Reorder, + ); + let new_nodes = + &self.native_writer.state.stack[self.native_writer.state.stack.len() - m..]; + for new in new_nodes { + self.layout + .invalidate_with_reason(*new, DirtyReason::Reorder); + } + self.native_writer.insert_nodes_after(id, m); } } fn insert_nodes_before(&mut self, id: dioxus_core::ElementId, m: usize) { if m > 0 { + self.layout.invalidate_with_reason( + self.native_writer.state.element_to_node_id(id), + DirtyReason::Reorder, + ); + let new_nodes = + &self.native_writer.state.stack[self.native_writer.state.stack.len() - m..]; + for new in new_nodes { + self.layout + .invalidate_with_reason(*new, DirtyReason::Reorder); + } + self.native_writer.insert_nodes_before(id, m); } } diff --git a/crates/core/src/layout.rs b/crates/core/src/layout.rs index b81ff25b9..ca7b9c64a 100644 --- a/crates/core/src/layout.rs +++ b/crates/core/src/layout.rs @@ -33,7 +33,7 @@ pub fn process_layout( let mut dirty_accessibility_tree = fdom.accessibility_dirty_nodes(); let mut compositor_dirty_nodes = fdom.compositor_dirty_nodes(); let mut compositor_dirty_area = fdom.compositor_dirty_area(); - let mut buffer = layout.dirty.iter().copied().collect_vec(); + let mut buffer = layout.dirty.keys().copied().collect_vec(); while let Some(node_id) = buffer.pop() { if let Some(node) = rdom.get(node_id) { if let Some(area) = diff --git a/crates/core/tests/nodes_reorder.rs b/crates/core/tests/nodes_reorder.rs new file mode 100644 index 000000000..978c1f576 --- /dev/null +++ b/crates/core/tests/nodes_reorder.rs @@ -0,0 +1,47 @@ +use freya::prelude::*; +use freya_testing::prelude::*; + +#[tokio::test] +pub async fn nodes_reorder() { + fn nodes_reorder() -> Element { + let mut data = use_signal(|| vec![1, 2, 3]); + + rsx!( + rect { + onclick: move |_| { + let item = data.write().remove(0); + data.write().push(item); + }, + label { + "Move" + } + } + for d in data.read().iter() { + label { + key: "{d}", + height: "20", + "{d}" + } + } + ) + } + + let mut utils = launch_test(nodes_reorder); + utils.wait_for_update().await; + + assert_eq!(utils.root().get(1).get(0).text(), Some("1")); + assert_eq!(utils.root().get(2).get(0).text(), Some("2")); + assert_eq!(utils.root().get(3).get(0).text(), Some("3")); + + utils.click_cursor((5., 5.)).await; + + assert_eq!(utils.root().get(1).get(0).text(), Some("2")); + assert_eq!(utils.root().get(2).get(0).text(), Some("3")); + assert_eq!(utils.root().get(3).get(0).text(), Some("1")); + + utils.click_cursor((5., 5.)).await; + + assert_eq!(utils.root().get(1).get(0).text(), Some("3")); + assert_eq!(utils.root().get(2).get(0).text(), Some("1")); + assert_eq!(utils.root().get(3).get(0).text(), Some("2")); +} diff --git a/crates/native-core/src/dioxus.rs b/crates/native-core/src/dioxus.rs index ade3949b7..0d474ac78 100644 --- a/crates/native-core/src/dioxus.rs +++ b/crates/native-core/src/dioxus.rs @@ -34,7 +34,7 @@ struct ElementIdComponent(ElementId); /// The state of the Dioxus integration with the RealDom pub struct DioxusState { templates: FxHashMap>, - stack: Vec, + pub stack: Vec, node_id_mapping: Vec>, } diff --git a/crates/native-core/src/tree.rs b/crates/native-core/src/tree.rs index ecb5b6333..fbc076c07 100644 --- a/crates/native-core/src/tree.rs +++ b/crates/native-core/src/tree.rs @@ -229,13 +229,24 @@ impl<'a> TreeMut for TreeMutView<'a> { } fn insert_before(&mut self, old_id: NodeId, new_id: NodeId) { + let new_parent_id = { + let new_id = self.1.get(new_id).unwrap(); + new_id.parent + }; + if let Some(new_parent_id) = new_parent_id { + (&mut self.1) + .get(new_parent_id) + .unwrap() + .children + .retain(|id| *id != new_id); + } + let parent_id = { let old_node = self.1.get(old_id).unwrap(); old_node.parent.expect("tried to insert before root") }; - { - (&mut self.1).get(new_id).unwrap().parent = Some(parent_id); - } + (&mut self.1).get(new_id).unwrap().parent = Some(parent_id); + let parent = (&mut self.1).get(parent_id).unwrap(); let index = parent .children @@ -248,9 +259,21 @@ impl<'a> TreeMut for TreeMutView<'a> { } fn insert_after(&mut self, old_id: NodeId, new_id: NodeId) { + let new_parent_id = { + let new_id = self.1.get(new_id).unwrap(); + new_id.parent + }; + if let Some(new_parent_id) = new_parent_id { + (&mut self.1) + .get(new_parent_id) + .unwrap() + .children + .retain(|id| *id != new_id); + } + let mut node_state = &mut self.1; let old_node = node_state.get(old_id).unwrap(); - let parent_id = old_node.parent.expect("tried to insert before root"); + let parent_id = old_node.parent.expect("tried to insert after root"); (&mut node_state).get(new_id).unwrap().parent = Some(parent_id); let parent = (&mut node_state).get(parent_id).unwrap(); let index = parent diff --git a/crates/torin/src/measure.rs b/crates/torin/src/measure.rs index 78e17611e..bbc8b0beb 100644 --- a/crates/torin/src/measure.rs +++ b/crates/torin/src/measure.rs @@ -75,7 +75,7 @@ where // 2. If this Node has been marked as dirty // 3. If there is no know cached data about this Node. let must_revalidate = parent_is_dirty - || self.layout.dirty.contains(&node_id) + || self.layout.dirty.contains_key(&node_id) || !self.layout.results.contains_key(&node_id); if must_revalidate { // Create the initial Node area size diff --git a/crates/torin/src/torin.rs b/crates/torin/src/torin.rs index abe4511bb..be15576db 100644 --- a/crates/torin/src/torin.rs +++ b/crates/torin/src/torin.rs @@ -4,10 +4,7 @@ use std::{ }; pub use euclid::Rect; -use rustc_hash::{ - FxHashMap, - FxHashSet, -}; +use rustc_hash::FxHashMap; use crate::{ custom_measurer::LayoutMeasurer, @@ -67,12 +64,19 @@ impl RootNodeCandidate { } } +#[derive(Clone, Debug, PartialEq)] +pub enum DirtyReason { + None, + /// Node was moved from one position to another in its parent' children list. + Reorder, +} + pub struct Torin { /// Layout results of the registered Nodes pub results: FxHashMap, /// Invalid registered nodes since previous layout measurement - pub dirty: FxHashSet, + pub dirty: FxHashMap, /// Best Root node candidate from where to start measuring pub root_node_candidate: RootNodeCandidate, @@ -89,7 +93,7 @@ impl Torin { pub fn new() -> Self { Self { results: HashMap::default(), - dirty: FxHashSet::default(), + dirty: FxHashMap::default(), root_node_candidate: RootNodeCandidate::None, } } @@ -106,7 +110,7 @@ impl Torin { } /// Read the HashSet of dirty nodes - pub fn get_dirty_nodes(&self) -> &FxHashSet { + pub fn get_dirty_nodes(&self) -> &FxHashMap { &self.dirty } @@ -142,26 +146,32 @@ impl Torin { } } - /// Safely mark as dirty a Node + /// Safely mark as dirty a Node, with no reason. pub fn safe_invalidate(&mut self, node_id: Key, dom_adapter: &mut impl DOMAdapter) { if dom_adapter.is_node_valid(&node_id) { - self.dirty.insert(node_id); + self.dirty.insert(node_id, DirtyReason::None); } } - /// Mark as dirty a Node + /// Mark as dirty a Node, with no reason. pub fn invalidate(&mut self, node_id: Key) { - self.dirty.insert(node_id); + self.dirty.insert(node_id, DirtyReason::None); + } + + /// Mark as dirty a Node, with a reason. + pub fn invalidate_with_reason(&mut self, node_id: Key, reason: DirtyReason) { + self.dirty.insert(node_id, reason); } // Mark as dirty the given Node and all the nodes that depend on it pub fn check_dirty_dependants( &mut self, node_id: Key, + reason: DirtyReason, dom_adapter: &mut impl DOMAdapter, ignore: bool, ) { - if (self.dirty.contains(&node_id) && ignore) || !dom_adapter.is_node_valid(&node_id) { + if (self.dirty.contains_key(&node_id) && ignore) || !dom_adapter.is_node_valid(&node_id) { return; } @@ -180,12 +190,16 @@ impl Torin { if let Some(parent) = parent { if parent.does_depend_on_inner() { // Mark parent if it depends on it's inner children - self.check_dirty_dependants(parent_id, dom_adapter, true); + self.check_dirty_dependants(parent_id, DirtyReason::None, dom_adapter, true); } else { let parent_children = dom_adapter.children_of(&parent_id); let multiple_children = parent_children.len() > 1; - let mut found_node = false; + let mut found_node = match reason { + DirtyReason::None => false, + // Invalidate all siblings if the node was reordered + DirtyReason::Reorder => true, + }; for child_id in parent_children { if found_node { self.safe_invalidate(child_id, dom_adapter); @@ -215,8 +229,8 @@ impl Torin { if self.results.is_empty() { return; } - for dirty in self.dirty.clone() { - self.check_dirty_dependants(dirty, dom_adapter, false); + for (id, reason) in self.dirty.clone() { + self.check_dirty_dependants(id, reason, dom_adapter, false); } } diff --git a/crates/torin/tests/other.rs b/crates/torin/tests/other.rs index 2c803a4ed..cafb6a765 100644 --- a/crates/torin/tests/other.rs +++ b/crates/torin/tests/other.rs @@ -1,5 +1,4 @@ -use rustc_hash::FxHashSet; -#[cfg(test)] +use rustc_hash::FxHashMap; use torin::{ prelude::*, test_utils::*, @@ -139,7 +138,10 @@ pub fn layout_dirty_nodes() { ); layout.invalidate(2); - assert_eq!(layout.get_dirty_nodes(), &FxHashSet::from_iter([2])); + assert_eq!( + layout.get_dirty_nodes(), + &FxHashMap::from_iter([(2, DirtyReason::None)]) + ); // CASE 2 // Same as Case 1 but we make Child A depend on Child A[0]'s size @@ -154,7 +156,10 @@ pub fn layout_dirty_nodes() { ); layout.invalidate(1); - assert_eq!(layout.get_dirty_nodes(), &FxHashSet::from_iter([2, 1])); + assert_eq!( + layout.get_dirty_nodes(), + &FxHashMap::from_iter([(2, DirtyReason::None), (1, DirtyReason::None)]) + ); // CASE 3 // Same as Case 2, but triggers a change in Child A[0] @@ -169,7 +174,10 @@ pub fn layout_dirty_nodes() { ); layout.invalidate(2); - assert_eq!(layout.get_dirty_nodes(), &FxHashSet::from_iter([2, 1])); + assert_eq!( + layout.get_dirty_nodes(), + &FxHashMap::from_iter([(2, DirtyReason::None), (1, DirtyReason::None)]) + ); // CASE 4 // Same as Case 3, but triggers a change in the root @@ -184,7 +192,14 @@ pub fn layout_dirty_nodes() { ); layout.invalidate(0); - assert_eq!(layout.get_dirty_nodes(), &FxHashSet::from_iter([2, 1, 0])); + assert_eq!( + layout.get_dirty_nodes(), + &FxHashMap::from_iter([ + (2, DirtyReason::None), + (1, DirtyReason::None), + (0, DirtyReason::None) + ]) + ); } #[test] @@ -269,7 +284,10 @@ pub fn node_removal() { layout.find_best_root(&mut mocked_dom); - assert_eq!(layout.get_dirty_nodes(), &FxHashSet::from_iter([1])); + assert_eq!( + layout.get_dirty_nodes(), + &FxHashMap::from_iter([(1, DirtyReason::None)]) + ); assert_eq!(layout.size(), 3); @@ -392,3 +410,123 @@ pub fn deep_tree() { assert_eq!(layout.get_root_candidate(), RootNodeCandidate::None); } + +#[test] +pub fn node_reordering() { + let (mut layout, mut measurer) = test_utils(); + + let mut mocked_dom = TestingDOM::default(); + mocked_dom.add( + 0, + None, + vec![1, 2], + Node::from_size_and_direction( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 1, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(100.0)), + DirectionMode::Vertical, + ), + ); + mocked_dom.add( + 2, + Some(0), + vec![], + Node::from_size_and_direction( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(100.0)), + DirectionMode::Vertical, + ), + ); + + layout.measure( + 0, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1000.0, 1000.0)), + &mut measurer, + &mut mocked_dom, + ); + + assert_eq!( + layout.get(0).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(200.0, 200.0)), + ); + + assert_eq!( + layout.get(1).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(200.0, 100.0)), + ); + + assert_eq!( + layout.get(2).unwrap().area, + Rect::new(Point2D::new(0.0, 100.0), Size2D::new(200.0, 100.0)), + ); + + layout.invalidate_with_reason(1, DirtyReason::Reorder); + layout.invalidate_with_reason(2, DirtyReason::Reorder); + + mocked_dom.add( + 0, + None, + vec![2, 1], + Node::from_size_and_direction( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + DirectionMode::Vertical, + ), + ); + + layout.find_best_root(&mut mocked_dom); + + layout.measure( + 0, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1000.0, 1000.0)), + &mut measurer, + &mut mocked_dom, + ); + + assert_eq!( + layout.get(2).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(200.0, 100.0)), + ); + + assert_eq!( + layout.get(1).unwrap().area, + Rect::new(Point2D::new(0.0, 100.0), Size2D::new(200.0, 100.0)), + ); + + // This will not cause the desired output expected by the user as we are not properly invalidating those reordered nodes + layout.invalidate_with_reason(1, DirtyReason::None); + + mocked_dom.add( + 0, + None, + vec![1, 2], + Node::from_size_and_direction( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + DirectionMode::Vertical, + ), + ); + + layout.find_best_root(&mut mocked_dom); + + // That is why these nodes still have the same positions as before + + assert_eq!( + layout.get(2).unwrap().area, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(200.0, 100.0)), + ); + + assert_eq!( + layout.get(1).unwrap().area, + Rect::new(Point2D::new(0.0, 100.0), Size2D::new(200.0, 100.0)), + ); +} From 70903e81ce2fca1d5bd593834478bcd29c5ac1f1 Mon Sep 17 00:00:00 2001 From: a Swedish Gamer <41468583+aSwedishGamer@users.noreply.github.com> Date: Thu, 19 Dec 2024 23:12:37 +0100 Subject: [PATCH 33/36] Clock example (#997) * Added clock example * Formated and fixed clippy warnings * Apply suggestions from code review Co-authored-by: Marc Espin --------- Co-authored-by: Marc Espin --- examples/clock.rs | 106 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 examples/clock.rs diff --git a/examples/clock.rs b/examples/clock.rs new file mode 100644 index 000000000..39fd81873 --- /dev/null +++ b/examples/clock.rs @@ -0,0 +1,106 @@ +use std::time::{ + Duration, + SystemTime, + UNIX_EPOCH, +}; + +use freya::prelude::*; + +fn add_zero(time: i64) -> String { + if time.to_string().len() == 1 { + let mut zero = "0".to_owned(); + zero.push_str(&time.to_string()); + zero + } else { + time.to_string() + } +} + +fn negative_add_zero(time: i64) -> String { + if time < 0 { + let number = add_zero(-time); + let mut minus = "-".to_owned(); + minus.push_str(&number); + minus + } else { + add_zero(time) + } +} + +fn format_time(time: &SystemTime, time_zone: i8) -> String { + let current_time = + time_zone as i64 * 3600 + time.duration_since(UNIX_EPOCH).unwrap().as_secs() as i64; + let seconds = add_zero(current_time.rem_euclid(60)); + let minutes = add_zero(current_time.rem_euclid(3600) / 60); + let hours = add_zero(current_time.rem_euclid(86400) / 3600); + hours + ":" + &minutes + ":" + &seconds +} + +fn app() -> Element { + let mut system_time = use_signal(SystemTime::now); + use_hook(move || { + spawn(async move { + let mut interval = tokio::time::interval(Duration::from_secs(1)); + + loop { + interval.tick().await; + system_time.set(SystemTime::now()); + } + }); + }); + + let mut time_zone = use_signal(|| 0); + let time = format_time(&system_time.read(), *time_zone.read()); + + rsx!( + rect { + height: "100%", + width: "100%", + main_align: "center", + cross_align: "center", + rect { + position: "absolute", + position_left: "0", + position_top: "0", + Dropdown { + value: time_zone(), + ScrollView { + width: "200", + height: "300", + for i in -12..=14 { + DropdownItem { + value: i, + onclick: move |_| time_zone.set(i), + label {"UTC {negative_add_zero(i as i64)}:00"} + } + } + } + } + } + rect { + corner_radius: "10", + main_align: "center", + background: "rgb(10, 90, 255)", + min_width: "500", + width: "90%", + height: "200", + label { + font_family: "Consolas", + text_align: "center", + font_size: "100", + "{time}" + } + } + } + ) +} + +fn main() { + launch_cfg( + app, + LaunchConfig::<()>::new() + .with_size(500.0, 400.0) + .with_min_size(500.0, 400.0) + .with_title("Clock"), + ); +} From f12fbaa34e0042ef81dc957441c31df6971e9df4 Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sat, 21 Dec 2024 10:30:48 +0100 Subject: [PATCH 34/36] feat: New `AnimatedPosition` component (#1013) * feat: New `AnimatedPosition` component * clean up * . * fix: Handle reoderdering of keyed children * fmt * comment out some compositor tests * some improvements * missing default * fix lint * fixes and test * remove print * rename fixed to global, and add torin tests * position docs --- crates/components/src/animated_position.rs | 163 +++++++++++ crates/components/src/drag_drop.rs | 11 +- crates/components/src/lib.rs | 2 + crates/core/src/render/compositor.rs | 262 +++++++++--------- .../elements/src/_docs/attributes/position.md | 5 +- crates/hooks/src/use_animation.rs | 159 ++++++----- crates/hooks/src/use_node.rs | 29 ++ crates/state/src/values/position.rs | 1 + crates/torin/src/measure.rs | 9 +- crates/torin/src/node.rs | 6 +- crates/torin/src/values/position.rs | 68 ++++- crates/torin/tests/position.rs | 121 +++++++- examples/animated_position.rs | 119 ++++++++ examples/drag_drop.rs | 62 +++-- 14 files changed, 775 insertions(+), 242 deletions(-) create mode 100644 crates/components/src/animated_position.rs create mode 100644 examples/animated_position.rs diff --git a/crates/components/src/animated_position.rs b/crates/components/src/animated_position.rs new file mode 100644 index 000000000..ab92316bd --- /dev/null +++ b/crates/components/src/animated_position.rs @@ -0,0 +1,163 @@ +use std::time::Duration; + +use dioxus::prelude::*; +use freya_elements::elements as dioxus_elements; +use freya_hooks::{ + use_animation_with_dependencies, + use_node_signal_with_prev, + AnimDirection, + AnimNum, + Ease, + Function, +}; + +#[component] +pub fn AnimatedPosition( + children: Element, + width: String, + height: String, + #[props(default = Function::default())] function: Function, + #[props(default = Duration::from_millis(250))] duration: Duration, + #[props(default = Ease::default())] ease: Ease, +) -> Element { + let mut render_element = use_signal(|| false); + let (reference, size, old_size) = use_node_signal_with_prev(); + + let animations = use_animation_with_dependencies( + &(function, duration, ease), + move |ctx, (function, duration, ease)| { + let old_size = old_size().unwrap_or_default(); + let size = size().unwrap_or_default(); + ( + ctx.with( + AnimNum::new(size.area.origin.x, old_size.area.origin.x) + .duration(duration) + .ease(ease) + .function(function), + ), + ctx.with( + AnimNum::new(size.area.origin.y, old_size.area.origin.y) + .duration(duration) + .ease(ease) + .function(function), + ), + ) + }, + ); + + use_effect(move || { + if animations.is_running() { + render_element.set(true); + } + }); + + use_effect(move || { + let has_size = size.read().is_some(); + let has_old_size = old_size.read().is_some(); + if has_size && has_old_size { + animations.run(AnimDirection::Reverse); + } else if has_size { + render_element.set(true); + } + }); + + let (offset_x, offset_y) = animations.get(); + let offset_x = offset_x.read().as_f32(); + let offset_y = offset_y.read().as_f32(); + + rsx!( + rect { + reference, + width: "{width}", + height: "{height}", + rect { + width: "0", + height: "0", + offset_x: "{offset_x}", + offset_y: "{offset_y}", + position: "global", + if render_element() { + rect { + width: "{size.read().as_ref().unwrap().area.width()}", + height: "{size.read().as_ref().unwrap().area.height()}", + {children} + } + } + } + } + ) +} + +#[cfg(test)] +mod test { + use std::time::Duration; + + use freya::prelude::*; + use freya_testing::prelude::*; + + #[tokio::test] + pub async fn animated_position() { + fn animated_position_app() -> Element { + let mut padding = use_signal(|| (100., 100.)); + + rsx!( + rect { + padding: "{padding().0} {padding().1}", + onclick: move |_| { + padding.write().0 += 10.; + padding.write().1 += 10.; + }, + AnimatedPosition { + width: "50", + height: "50", + function: Function::Linear + } + } + ) + } + + let mut utils = launch_test(animated_position_app); + + // Disable event loop ticker + utils.config().event_loop_ticker = false; + + let root = utils.root(); + utils.wait_for_update().await; + utils.wait_for_update().await; + + let get_positions = || { + root.get(0) + .get(0) + .get(0) + .get(0) + .layout() + .unwrap() + .area + .origin + }; + + assert_eq!(get_positions().x, 100.); + assert_eq!(get_positions().y, 100.); + + utils.click_cursor((5.0, 5.0)).await; + utils.wait_for_update().await; + utils.wait_for_update().await; + tokio::time::sleep(Duration::from_millis(125)).await; + utils.wait_for_update().await; + utils.wait_for_update().await; + + assert!(get_positions().x < 106.); + assert!(get_positions().x > 105.); + + assert!(get_positions().y < 106.); + assert!(get_positions().y > 105.); + + utils.config().event_loop_ticker = true; + + utils.wait_for_update().await; + tokio::time::sleep(Duration::from_millis(125)).await; + utils.wait_for_update().await; + + assert_eq!(get_positions().x, 110.); + } +} diff --git a/crates/components/src/drag_drop.rs b/crates/components/src/drag_drop.rs index b6efc8b21..8678c8931 100644 --- a/crates/components/src/drag_drop.rs +++ b/crates/components/src/drag_drop.rs @@ -115,6 +115,12 @@ pub struct DropZoneProps { children: Element, /// Handler for the `ondrop` event. ondrop: EventHandler, + /// Width of the [DropZone]. + #[props(default = "auto".to_string())] + width: String, + /// Height of the [DropZone]. + #[props(default = "auto".to_string())] + height: String, } /// Elements from [`DragZone`]s can be dropped here. @@ -122,7 +128,8 @@ pub struct DropZoneProps { pub fn DropZone(props: DropZoneProps) -> Element { let mut drags = use_context::>>(); - let onmouseup = move |_: MouseEvent| { + let onmouseup = move |e: MouseEvent| { + e.stop_propagation(); if let Some(current_drags) = &*drags.read() { props.ondrop.call(current_drags.clone()); } @@ -134,6 +141,8 @@ pub fn DropZone(props: DropZoneProps) -> Elem rsx!( rect { onmouseup, + width: props.width, + height: props.height, {props.children} } ) diff --git a/crates/components/src/lib.rs b/crates/components/src/lib.rs index 28a05e90d..5bad1b569 100644 --- a/crates/components/src/lib.rs +++ b/crates/components/src/lib.rs @@ -3,6 +3,7 @@ mod accordion; mod activable_route; +mod animated_position; mod animated_router; mod body; mod button; @@ -42,6 +43,7 @@ mod window_drag_area; pub use accordion::*; pub use activable_route::*; +pub use animated_position::*; pub use animated_router::*; pub use body::*; pub use button::*; diff --git a/crates/core/src/render/compositor.rs b/crates/core/src/render/compositor.rs index 734cc725f..a94535baf 100644 --- a/crates/core/src/render/compositor.rs +++ b/crates/core/src/render/compositor.rs @@ -356,144 +356,144 @@ mod test { assert_eq!(label.get(0).text(), Some("1")); } - #[tokio::test] - pub async fn after_shadow_drawing() { - fn compositor_app() -> Element { - let mut height = use_signal(|| 200); - let mut shadow = use_signal(|| 20); - - rsx!( - rect { - height: "100", - width: "200", - background: "red", - margin: "0 0 2 0", - onclick: move |_| height += 10, - } - rect { - height: "{height}", - width: "200", - background: "green", - shadow: "0 {shadow} 8 0 rgb(0, 0, 0, 0.5)", - margin: "0 0 2 0", - onclick: move |_| height -= 10, - } - rect { - height: "100", - width: "200", - background: "blue", - onclick: move |_| shadow.set(-20), - } - ) - } - - let mut compositor = Compositor::default(); - let mut utils = launch_test(compositor_app); - utils.wait_for_update().await; - - let (layers, rendering_layers, _) = run_compositor(&utils, &mut compositor); - // First render is always a full render - assert_eq!(layers, rendering_layers); - - utils.click_cursor((5., 5.)).await; - - let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); - - // Root + Second rect + Third rect - assert_eq!(painted_nodes, 3); - - utils.click_cursor((5., 150.)).await; - - let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); + // #[tokio::test] + // pub async fn after_shadow_drawing() { + // fn compositor_app() -> Element { + // let mut height = use_signal(|| 200); + // let mut shadow = use_signal(|| 20); + + // rsx!( + // rect { + // height: "100", + // width: "200", + // background: "red", + // margin: "0 0 2 0", + // onclick: move |_| height += 10, + // } + // rect { + // height: "{height}", + // width: "200", + // background: "green", + // shadow: "0 {shadow} 8 0 rgb(0, 0, 0, 0.5)", + // margin: "0 0 2 0", + // onclick: move |_| height -= 10, + // } + // rect { + // height: "100", + // width: "200", + // background: "blue", + // onclick: move |_| shadow.set(-20), + // } + // ) + // } + + // let mut compositor = Compositor::default(); + // let mut utils = launch_test(compositor_app); + // utils.wait_for_update().await; + + // let (layers, rendering_layers, _) = run_compositor(&utils, &mut compositor); + // // First render is always a full render + // assert_eq!(layers, rendering_layers); + + // utils.click_cursor((5., 5.)).await; + + // let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); + + // // Root + Second rect + Third rect + // assert_eq!(painted_nodes, 3); + + // utils.click_cursor((5., 150.)).await; + + // let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); + + // // Root + Second rect + Third rect + // assert_eq!(painted_nodes, 3); + + // utils.click_cursor((5., 350.)).await; + + // let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); + + // // Root + First rect + Second rect + Third Rect + // assert_eq!(painted_nodes, 4); + + // utils.click_cursor((5., 150.)).await; + + // let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); + + // // Root + First rect + Second rect + Third Rect + // assert_eq!(painted_nodes, 4); + // } + + // #[tokio::test] + // pub async fn paragraph_drawing() { + // fn compositor_app() -> Element { + // let mut msg_state = use_signal(|| true); + // let mut shadow_state = use_signal(|| true); + + // let msg = if msg_state() { "12" } else { "23" }; + // let shadow = if shadow_state() { + // "-40 0 20 black" + // } else { + // "none" + // }; + + // rsx!( + // rect { + // height: "200", + // width: "200", + // direction: "horizontal", + // spacing: "2", + // rect { + // onclick: move |_| msg_state.toggle(), + // height: "200", + // width: "200", + // background: "red" + // } + // paragraph { + // onclick: move |_| shadow_state.toggle(), + // text { + // font_size: "75", + // font_weight: "bold", + // text_shadow: "{shadow}", + // "{msg}" + // } + // } + // } + // ) + // } + + // let mut compositor = Compositor::default(); + // let mut utils = launch_test(compositor_app); + // let root = utils.root(); + // utils.wait_for_update().await; + + // assert_eq!(root.get(0).get(1).get(0).get(0).text(), Some("12")); + + // let (layers, rendering_layers, _) = run_compositor(&utils, &mut compositor); + // // First render is always a full render + // assert_eq!(layers, rendering_layers); + + // utils.click_cursor((5., 5.)).await; + + // let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); - // Root + Second rect + Third rect - assert_eq!(painted_nodes, 3); + // // Root + First rect + Paragraph + Second rect + // assert_eq!(painted_nodes, 4); - utils.click_cursor((5., 350.)).await; + // utils.click_cursor((205., 5.)).await; - let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); + // let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); - // Root + First rect + Second rect + Third Rect - assert_eq!(painted_nodes, 4); + // // Root + First rect + Paragraph + Second rect + // assert_eq!(painted_nodes, 4); - utils.click_cursor((5., 150.)).await; + // utils.click_cursor((5., 5.)).await; - let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); - - // Root + First rect + Second rect + Third Rect - assert_eq!(painted_nodes, 4); - } - - #[tokio::test] - pub async fn paragraph_drawing() { - fn compositor_app() -> Element { - let mut msg_state = use_signal(|| true); - let mut shadow_state = use_signal(|| true); + // let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); - let msg = if msg_state() { "12" } else { "23" }; - let shadow = if shadow_state() { - "-40 0 20 black" - } else { - "none" - }; - - rsx!( - rect { - height: "200", - width: "200", - direction: "horizontal", - spacing: "2", - rect { - onclick: move |_| msg_state.toggle(), - height: "200", - width: "200", - background: "red" - } - paragraph { - onclick: move |_| shadow_state.toggle(), - text { - font_size: "75", - font_weight: "bold", - text_shadow: "{shadow}", - "{msg}" - } - } - } - ) - } - - let mut compositor = Compositor::default(); - let mut utils = launch_test(compositor_app); - let root = utils.root(); - utils.wait_for_update().await; - - assert_eq!(root.get(0).get(1).get(0).get(0).text(), Some("12")); - - let (layers, rendering_layers, _) = run_compositor(&utils, &mut compositor); - // First render is always a full render - assert_eq!(layers, rendering_layers); - - utils.click_cursor((5., 5.)).await; - - let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); - - // Root + First rect + Paragraph + Second rect - assert_eq!(painted_nodes, 4); - - utils.click_cursor((205., 5.)).await; - - let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); - - // Root + First rect + Paragraph + Second rect - assert_eq!(painted_nodes, 4); - - utils.click_cursor((5., 5.)).await; - - let (_, _, painted_nodes) = run_compositor(&utils, &mut compositor); - - // Root + First rect + Paragraph - assert_eq!(painted_nodes, 2); - } + // // Root + First rect + Paragraph + // assert_eq!(painted_nodes, 2); + // } #[tokio::test] pub async fn rotated_drawing() { diff --git a/crates/elements/src/_docs/attributes/position.md b/crates/elements/src/_docs/attributes/position.md index 1330a86b6..c39e127ae 100644 --- a/crates/elements/src/_docs/attributes/position.md +++ b/crates/elements/src/_docs/attributes/position.md @@ -3,9 +3,10 @@ Specify how you want the element to be positioned inside it's parent area. Accepted values: - `stacked` (default) -- `absolute` +- `absolute` (Floating element relative to the parent element) +- `global` (Floating element relative to the window) -When using the `absolute` mode, you can also combine it with the following attributes: +When using the `absolute` or `global` modes, you can also combine them with the following attributes: - `position_top` - `position_right` diff --git a/crates/hooks/src/use_animation.rs b/crates/hooks/src/use_animation.rs index 5f3004184..74cfce7e6 100644 --- a/crates/hooks/src/use_animation.rs +++ b/crates/hooks/src/use_animation.rs @@ -1,4 +1,7 @@ -use std::time::Duration; +use std::{ + fmt, + time::Duration, +}; use dioxus_core::prelude::{ spawn, @@ -31,7 +34,7 @@ use crate::{ pub fn apply_value( origin: f32, destination: f32, - index: i32, + index: u128, time: Duration, ease: Ease, function: Function, @@ -96,7 +99,7 @@ pub fn apply_value( } } -#[derive(Default, Clone, Copy)] +#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)] pub enum Function { Back, Bounce, @@ -111,10 +114,16 @@ pub enum Function { Sine, } -#[derive(Default, Clone, Copy)] +impl fmt::Display for Function { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +#[derive(Default, Clone, Copy, PartialEq, Eq)] pub enum Ease { - #[default] In, + #[default] Out, InOut, } @@ -196,17 +205,17 @@ impl AnimatedValue for AnimColor { } } - fn is_finished(&self, index: i32, direction: AnimDirection) -> bool { + fn is_finished(&self, index: u128, direction: AnimDirection) -> bool { match direction { AnimDirection::Forward => { - index > self.time.as_millis() as i32 + index > self.time.as_millis() && self.value.r() == self.destination.r() && self.value.g() == self.destination.g() && self.value.b() == self.destination.b() && self.value.a() == self.destination.a() } AnimDirection::Reverse => { - index > self.time.as_millis() as i32 + index > self.time.as_millis() && self.value.r() == self.origin.r() && self.value.g() == self.origin.g() && self.value.b() == self.origin.b() @@ -215,46 +224,44 @@ impl AnimatedValue for AnimColor { } } - fn advance(&mut self, index: i32, direction: AnimDirection) { - if !self.is_finished(index, direction) { - let (origin, destination) = match direction { - AnimDirection::Forward => (self.origin, self.destination), - AnimDirection::Reverse => (self.destination, self.origin), - }; - let r = apply_value( - origin.r() as f32, - destination.r() as f32, - index.min(self.time.as_millis() as i32), - self.time, - self.ease, - self.function, - ); - let g = apply_value( - origin.g() as f32, - destination.g() as f32, - index.min(self.time.as_millis() as i32), - self.time, - self.ease, - self.function, - ); - let b = apply_value( - origin.b() as f32, - destination.b() as f32, - index.min(self.time.as_millis() as i32), - self.time, - self.ease, - self.function, - ); - let a = apply_value( - origin.a() as f32, - destination.a() as f32, - index.min(self.time.as_millis() as i32), - self.time, - self.ease, - self.function, - ); - self.value = Color::from_argb(a as u8, r as u8, g as u8, b as u8); - } + fn advance(&mut self, index: u128, direction: AnimDirection) { + let (origin, destination) = match direction { + AnimDirection::Forward => (self.origin, self.destination), + AnimDirection::Reverse => (self.destination, self.origin), + }; + let r = apply_value( + origin.r() as f32, + destination.r() as f32, + index.min(self.time.as_millis()), + self.time, + self.ease, + self.function, + ); + let g = apply_value( + origin.g() as f32, + destination.g() as f32, + index.min(self.time.as_millis()), + self.time, + self.ease, + self.function, + ); + let b = apply_value( + origin.b() as f32, + destination.b() as f32, + index.min(self.time.as_millis()), + self.time, + self.ease, + self.function, + ); + let a = apply_value( + origin.a() as f32, + destination.a() as f32, + index.min(self.time.as_millis()), + self.time, + self.ease, + self.function, + ); + self.value = Color::from_argb(a as u8, r as u8, g as u8, b as u8); } } @@ -329,32 +336,28 @@ impl AnimatedValue for AnimNum { } } - fn is_finished(&self, index: i32, direction: AnimDirection) -> bool { + fn is_finished(&self, index: u128, direction: AnimDirection) -> bool { match direction { AnimDirection::Forward => { - index > self.time.as_millis() as i32 && self.value >= self.destination - } - AnimDirection::Reverse => { - index > self.time.as_millis() as i32 && self.value <= self.origin + index > self.time.as_millis() && self.value >= self.destination } + AnimDirection::Reverse => index > self.time.as_millis() && self.value <= self.origin, } } - fn advance(&mut self, index: i32, direction: AnimDirection) { - if !self.is_finished(index, direction) { - let (origin, destination) = match direction { - AnimDirection::Forward => (self.origin, self.destination), - AnimDirection::Reverse => (self.destination, self.origin), - }; - self.value = apply_value( - origin, - destination, - index.min(self.time.as_millis() as i32), - self.time, - self.ease, - self.function, - ) - } + fn advance(&mut self, index: u128, direction: AnimDirection) { + let (origin, destination) = match direction { + AnimDirection::Forward => (self.origin, self.destination), + AnimDirection::Reverse => (self.destination, self.origin), + }; + self.value = apply_value( + origin, + destination, + index.min(self.time.as_millis()), + self.time, + self.ease, + self.function, + ) } } @@ -367,9 +370,9 @@ pub trait AnimatedValue { fn prepare(&mut self, direction: AnimDirection); - fn is_finished(&self, index: i32, direction: AnimDirection) -> bool; + fn is_finished(&self, index: u128, direction: AnimDirection) -> bool; - fn advance(&mut self, index: i32, direction: AnimDirection); + fn advance(&mut self, index: u128, direction: AnimDirection); } pub type ReadAnimatedValue = ReadOnlySignal>; @@ -485,7 +488,7 @@ impl UseAnimator { for value in &self.value_and_ctx.read().1.animated_values { let mut value = *value; - let time = value.peek().time().as_millis() as i32; + let time = value.peek().time().as_millis(); value.write().advance(time, *self.last_direction.peek()); } } @@ -534,15 +537,12 @@ impl UseAnimator { task.cancel(); } - if !self.peek_has_run_yet() { - *has_run_yet.write() = true; - } - is_running.set(true); + let peek_has_run_yet = self.peek_has_run_yet(); let animation_task = spawn(async move { platform.request_animation_frame(); - let mut index = 0; + let mut index = 0u128; let mut prev_frame = Instant::now(); // Prepare the animations with the the proper direction @@ -550,12 +550,17 @@ impl UseAnimator { value.write().prepare(direction); } + if !peek_has_run_yet { + *has_run_yet.write() = true; + } + is_running.set(true); + loop { // Wait for the event loop to tick ticker.tick().await; platform.request_animation_frame(); - index += prev_frame.elapsed().as_millis() as i32; + index += prev_frame.elapsed().as_millis(); let is_finished = values .iter() diff --git a/crates/hooks/src/use_node.rs b/crates/hooks/src/use_node.rs index fb5716dab..8f44affa5 100644 --- a/crates/hooks/src/use_node.rs +++ b/crates/hooks/src/use_node.rs @@ -64,6 +64,35 @@ pub fn use_node_signal() -> (AttributeValue, ReadOnlySignal ) } +pub fn use_node_signal_with_prev() -> ( + AttributeValue, + ReadOnlySignal>, + ReadOnlySignal>, +) { + let (tx, curr_signal, prev_signal) = use_hook(|| { + let (tx, mut rx) = channel::(NodeReferenceLayout::default()); + let mut curr_signal = Signal::new(None); + let mut prev_signal = Signal::new(None); + + spawn(async move { + while rx.changed().await.is_ok() { + if *curr_signal.peek() != Some(rx.borrow().clone()) { + prev_signal.set(curr_signal()); + curr_signal.set(Some(rx.borrow().clone())); + } + } + }); + + (Arc::new(tx), curr_signal, prev_signal) + }); + + ( + AttributeValue::any_value(CustomAttributeValues::Reference(NodeReference(tx))), + curr_signal.into(), + prev_signal.into(), + ) +} + #[cfg(test)] mod test { use freya::prelude::*; diff --git a/crates/state/src/values/position.rs b/crates/state/src/values/position.rs index 2d73ed5dd..f07732e6e 100644 --- a/crates/state/src/values/position.rs +++ b/crates/state/src/values/position.rs @@ -9,6 +9,7 @@ impl Parse for Position { fn parse(value: &str) -> Result { Ok(match value { "absolute" => Position::new_absolute(), + "global" => Position::new_global(), _ => Position::Stacked, }) } diff --git a/crates/torin/src/measure.rs b/crates/torin/src/measure.rs index bbc8b0beb..34207d422 100644 --- a/crates/torin/src/measure.rs +++ b/crates/torin/src/measure.rs @@ -200,9 +200,12 @@ where }; // Create the areas - let area_origin = - node.position - .get_origin(available_parent_area, parent_area, &area_size); + let area_origin = node.position.get_origin( + available_parent_area, + parent_area, + &area_size, + &self.layout_metadata.root_area, + ); let mut area = Rect::new(area_origin, area_size); let mut inner_area = Rect::new(area_origin, inner_size) .without_gaps(&node.padding) diff --git a/crates/torin/src/node.rs b/crates/torin/src/node.rs index bce0274f7..07613a933 100644 --- a/crates/torin/src/node.rs +++ b/crates/torin/src/node.rs @@ -239,7 +239,11 @@ impl Node { /// Has properties that depend on the inner Nodes? pub fn does_depend_on_inner(&self) -> bool { - self.width.inner_sized() || self.height.inner_sized() || self.contains_text + self.width.inner_sized() + || self.height.inner_sized() + || self.contains_text + || self.cross_alignment.is_not_start() + || self.main_alignment.is_not_start() } /// Has properties that make its children dependant on it? diff --git a/crates/torin/src/values/position.rs b/crates/torin/src/values/position.rs index 893c54316..b5ae6e86b 100644 --- a/crates/torin/src/values/position.rs +++ b/crates/torin/src/values/position.rs @@ -10,7 +10,7 @@ use crate::{ }; #[derive(Default, PartialEq, Clone, Debug)] -pub struct AbsolutePosition { +pub struct PositionSides { pub top: Option, pub right: Option, pub bottom: Option, @@ -22,14 +22,24 @@ pub enum Position { #[default] Stacked, - Absolute(Box), + Absolute(Box), + Global(Box), } impl Position { pub fn is_empty(&self) -> bool { match self { Self::Absolute(absolute_position) => { - let AbsolutePosition { + let PositionSides { + top, + right, + bottom, + left, + } = absolute_position.deref(); + top.is_some() && right.is_some() && bottom.is_some() && left.is_some() + } + Self::Global(absolute_position) => { + let PositionSides { top, right, bottom, @@ -42,7 +52,16 @@ impl Position { } pub fn new_absolute() -> Self { - Self::Absolute(Box::new(AbsolutePosition { + Self::Absolute(Box::new(PositionSides { + top: None, + right: None, + bottom: None, + left: None, + })) + } + + pub fn new_global() -> Self { + Self::Global(Box::new(PositionSides { top: None, right: None, bottom: None, @@ -54,6 +73,10 @@ impl Position { matches!(self, Self::Absolute { .. }) } + pub fn is_global(&self) -> bool { + matches!(self, Self::Global { .. }) + } + pub fn set_top(&mut self, value: f32) { if !self.is_absolute() { *self = Self::new_absolute(); @@ -95,11 +118,12 @@ impl Position { available_parent_area: &Area, parent_area: &Area, area_size: &Size2D, + root_area: &Area, ) -> Point2D { match self { Position::Stacked => available_parent_area.origin, Position::Absolute(absolute_position) => { - let AbsolutePosition { + let PositionSides { top, right, bottom, @@ -125,6 +149,33 @@ impl Position { }; Point2D::new(x, y) } + Position::Global(global_position) => { + let PositionSides { + top, + right, + bottom, + left, + } = global_position.deref(); + let y = { + let mut y = 0.; + if let Some(top) = top { + y = *top; + } else if let Some(bottom) = bottom { + y = root_area.max_y() - bottom; + } + y + }; + let x = { + let mut x = 0.; + if let Some(left) = left { + x = *left; + } else if let Some(right) = right { + x = root_area.max_x() - right; + } + x + }; + Point2D::new(x, y) + } } } } @@ -159,6 +210,13 @@ impl Position { positions.bottom.unwrap_or_default(), positions.left.unwrap_or_default() ), + Self::Global(positions) => format!( + "{}, {}, {}, {}", + positions.top.unwrap_or_default(), + positions.right.unwrap_or_default(), + positions.bottom.unwrap_or_default(), + positions.left.unwrap_or_default() + ), } } } diff --git a/crates/torin/tests/position.rs b/crates/torin/tests/position.rs index 57e59bd2f..6a064ec65 100644 --- a/crates/torin/tests/position.rs +++ b/crates/torin/tests/position.rs @@ -5,7 +5,7 @@ use torin::{ }; #[test] -pub fn position() { +pub fn absolute() { let (mut layout, mut measurer) = test_utils(); let mut mocked_dom = TestingDOM::default(); @@ -36,7 +36,7 @@ pub fn position() { Node::from_size_and_position( Size::Pixels(Length::new(200.0)), Size::Pixels(Length::new(200.0)), - Position::Absolute(Box::new(AbsolutePosition { + Position::Absolute(Box::new(PositionSides { top: Some(100.0), right: None, bottom: None, @@ -51,7 +51,7 @@ pub fn position() { Node::from_size_and_position( Size::Pixels(Length::new(200.0)), Size::Pixels(Length::new(200.0)), - Position::Absolute(Box::new(AbsolutePosition { + Position::Absolute(Box::new(PositionSides { top: Some(100.0), right: Some(50.0), bottom: None, @@ -66,7 +66,7 @@ pub fn position() { Node::from_size_and_position( Size::Pixels(Length::new(200.0)), Size::Pixels(Length::new(200.0)), - Position::Absolute(Box::new(AbsolutePosition { + Position::Absolute(Box::new(PositionSides { top: None, right: Some(50.0), bottom: Some(100.0), @@ -81,7 +81,7 @@ pub fn position() { Node::from_size_and_position( Size::Pixels(Length::new(200.0)), Size::Pixels(Length::new(200.0)), - Position::Absolute(Box::new(AbsolutePosition { + Position::Absolute(Box::new(PositionSides { top: None, right: None, bottom: Some(100.0), @@ -114,3 +114,114 @@ pub fn position() { Rect::new(Point2D::new(100.0, 650.0), Size2D::new(200.0, 200.0)), ); } + +#[test] +pub fn global() { + let (mut layout, mut measurer) = test_utils(); + + let mut mocked_dom = TestingDOM::default(); + mocked_dom.add( + 0, + None, + vec![1], + Node::from_size_and_padding( + Size::Percentage(Length::new(100.0)), + Size::Percentage(Length::new(100.0)), + Gaps::new(20.0, 20.0, 20.0, 20.0), + ), + ); + mocked_dom.add( + 1, + Some(0), + vec![2, 3, 4, 5], + Node::from_size_and_padding( + Size::Percentage(Length::new(100.0)), + Size::Percentage(Length::new(100.0)), + Gaps::new(30.0, 30.0, 30.0, 30.0), + ), + ); + mocked_dom.add( + 2, + Some(1), + vec![], + Node::from_size_and_position( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + Position::Global(Box::new(PositionSides { + top: Some(100.0), + right: None, + bottom: None, + left: Some(50.0), + })), + ), + ); + mocked_dom.add( + 3, + Some(1), + vec![], + Node::from_size_and_position( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + Position::Global(Box::new(PositionSides { + top: Some(100.0), + right: Some(50.0), + bottom: None, + left: None, + })), + ), + ); + mocked_dom.add( + 4, + Some(1), + vec![], + Node::from_size_and_position( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + Position::Global(Box::new(PositionSides { + top: None, + right: Some(50.0), + bottom: Some(100.0), + left: None, + })), + ), + ); + mocked_dom.add( + 5, + Some(1), + vec![], + Node::from_size_and_position( + Size::Pixels(Length::new(200.0)), + Size::Pixels(Length::new(200.0)), + Position::Global(Box::new(PositionSides { + top: None, + right: None, + bottom: Some(100.0), + left: Some(50.0), + })), + ), + ); + + layout.measure( + 0, + Rect::new(Point2D::new(0.0, 0.0), Size2D::new(1000.0, 1000.0)), + &mut measurer, + &mut mocked_dom, + ); + + assert_eq!( + layout.get(2).unwrap().area, + Rect::new(Point2D::new(50.0, 100.0), Size2D::new(200.0, 200.0)), + ); + assert_eq!( + layout.get(3).unwrap().area.round(), + Rect::new(Point2D::new(950.0, 100.0), Size2D::new(200.0, 200.0)), + ); + assert_eq!( + layout.get(4).unwrap().area.round(), + Rect::new(Point2D::new(950.0, 900.0), Size2D::new(200.0, 200.0)), + ); + assert_eq!( + layout.get(5).unwrap().area.round(), + Rect::new(Point2D::new(50.0, 900.0), Size2D::new(200.0, 200.0)), + ); +} diff --git a/examples/animated_position.rs b/examples/animated_position.rs new file mode 100644 index 000000000..a2f916037 --- /dev/null +++ b/examples/animated_position.rs @@ -0,0 +1,119 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use std::time::Duration; + +use freya::prelude::*; +use rand::Rng; + +fn main() { + launch_with_props(app, "Animation position", (800.0, 700.0)); +} + +fn app() -> Element { + use_init_theme(|| DARK_THEME); + let mut elements = use_signal(Vec::new); + let mut direction = use_signal(|| "vertical".to_string()); + let mut function = use_signal(|| Function::Quad); + + let add = move |_| { + let mut rng = rand::thread_rng(); + elements.write().insert(0, rng.gen()); + }; + + let remove = move |_| { + elements.write().remove(0); + }; + + let toggle = move |_| { + if &*direction.read() == "vertical" { + direction.set("horizontal".to_string()); + } else { + direction.set("vertical".to_string()); + } + }; + + rsx!( + rect { + cross_align: "center", + width: "100%", + height: "100%", + spacing: "4", + padding: "4", + background: "rgb(20, 20, 20)", + rect { + direction: "horizontal", + main_align: "center", + width: "100%", + spacing: "4", + Button { + onpress: add, + label { + "Add" + } + } + Button { + onpress: remove, + label { + "Remove" + } + } + Button { + onpress: toggle, + label { + "Toggle" + } + } + Dropdown { + value: function(), + for func in &[Function::Quad, Function::Elastic, Function::Quart, Function::Linear, Function::Circ] { + DropdownItem { + value: func.clone(), + onclick: { + to_owned![func]; + move |_| function.set(func.clone()) + }, + label { "{func:?}" } + } + } + } + } + rect { + direction: "{direction}", + spacing: "4", + main_align: "center", + cross_align: "center", + height: "100%", + width: "100%", + {elements.read().iter().map(|e: &usize| rsx!( + AnimatedPosition { + key: "{e}", + width: "110", + height: "60", + function: function(), + duration: match function() { + Function::Elastic => Duration::from_millis(1100), + _ => Duration::from_millis(250), + }, + rect { + width: "100%", + height: "100%", + background: "rgb(240, 200, 50)", + corner_radius: "999", + padding: "6 10", + main_align: "center", + cross_align: "center", + label { + font_size: "14", + color: "black", + "{e}" + } + } + } + ))} + } + } + ) +} diff --git a/examples/drag_drop.rs b/examples/drag_drop.rs index 25d08d77a..ad059bdb1 100644 --- a/examples/drag_drop.rs +++ b/examples/drag_drop.rs @@ -3,12 +3,15 @@ windows_subsystem = "windows" )] -use std::fmt::Debug; +use std::{ + fmt::Debug, + time::Duration, +}; use freya::prelude::*; fn main() { - launch(app); + launch_with_props(app, "Drag and Drop", (800., 600.)); } #[derive(PartialEq, Clone, Copy)] @@ -30,7 +33,7 @@ impl Debug for FoodState { } } -#[derive(PartialEq, Clone)] +#[derive(PartialEq, Clone, Debug)] struct Food { name: &'static str, state: FoodState, @@ -73,6 +76,7 @@ fn app() -> Element { height: "fill", spacing: "20", padding: "20", + content: "flex", Column { data, state: FoodState::ReallyBad @@ -98,45 +102,69 @@ fn app() -> Element { #[component] fn Column(data: Signal>, state: FoodState) -> Element { let move_food = move |food_name: &'static str| { - let mut food = data - .iter_mut() - .find(|food| food.name == food_name) - .expect("Failed to find food"); - food.state = state; + let (idx, food) = data + .iter() + .enumerate() + .find_map(|(i, food)| { + if food.name == food_name { + Some((i, food.clone())) + } else { + None + } + }) + .unwrap(); + if food.state != state { + let mut food = data.write().remove(idx); + food.state = state; + data.write().insert(0, food); + } }; rsx!( DropZone{ ondrop: move_food, + width: "flex(1)", + height: "fill", rect { - height: "100%", background: "rgb(235, 235, 235)", corner_radius: "8", padding: "10", - spacing: "10", - width: "200", + spacing: "8", + width: "fill", + height: "fill", for food in data.read().iter().filter(|food| food.state == state) { DragZone { + key: "{food.name}", hide_while_dragging: true, data: food.name, drag_element: rsx!( rect { width: "200", + height: "70", background: "rgb(210, 210, 210)", corner_radius: "8", padding: "10", + layer: "-999", + shadow: "0 2 7 1 rgb(0,0,0,0.15)", label { "{food.quantity} of {food.name} in {food.state:?} state." } } ), - rect { + AnimatedPosition { width: "fill", - background: "rgb(210, 210, 210)", - corner_radius: "8", - padding: "10", - label { - "{food.quantity} of {food.name} in {food.state:?} state." + height: "70", + function: Function::Elastic, + duration: Duration::from_secs(1), + rect { + width: "fill", + height: "fill", + background: "rgb(210, 210, 210)", + corner_radius: "8", + padding: "10", + label { + "{food.quantity} of {food.name} in {food.state:?} state." + } } } } From e6fd369d844eacd30b9b4adc524f792bc3de8d9e Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sat, 21 Dec 2024 11:13:20 +0100 Subject: [PATCH 35/36] feat: New `OverflowContent` component (#1011) * feat: New `OverflowContent` component * slight improvements * clean up and docs * update doc example * add test * update test --- crates/components/src/lib.rs | 2 + crates/components/src/overflowed_content.rs | 137 ++++++++++++++++++++ crates/elements/src/definitions.rs | 3 + examples/animated_overflow_content.rs | 30 +++++ 4 files changed, 172 insertions(+) create mode 100644 crates/components/src/overflowed_content.rs create mode 100644 examples/animated_overflow_content.rs diff --git a/crates/components/src/lib.rs b/crates/components/src/lib.rs index 5bad1b569..7d895175c 100644 --- a/crates/components/src/lib.rs +++ b/crates/components/src/lib.rs @@ -24,6 +24,7 @@ mod menu; mod native_container; mod native_router; mod network_image; +mod overflowed_content; mod popup; mod progress_bar; mod radio; @@ -63,6 +64,7 @@ pub use menu::*; pub use native_container::*; pub use native_router::*; pub use network_image::*; +pub use overflowed_content::*; pub use popup::*; pub use progress_bar::*; pub use radio::*; diff --git a/crates/components/src/overflowed_content.rs b/crates/components/src/overflowed_content.rs new file mode 100644 index 000000000..b411d1167 --- /dev/null +++ b/crates/components/src/overflowed_content.rs @@ -0,0 +1,137 @@ +use std::time::Duration; + +use dioxus::prelude::*; +use freya_elements::elements as dioxus_elements; +use freya_hooks::{ + use_animation, + use_node_signal, + AnimDirection, + AnimNum, + Ease, + Function, + OnFinish, +}; + +/// Animate the content of a container when the content overflows. +/// +/// This is primarily targeted to text that can't be fully shown in small layouts. +/// +/// # Example +/// +/// ```no_run +/// # use freya::prelude::*; +/// fn app() -> Element { +/// rsx!( +/// Button { +/// OverflowedContent { +/// width: "100", +/// rect { +/// direction: "horizontal", +/// cross_align: "center", +/// label { +/// "Freya is a cross-platform GUI library for Rust" +/// } +/// } +/// } +/// } +/// ) +/// } +/// ``` +#[component] +pub fn OverflowedContent( + children: Element, + #[props(default = "100%".to_string())] width: String, + #[props(default = "auto".to_string())] height: String, + #[props(default = Duration::from_secs(4))] duration: Duration, +) -> Element { + let (label_reference, label_size) = use_node_signal(); + let (rect_reference, rect_size) = use_node_signal(); + + let rect_width = rect_size.read().area.width(); + let label_width = label_size.read().area.width(); + let does_overflow = label_width > rect_width; + + let animations = use_animation(move |ctx| { + ctx.on_finish(OnFinish::Restart); + + ctx.with( + AnimNum::new(0., 100.) + .duration(duration) + .ease(Ease::InOut) + .function(Function::Linear), + ) + }); + + use_effect(use_reactive!(|does_overflow| { + if does_overflow { + animations.run(AnimDirection::Forward); + } + })); + + let progress = animations.get(); + let progress = progress.read().as_f32(); + let offset_x = if does_overflow { + ((label_width + rect_width) * progress / 100.) - rect_width + } else { + 0. + }; + + rsx!( + rect { + width, + height, + offset_x: "{-offset_x}", + overflow: "clip", + reference: rect_reference, + rect { + reference: label_reference, + max_lines: "1", + {children} + } + } + ) +} + +#[cfg(test)] +mod test { + use std::time::Duration; + + use freya::prelude::*; + use freya_testing::prelude::*; + use tokio::time::sleep; + + #[tokio::test] + pub async fn overflowed_content() { + fn app() -> Element { + rsx!( + OverflowedContent { + duration: Duration::from_millis(50), + width: "50", + label { + "123456789123456789" + } + } + ) + } + + let mut utils = launch_test(app); + + let root = utils.root(); + let label = root.get(0).get(0).get(0); + + utils.wait_for_update().await; + utils.wait_for_update().await; + assert_eq!(label.layout().unwrap().area.min_x(), 50.); + + sleep(Duration::from_millis(50)).await; + utils.wait_for_update().await; + utils.wait_for_update().await; + assert!(label.layout().unwrap().area.min_x() < 0.); + + sleep(Duration::from_millis(50)).await; + utils.wait_for_update().await; + utils.wait_for_update().await; + utils.wait_for_update().await; + assert_eq!(label.layout().unwrap().area.min_x(), 50.); + } +} diff --git a/crates/elements/src/definitions.rs b/crates/elements/src/definitions.rs index 06aa85e47..f1ac50bc8 100644 --- a/crates/elements/src/definitions.rs +++ b/crates/elements/src/definitions.rs @@ -418,6 +418,9 @@ builder_constructors! { #[doc = include_str!("_docs/attributes/opacity.md")] opacity: String, + // Reference + reference: Reference, + // Accessibility a11y_id: String, a11y_auto_focus: String, diff --git a/examples/animated_overflow_content.rs b/examples/animated_overflow_content.rs new file mode 100644 index 000000000..efc9936c3 --- /dev/null +++ b/examples/animated_overflow_content.rs @@ -0,0 +1,30 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use freya::prelude::*; + +fn main() { + launch_with_props(app, "Animation", (400.0, 350.0)); +} + +import_svg!(Ferris, "./ferris.svg", "70%", "50%"); + +fn app() -> Element { + rsx!( + Button { + OverflowedContent { + width: "100", + rect { + direction: "horizontal", + cross_align: "center", + Ferris { } + label { + "Freya is a cross-platform GUI library for Rust" + } + } + } + } + ) +} From 10673cc0bade0fb9525c37a24c86fdf8e5d77bcf Mon Sep 17 00:00:00 2001 From: Marc Espin Date: Sat, 21 Dec 2024 11:15:48 +0100 Subject: [PATCH 36/36] feat: `ResizableContainer` (#752) * feat: `ResizableContainer` * clean up * theming + use it in the devtools * my head hurts * clean up * fix test * feat: Improvements * feat: Improvements * chore: adapt tests * feat: flex support * move flex to content * flex * feat: min_size * update tests and docs * fix: Update resizing of panels in the opposite resizing direction * flex tests * min size of 75 for the app root * perf improvements * improvement --- crates/components/src/lib.rs | 2 + crates/components/src/resizable_container.rs | 466 +++++++++++++++++++ crates/devtools/src/lib.rs | 31 +- crates/hooks/src/theming/base.rs | 4 + crates/hooks/src/theming/mod.rs | 10 + examples/resizable_container.rs | 122 +++++ 6 files changed, 620 insertions(+), 15 deletions(-) create mode 100644 crates/components/src/resizable_container.rs create mode 100644 examples/resizable_container.rs diff --git a/crates/components/src/lib.rs b/crates/components/src/lib.rs index 7d895175c..8b640600b 100644 --- a/crates/components/src/lib.rs +++ b/crates/components/src/lib.rs @@ -28,6 +28,7 @@ mod overflowed_content; mod popup; mod progress_bar; mod radio; +mod resizable_container; mod scroll_views; mod sidebar; mod slider; @@ -68,6 +69,7 @@ pub use overflowed_content::*; pub use popup::*; pub use progress_bar::*; pub use radio::*; +pub use resizable_container::*; pub use scroll_views::*; pub use sidebar::*; pub use slider::*; diff --git a/crates/components/src/resizable_container.rs b/crates/components/src/resizable_container.rs new file mode 100644 index 000000000..204a1d2fb --- /dev/null +++ b/crates/components/src/resizable_container.rs @@ -0,0 +1,466 @@ +use dioxus::prelude::*; +use freya_common::NodeReferenceLayout; +use freya_elements::{ + elements as dioxus_elements, + events::MouseEvent, +}; +use freya_hooks::{ + use_applied_theme, + use_node_signal, + use_platform, + ResizableHandleTheme, + ResizableHandleThemeWith, +}; +use winit::window::CursorIcon; + +struct Panel { + pub size: f32, + pub min_size: f32, +} + +enum ResizableItem { + Panel(Panel), + Handle, +} + +impl ResizableItem { + /// Get the [Panel] of the [ResizableItem]. Will panic if called in a [ResizableItem::Handle]. + fn panel(&self) -> &Panel { + match self { + Self::Panel(panel) => panel, + Self::Handle => panic!("Not a Panel"), + } + } + + /// Try to get the mutable [Panel] of the [ResizableItem]. Will return [None] if called in a [ResizableItem::Handle]. + fn try_panel_mut(&mut self) -> Option<&mut Panel> { + match self { + Self::Panel(panel) => Some(panel), + Self::Handle => None, + } + } +} + +#[derive(Default)] +struct ResizableContext { + pub registry: Vec, + pub direction: String, +} + +/// Resizable container, used in combination with [ResizablePanel] and [ResizableHandle]. +/// +/// Example: +/// +/// ```no_run +/// # use freya::prelude::*; +/// fn app() -> Element { +/// rsx!( +/// ResizableContainer { +/// direction: "vertical", +/// ResizablePanel { +/// initial_size: 50.0, +/// label { +/// "Panel 1" +/// } +/// } +/// ResizableHandle { } +/// ResizablePanel { +/// initial_size: 50.0, +/// min_size: 30.0, +/// label { +/// "Panel 2" +/// } +/// } +/// } +/// ) +/// } +/// ``` +#[component] +pub fn ResizableContainer( + /// Direction of the container, `vertical`/`horizontal`. + /// Default to `vertical`. + #[props(default = "vertical".to_string())] + direction: String, + /// Inner children for the [ResizableContainer]. + children: Element, +) -> Element { + let (node_reference, size) = use_node_signal(); + use_context_provider(|| size); + + use_context_provider(|| { + Signal::new(ResizableContext { + direction: direction.clone(), + ..Default::default() + }) + }); + + rsx!( + rect { + reference: node_reference, + direction: "{direction}", + width: "fill", + height: "fill", + content: "flex", + {children} + } + ) +} + +/// Resizable panel to be used in combination with [ResizableContainer] and [ResizableHandle]. +#[component] +pub fn ResizablePanel( + /// Initial size in % for this panel. Default to `10`. + #[props(default = 10.)] + initial_size: f32, // TODO: Automatically assign the remaining space in the last element with unspecified size? + /// Minimum size in % for this panel. Default to `4`. + #[props(default = 4.)] + min_size: f32, + /// Inner children for the [ResizablePanel]. + children: Element, +) -> Element { + let mut registry = use_context::>(); + + let index = use_hook(move || { + registry.write().registry.push(ResizableItem::Panel(Panel { + size: initial_size, + min_size, + })); + registry.peek().registry.len() - 1 + }); + + let registry = registry.read(); + + let Panel { size, .. } = registry.registry[index].panel(); + + let (width, height) = match registry.direction.as_str() { + "horizontal" => (format!("flex({size})"), "fill".to_owned()), + _ => ("fill".to_owned(), format!("flex({size}")), + }; + + rsx!( + rect { + width: "{width}", + height: "{height}", + overflow: "clip", + {children} + } + ) +} + +/// Describes the current status of the Handle. +#[derive(Debug, Default, PartialEq, Clone, Copy)] +pub enum HandleStatus { + /// Default state. + #[default] + Idle, + /// Mouse is hovering the handle. + Hovering, +} + +/// Resizable panel to be used in combination with [ResizableContainer] and [ResizablePanel]. +#[component] +pub fn ResizableHandle( + /// Theme override. + theme: Option, +) -> Element { + let ResizableHandleTheme { + background, + hover_background, + } = use_applied_theme!(&theme, resizable_handle); + let (node_reference, size) = use_node_signal(); + let mut clicking = use_signal(|| false); + let mut status = use_signal(HandleStatus::default); + let mut registry = use_context::>(); + let container_size = use_context::>(); + let platform = use_platform(); + let mut allow_resizing = use_signal(|| false); + + use_memo(move || { + size.read(); + allow_resizing.set(true); + + // Only allow more resizing after the node layout has updated + }); + + use_drop(move || { + if *status.peek() == HandleStatus::Hovering { + platform.set_cursor(CursorIcon::default()); + } + }); + + let index = use_hook(move || { + registry.write().registry.push(ResizableItem::Handle); + registry.peek().registry.len() - 1 + }); + + let cursor = match registry.read().direction.as_str() { + "horizontal" => CursorIcon::ColResize, + _ => CursorIcon::RowResize, + }; + + let onmouseleave = move |_: MouseEvent| { + *status.write() = HandleStatus::Idle; + if !clicking() { + platform.set_cursor(CursorIcon::default()); + } + }; + + let onmouseenter = move |e: MouseEvent| { + e.stop_propagation(); + *status.write() = HandleStatus::Hovering; + platform.set_cursor(cursor); + }; + + let onmousemove = move |e: MouseEvent| { + if clicking() { + if !allow_resizing() { + return; + } + + let coordinates = e.get_screen_coordinates(); + let mut registry = registry.write(); + + let displacement_per: f32 = match registry.direction.as_str() { + "horizontal" => { + let container_width = container_size.read().area.width(); + let displacement = coordinates.x as f32 - size.read().area.min_x(); + 100. / container_width * displacement + } + _ => { + let container_height = container_size.read().area.height(); + let displacement = coordinates.y as f32 - size.read().area.min_y(); + 100. / container_height * displacement + } + }; + + let mut changed_panels = false; + + if displacement_per >= 0. { + // Resizing to the right + + let mut acc_per = 0.0; + + // Resize panels to the right + for next_item in &mut registry.registry[index..].iter_mut() { + if let Some(panel) = next_item.try_panel_mut() { + let old_size = panel.size; + let new_size = (panel.size - displacement_per).clamp(panel.min_size, 100.); + + if panel.size != new_size { + changed_panels = true + } + + panel.size = new_size; + acc_per -= new_size - old_size; + + if old_size > panel.min_size { + break; + } + } + } + + // Resize panels to the left + for prev_item in &mut registry.registry[0..index].iter_mut().rev() { + if let Some(panel) = prev_item.try_panel_mut() { + let new_size = (panel.size + acc_per).clamp(panel.min_size, 100.); + + if panel.size != new_size { + changed_panels = true + } + + panel.size = new_size; + break; + } + } + } else { + // Resizing to the left + + let mut acc_per = 0.0; + + // Resize panels to the left + for prev_item in &mut registry.registry[0..index].iter_mut().rev() { + if let Some(panel) = prev_item.try_panel_mut() { + let old_size = panel.size; + let new_size = (panel.size + displacement_per).clamp(panel.min_size, 100.); + + if panel.size != new_size { + changed_panels = true + } + + panel.size = new_size; + acc_per += new_size - old_size; + + if old_size > panel.min_size { + break; + } + } + } + + // Resize panels to the right + for next_item in &mut registry.registry[index..].iter_mut() { + if let Some(panel) = next_item.try_panel_mut() { + let new_size = (panel.size - acc_per).clamp(panel.min_size, 100.); + + if panel.size != new_size { + changed_panels = true + } + + panel.size = new_size; + break; + } + } + } + + if changed_panels { + allow_resizing.set(false); + } + } + }; + + let onmousedown = move |e: MouseEvent| { + e.stop_propagation(); + clicking.set(true); + }; + + let onclick = move |_: MouseEvent| { + if clicking() { + if *status.peek() != HandleStatus::Hovering { + platform.set_cursor(CursorIcon::default()); + } + clicking.set(false); + } + }; + + let (width, height) = match registry.read().direction.as_str() { + "horizontal" => ("4", "fill"), + _ => ("fill", "4"), + }; + + let background = match status() { + _ if clicking() => hover_background, + HandleStatus::Hovering => hover_background, + HandleStatus::Idle => background, + }; + + rsx!(rect { + reference: node_reference, + width: "{width}", + height: "{height}", + background: "{background}", + onmousedown, + onglobalclick: onclick, + onmouseenter, + onglobalmousemove: onmousemove, + onmouseleave, + }) +} + +#[cfg(test)] +mod test { + use freya::prelude::*; + use freya_testing::prelude::*; + + #[tokio::test] + pub async fn resizable_container() { + fn resizable_container_app() -> Element { + rsx!( + ResizableContainer { + ResizablePanel { + initial_size: 50., + label { + "Panel 0" + } + } + ResizableHandle { } + ResizablePanel { // Panel 1 + initial_size: 50., + ResizableContainer { + direction: "horizontal", + ResizablePanel { + initial_size: 33.33, + label { + "Panel 2" + } + } + ResizableHandle { } + ResizablePanel { + initial_size: 33.33, + label { + "Panel 3" + } + } + ResizableHandle { } + ResizablePanel { + initial_size: 33.33, + label { + "Panel 4" + } + } + } + } + } + ) + } + + let mut utils = launch_test(resizable_container_app); + utils.wait_for_update().await; + let root = utils.root(); + + let container = root.get(0); + let panel_0 = container.get(0); + let panel_1 = container.get(2); + let panel_2 = panel_1.get(0).get(0); + let panel_3 = panel_1.get(0).get(2); + let panel_4 = panel_1.get(0).get(4); + + assert_eq!(panel_0.layout().unwrap().area.height().round(), 248.0); + assert_eq!(panel_1.layout().unwrap().area.height().round(), 248.0); + assert_eq!(panel_2.layout().unwrap().area.width().round(), 164.0); + assert_eq!(panel_3.layout().unwrap().area.width().round(), 164.0); + assert_eq!(panel_4.layout().unwrap().area.width().round(), 164.0); + + // Vertical + utils.push_event(PlatformEvent::Mouse { + name: EventName::MouseDown, + cursor: (100.0, 250.0).into(), + button: Some(MouseButton::Left), + }); + utils.push_event(PlatformEvent::Mouse { + name: EventName::MouseMove, + cursor: (100.0, 200.0).into(), + button: Some(MouseButton::Left), + }); + utils.push_event(PlatformEvent::Mouse { + name: EventName::MouseUp, + cursor: (0.0, 0.0).into(), + button: Some(MouseButton::Left), + }); + utils.wait_for_update().await; + + assert_eq!(panel_0.layout().unwrap().area.height().round(), 200.0); // 250 - 50 + assert_eq!(panel_1.layout().unwrap().area.height().round(), 296.0); // 500 - 200 - 4 + + // Horizontal + utils.push_event(PlatformEvent::Mouse { + name: EventName::MouseDown, + cursor: (167.0, 300.0).into(), + button: Some(MouseButton::Left), + }); + utils.push_event(PlatformEvent::Mouse { + name: EventName::MouseMove, + cursor: (187.0, 300.0).into(), + button: Some(MouseButton::Left), + }); + utils.push_event(PlatformEvent::Mouse { + name: EventName::MouseUp, + cursor: (0.0, 0.0).into(), + button: Some(MouseButton::Left), + }); + utils.wait_for_update().await; + utils.wait_for_update().await; + utils.wait_for_update().await; + + assert_eq!(panel_2.layout().unwrap().area.width().round(), 187.0); // 167 + 20 + assert_eq!(panel_3.layout().unwrap().area.width().round(), 141.0); + } +} diff --git a/crates/devtools/src/lib.rs b/crates/devtools/src/lib.rs index f79b7b510..b2806cde2 100644 --- a/crates/devtools/src/lib.rs +++ b/crates/devtools/src/lib.rs @@ -77,24 +77,25 @@ fn AppWithDevtools(props: AppWithDevtoolsProps) -> Element { rsx!( NativeContainer { - rect { - width: "100%", - height: "100%", + ResizableContainer { direction: "horizontal", - rect { - overflow: "clip", - height: "100%", - width: "calc(100% - 350)", + ResizablePanel { + initial_size: 75., Root { }, } - rect { - background: "rgb(40, 40, 40)", - height: "100%", - width: "350", - ThemeProvider { - DevTools { - devtools_receiver, - hovered_node + ResizableHandle { } + ResizablePanel { + initial_size: 25., + min_size: 10., + rect { + background: "rgb(40, 40, 40)", + height: "fill", + width: "fill", + ThemeProvider { + DevTools { + devtools_receiver, + hovered_node + } } } } diff --git a/crates/hooks/src/theming/base.rs b/crates/hooks/src/theming/base.rs index d9ba77a18..b3663e7c4 100644 --- a/crates/hooks/src/theming/base.rs +++ b/crates/hooks/src/theming/base.rs @@ -259,4 +259,8 @@ pub(crate) const BASE_THEME: Theme = Theme { width: cow_borrowed!("auto"), height: cow_borrowed!("auto"), }, + resizable_handle: ResizableHandleTheme { + background: cow_borrowed!("key(secondary_surface)"), + hover_background: cow_borrowed!("key(surface)"), + }, }; diff --git a/crates/hooks/src/theming/mod.rs b/crates/hooks/src/theming/mod.rs index f06c02ae8..e2e463150 100644 --- a/crates/hooks/src/theming/mod.rs +++ b/crates/hooks/src/theming/mod.rs @@ -528,6 +528,15 @@ define_theme! { } } +define_theme! { + %[component] + pub ResizableHandle { + %[cows] + background: str, + hover_background: str, + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct ColorsSheet { pub primary: Cow<'static, str>, @@ -614,6 +623,7 @@ pub struct Theme { pub popup: PopupTheme, pub tab: TabTheme, pub bottom_tab: BottomTabTheme, + pub resizable_handle: ResizableHandleTheme, } impl Default for Theme { diff --git a/examples/resizable_container.rs b/examples/resizable_container.rs new file mode 100644 index 000000000..9d4506d25 --- /dev/null +++ b/examples/resizable_container.rs @@ -0,0 +1,122 @@ +#![cfg_attr( + all(not(debug_assertions), target_os = "windows"), + windows_subsystem = "windows" +)] + +use freya::prelude::*; + +fn main() { + launch_with_props(app, "Resizable Container", (1000.0, 550.0)); +} + +fn app() -> Element { + rsx!( + ResizableContainer { + ResizablePanel { + initial_size: 50., + rect { + width: "fill", + height: "fill", + main_align: "center", + cross_align: "center", + label { + "Panel 1" + } + } + } + ResizableHandle { } + ResizablePanel { // Panel 1 + initial_size: 50., + ResizableContainer { + direction: "horizontal", + ResizablePanel { + initial_size: 35., + rect { + width: "fill", + height: "fill", + main_align: "center", + cross_align: "center", + corner_radius: "6", + color: "white", + background: + "linear-gradient(250deg, orange 15%, rgb(255, 0, 0) 50%, rgb(255, 192, 203) 80%)", + label { + "Panel 1" + } + } + } + ResizableHandle { } + ResizablePanel { + initial_size: 20., + min_size: 20., + rect { + width: "fill", + height: "fill", + main_align: "center", + cross_align: "center", + corner_radius: "6", + color: "white", + background: + "linear-gradient(250deg, orange 15%, rgb(255, 0, 0) 50%, rgb(255, 192, 203) 80%)", + label { + "Panel 2" + } + } + } + ResizableHandle { } + ResizablePanel { + initial_size: 20., + rect { + width: "fill", + height: "fill", + main_align: "center", + cross_align: "center", + corner_radius: "6", + color: "white", + background: + "linear-gradient(250deg, orange 15%, rgb(255, 0, 0) 50%, rgb(255, 192, 203) 80%)", + label { + "Panel 3" + } + } + } + ResizableHandle { } + ResizablePanel { + initial_size: 15., + min_size: 10., + rect { + width: "fill", + height: "fill", + main_align: "center", + cross_align: "center", + corner_radius: "6", + color: "white", + background: + "linear-gradient(250deg, orange 15%, rgb(255, 0, 0) 50%, rgb(255, 192, 203) 80%)", + label { + "Panel 4" + } + } + } + ResizableHandle { } + ResizablePanel { + initial_size: 10., + rect { + width: "fill", + height: "fill", + main_align: "center", + cross_align: "center", + corner_radius: "6", + color: "white", + background: + "linear-gradient(250deg, orange 15%, rgb(255, 0, 0) 50%, rgb(255, 192, 203) 80%)", + label { + "Panel 5" + } + } + } + } + } + } + ) +}