improve wrap into tag, improving text styles
This commit is contained in:
parent
63302fef71
commit
9cc34f16bb
@ -60,6 +60,7 @@ features = [
|
|||||||
"FormData",
|
"FormData",
|
||||||
"FileReader",
|
"FileReader",
|
||||||
"FileReaderSync",
|
"FileReaderSync",
|
||||||
|
"DocumentFragment",
|
||||||
"Range",
|
"Range",
|
||||||
# events
|
# events
|
||||||
"EventTarget",
|
"EventTarget",
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use seed::prelude::*;
|
use seed::prelude::*;
|
||||||
use seed::*;
|
use seed::*;
|
||||||
use tracing::{debug, info};
|
|
||||||
|
|
||||||
use crate::components::styled_button::{ButtonVariant, StyledButton};
|
use crate::components::styled_button::{ButtonVariant, StyledButton};
|
||||||
use crate::components::styled_icon::{Icon, StyledIcon};
|
use crate::components::styled_icon::{Icon, StyledIcon};
|
||||||
@ -42,6 +41,31 @@ impl HeadingSize {
|
|||||||
H6 => "H6",
|
H6 => "H6",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_u32(&self) -> u32 {
|
||||||
|
match self {
|
||||||
|
HeadingSize::Normal => 0,
|
||||||
|
HeadingSize::H1 => 1,
|
||||||
|
HeadingSize::H2 => 2,
|
||||||
|
HeadingSize::H3 => 3,
|
||||||
|
HeadingSize::H4 => 4,
|
||||||
|
HeadingSize::H5 => 5,
|
||||||
|
HeadingSize::H6 => 6,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_u32(n: u32) -> Self {
|
||||||
|
match n {
|
||||||
|
0 => HeadingSize::Normal,
|
||||||
|
1 => HeadingSize::H1,
|
||||||
|
2 => HeadingSize::H2,
|
||||||
|
3 => HeadingSize::H3,
|
||||||
|
4 => HeadingSize::H4,
|
||||||
|
5 => HeadingSize::H5,
|
||||||
|
6 => HeadingSize::H6,
|
||||||
|
_ => HeadingSize::Normal,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -55,12 +79,7 @@ pub enum RteMsg {
|
|||||||
Bold,
|
Bold,
|
||||||
Italic,
|
Italic,
|
||||||
Underscore,
|
Underscore,
|
||||||
Undo,
|
|
||||||
Redo,
|
|
||||||
Strikethrough,
|
Strikethrough,
|
||||||
Copy,
|
|
||||||
Paste,
|
|
||||||
Cut,
|
|
||||||
JustifyFull,
|
JustifyFull,
|
||||||
JustifyCenter,
|
JustifyCenter,
|
||||||
JustifyLeft,
|
JustifyLeft,
|
||||||
@ -107,15 +126,10 @@ impl<'l> ExecCommand<'l> {
|
|||||||
impl RteMsg {
|
impl RteMsg {
|
||||||
pub fn to_command(&self) -> Option<ExecCommand> {
|
pub fn to_command(&self) -> Option<ExecCommand> {
|
||||||
match self {
|
match self {
|
||||||
RteMsg::Bold => Some(ExecCommand::new("bold")),
|
RteMsg::Bold => None,
|
||||||
RteMsg::Italic => Some(ExecCommand::new("italic")),
|
RteMsg::Italic => None,
|
||||||
RteMsg::Underscore => Some(ExecCommand::new("underline")),
|
RteMsg::Underscore => None,
|
||||||
RteMsg::Undo => Some(ExecCommand::new("undo")),
|
|
||||||
RteMsg::Redo => Some(ExecCommand::new("redo")),
|
|
||||||
RteMsg::Strikethrough => Some(ExecCommand::new("strikeThrough")),
|
RteMsg::Strikethrough => Some(ExecCommand::new("strikeThrough")),
|
||||||
RteMsg::Copy => Some(ExecCommand::new("copy")),
|
|
||||||
RteMsg::Paste => Some(ExecCommand::new("paste")),
|
|
||||||
RteMsg::Cut => Some(ExecCommand::new("cut")),
|
|
||||||
RteMsg::JustifyFull => Some(ExecCommand::new("justifyFull")),
|
RteMsg::JustifyFull => Some(ExecCommand::new("justifyFull")),
|
||||||
RteMsg::JustifyCenter => Some(ExecCommand::new("justifyCenter")),
|
RteMsg::JustifyCenter => Some(ExecCommand::new("justifyCenter")),
|
||||||
RteMsg::JustifyLeft => Some(ExecCommand::new("justifyLeft")),
|
RteMsg::JustifyLeft => Some(ExecCommand::new("justifyLeft")),
|
||||||
@ -127,17 +141,14 @@ impl RteMsg {
|
|||||||
| HeadingSize::H3
|
| HeadingSize::H3
|
||||||
| HeadingSize::H4
|
| HeadingSize::H4
|
||||||
| HeadingSize::H5
|
| HeadingSize::H5
|
||||||
| HeadingSize::H6 => {
|
| HeadingSize::H6 => None,
|
||||||
// Some(ExecCommand::new_with_param("heading", heading.as_str()))
|
HeadingSize::Normal => None,
|
||||||
None
|
|
||||||
}
|
|
||||||
HeadingSize::Normal => Some(ExecCommand::new_with_param("formatBlock", "div")),
|
|
||||||
},
|
},
|
||||||
RteMsg::InsertUnorderedList => Some(ExecCommand::new("insertUnorderedList")),
|
RteMsg::InsertUnorderedList => Some(ExecCommand::new("insertUnorderedList")),
|
||||||
RteMsg::InsertOrderedList => Some(ExecCommand::new("insertOrderedList")),
|
RteMsg::InsertOrderedList => Some(ExecCommand::new("insertOrderedList")),
|
||||||
RteMsg::RemoveFormat => Some(ExecCommand::new("removeFormat")),
|
RteMsg::RemoveFormat => None,
|
||||||
RteMsg::Subscript => Some(ExecCommand::new("subscript")),
|
RteMsg::Subscript => None,
|
||||||
RteMsg::Superscript => Some(ExecCommand::new("superscript")),
|
RteMsg::Superscript => None,
|
||||||
RteMsg::InsertTable { .. } => None,
|
RteMsg::InsertTable { .. } => None,
|
||||||
// code
|
// code
|
||||||
RteMsg::InsertCode(_) => None,
|
RteMsg::InsertCode(_) => None,
|
||||||
@ -284,12 +295,13 @@ impl StyledRteState {
|
|||||||
if self.restore_range().is_err() {
|
if self.restore_range().is_err() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.schedule_focus(orders);
|
|
||||||
}
|
}
|
||||||
_ => match m {
|
_ => match m {
|
||||||
RteMsg::InsertHeading(heading) => {
|
RteMsg::Subscript => wrap_into("SUB"),
|
||||||
wrap_into(heading.as_str());
|
RteMsg::Superscript => wrap_into("SUP"),
|
||||||
}
|
RteMsg::Bold => wrap_into("B"),
|
||||||
|
RteMsg::Underscore => wrap_into("U"),
|
||||||
|
RteMsg::InsertHeading(heading) => wrap_into(heading.as_str()),
|
||||||
// code
|
// code
|
||||||
RteMsg::InsertCode(b) => {
|
RteMsg::InsertCode(b) => {
|
||||||
if *b {
|
if *b {
|
||||||
@ -394,7 +406,7 @@ impl StyledRteState {
|
|||||||
let sel = sel
|
let sel = sel
|
||||||
.unwrap_or(None)
|
.unwrap_or(None)
|
||||||
.ok_or_else(|| "Restoring selection failed. Unable to obtain select".to_string())?;
|
.ok_or_else(|| "Restoring selection failed. Unable to obtain select".to_string())?;
|
||||||
sel.collapse_to_start();
|
sel.collapse_to_end().ok();
|
||||||
let r = self
|
let r = self
|
||||||
.range
|
.range
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@ -436,89 +448,6 @@ impl<'component> Default for StyledRte<'component> {
|
|||||||
|
|
||||||
impl<'outer> StyledRte<'outer> {
|
impl<'outer> StyledRte<'outer> {
|
||||||
pub fn render(self) -> Node<Msg> {
|
pub fn render(self) -> Node<Msg> {
|
||||||
/*{
|
|
||||||
let _brush_button = styled_rte_button(
|
|
||||||
"Brush",
|
|
||||||
Icon::Brush,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let _color_bucket_button = styled_rte_button(
|
|
||||||
"Color bucket",
|
|
||||||
Icon::ColorBucket,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let _color_picker_button = styled_rte_button(
|
|
||||||
"Color picker",
|
|
||||||
Icon::ColorPicker,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
let _link_broken_button = styled_rte_button(
|
|
||||||
"Link broken",
|
|
||||||
Icon::LinkBroken,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
let _pin_button = styled_rte_button(
|
|
||||||
"Pin",
|
|
||||||
Icon::Pin,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let _rotation_button = styled_rte_button(
|
|
||||||
"Rotation",
|
|
||||||
Icon::Rotation,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let _save_button = styled_rte_button(
|
|
||||||
"Save",
|
|
||||||
Icon::Save,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let _text_height_button = styled_rte_button(
|
|
||||||
"Text height",
|
|
||||||
Icon::TextHeight,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let _text_width_button = styled_rte_button(
|
|
||||||
"Text width",
|
|
||||||
Icon::TextWidth,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// let field_id = values.field_id.clone();
|
|
||||||
// let capture_change = ev(Ev::Input, |ev| {
|
|
||||||
// ev.stop_propagation();
|
|
||||||
// Some(Msg::StrInputChanged(field_id, "".to_string()))
|
|
||||||
// });
|
|
||||||
|
|
||||||
let id = self.identifier.unwrap_or_default().to_string();
|
let id = self.identifier.unwrap_or_default().to_string();
|
||||||
|
|
||||||
let click_handler = {
|
let click_handler = {
|
||||||
@ -543,18 +472,7 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
"justifyCenter" => RteMsg::JustifyCenter,
|
"justifyCenter" => RteMsg::JustifyCenter,
|
||||||
"justifyLeft" => RteMsg::JustifyLeft,
|
"justifyLeft" => RteMsg::JustifyLeft,
|
||||||
"justifyRight" => RteMsg::JustifyRight,
|
"justifyRight" => RteMsg::JustifyRight,
|
||||||
"undo" => RteMsg::Undo,
|
|
||||||
"redo" => RteMsg::Redo,
|
|
||||||
|
|
||||||
"removeFormat" => RteMsg::RemoveFormat,
|
|
||||||
"bold" => RteMsg::Bold,
|
|
||||||
"italic " => RteMsg::Italic,
|
|
||||||
"underscore" => RteMsg::Underscore,
|
|
||||||
"strikethrough" => RteMsg::Strikethrough,
|
|
||||||
"subscript" => RteMsg::Subscript,
|
|
||||||
"superscript" => RteMsg::Superscript,
|
|
||||||
|
|
||||||
// "font" => RteMsg::, // Some(RteMsg::Font),
|
|
||||||
"listingDots" => RteMsg::InsertUnorderedList,
|
"listingDots" => RteMsg::InsertUnorderedList,
|
||||||
"listingNumber" => RteMsg::InsertOrderedList,
|
"listingNumber" => RteMsg::InsertOrderedList,
|
||||||
"table" => RteMsg::TableSetVisibility(true),
|
"table" => RteMsg::TableSetVisibility(true),
|
||||||
@ -600,21 +518,12 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
C!["bar"],
|
C!["bar"],
|
||||||
Self::first_row(click_handler.clone()),
|
Self::first_row(click_handler.clone()),
|
||||||
self.second_row(click_handler, change_handler),
|
self.second_row(click_handler, change_handler),
|
||||||
/* brush_button,
|
|
||||||
* color_bucket_button,
|
|
||||||
* color_picker_button,
|
|
||||||
* link_broken_button,
|
|
||||||
* pin_button,
|
|
||||||
* save_button,
|
|
||||||
* text_height_button,
|
|
||||||
* text_width_button, */
|
|
||||||
],
|
],
|
||||||
div![
|
div![
|
||||||
C!["editorWrapper"],
|
C!["editorWrapper"],
|
||||||
div![
|
div![
|
||||||
C!["editor", self.field_id.to_str()],
|
C!["editor", self.field_id.to_str()],
|
||||||
attrs![At::ContentEditable => true],
|
attrs![At::ContentEditable => true],
|
||||||
// capture_change
|
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
@ -660,50 +569,10 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
Self::styled_rte_button("Redo", ButtonId::Redo, Icon::Redo, click_handler.clone());
|
Self::styled_rte_button("Redo", ButtonId::Redo, Icon::Redo, click_handler.clone());
|
||||||
let undo_button =
|
let undo_button =
|
||||||
Self::styled_rte_button("Undo", ButtonId::Undo, Icon::Undo, click_handler.clone());
|
Self::styled_rte_button("Undo", ButtonId::Undo, Icon::Undo, click_handler.clone());
|
||||||
/*let field_id = values.field_id.clone();
|
div![C!["group system"], undo_button, redo_button,]
|
||||||
let clip_board_button = styled_rte_button(
|
|
||||||
"Paste",
|
|
||||||
Icon::ClipBoard,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
Some(Msg::Rte(RteMsg::Paste, field_id))
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let field_id = values.field_id.clone();
|
|
||||||
let copy_button = styled_rte_button(
|
|
||||||
"Copy",
|
|
||||||
Icon::Copy,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
Some(Msg::Rte(RteMsg::Copy, field_id))
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let field_id = values.field_id.clone();
|
|
||||||
let cut_button = styled_rte_button(
|
|
||||||
"Cut",
|
|
||||||
Icon::Cut,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
Some(Msg::Rte(RteMsg::Cut, field_id))
|
|
||||||
}),
|
|
||||||
);*/
|
|
||||||
div![
|
|
||||||
C!["group system"],
|
|
||||||
// clip_board_button,
|
|
||||||
// copy_button,
|
|
||||||
// cut_button,
|
|
||||||
undo_button,
|
|
||||||
redo_button,
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let formatting = {
|
let formatting = {
|
||||||
let remove_formatting = Self::styled_rte_button(
|
|
||||||
"Remove format",
|
|
||||||
ButtonId::RemoveFormat,
|
|
||||||
Icon::EraserAlt,
|
|
||||||
click_handler.clone(),
|
|
||||||
);
|
|
||||||
let bold_button =
|
let bold_button =
|
||||||
Self::styled_rte_button("Bold", ButtonId::Bold, Icon::Bold, click_handler.clone());
|
Self::styled_rte_button("Bold", ButtonId::Bold, Icon::Bold, click_handler.clone());
|
||||||
let italic_button = Self::styled_rte_button(
|
let italic_button = Self::styled_rte_button(
|
||||||
@ -749,7 +618,6 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
strike_through_button,
|
strike_through_button,
|
||||||
subscript_button,
|
subscript_button,
|
||||||
superscript_button,
|
superscript_button,
|
||||||
remove_formatting,
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -761,45 +629,7 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
click_handler: EventHandler<Msg>,
|
click_handler: EventHandler<Msg>,
|
||||||
change_handler: EventHandler<Msg>,
|
change_handler: EventHandler<Msg>,
|
||||||
) -> Node<Msg> {
|
) -> Node<Msg> {
|
||||||
/*let align_group = {
|
|
||||||
let field_id = values.field_id.clone();
|
|
||||||
let align_center_button = styled_rte_button(
|
|
||||||
"Align Center",
|
|
||||||
Icon::AlignCenter,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let field_id = values.field_id.clone();
|
|
||||||
let align_left_button = styled_rte_button(
|
|
||||||
"Align Left",
|
|
||||||
Icon::AlignLeft,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
let field_id = values.field_id.clone();
|
|
||||||
let align_right_button = styled_rte_button(
|
|
||||||
"Align Right",
|
|
||||||
Icon::AlignRight,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
div![
|
|
||||||
C!["group align"],
|
|
||||||
align_center_button,
|
|
||||||
align_left_button,
|
|
||||||
align_right_button,
|
|
||||||
]
|
|
||||||
};*/
|
|
||||||
|
|
||||||
let font_group = {
|
let font_group = {
|
||||||
let _font_button =
|
|
||||||
Self::styled_rte_button("Font", ButtonId::Font, Icon::Font, click_handler.clone());
|
|
||||||
let options: Vec<Node<Msg>> = HeadingSize::all()
|
let options: Vec<Node<Msg>> = HeadingSize::all()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|h| {
|
.map(|h| {
|
||||||
@ -814,36 +644,30 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
.render();
|
.render();
|
||||||
span![C!["headingOption"], button]
|
option![
|
||||||
|
attrs!["value" => h.as_u32(), "title" => "Text styles"],
|
||||||
|
C!["headingOption"],
|
||||||
|
button
|
||||||
|
]
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
let heading_button = span![C!["headingList"], options];
|
|
||||||
|
|
||||||
/*let _field_id = values.field_id.clone();
|
let field_id = self.field_id.clone();
|
||||||
let _small_cap_button = styled_rte_button(
|
let on_change = ev("change", |ev| {
|
||||||
"Small Cap",
|
let target = ev.target().expect("is selected");
|
||||||
Icon::SmallCap,
|
let select = seed::to_select(&target);
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
let value: String = select.value();
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
let value = value.parse::<u32>().ok().unwrap_or_default();
|
||||||
}),
|
Msg::Rte(
|
||||||
);
|
field_id,
|
||||||
let _field_id = values.field_id.clone();
|
RteMsg::InsertHeading(HeadingSize::from_u32(value)),
|
||||||
let _all_caps_button = styled_rte_button(
|
)
|
||||||
"All caps",
|
});
|
||||||
Icon::AllCaps,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
let heading_button = select![C!["headingList"], options, on_change,];
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
div![C!["group font"], heading_button]
|
||||||
}),
|
|
||||||
);*/
|
|
||||||
div![
|
|
||||||
C!["group font"],
|
|
||||||
// font_button,
|
|
||||||
heading_button,
|
|
||||||
/* small_cap_button,
|
|
||||||
* all_caps_button */
|
|
||||||
]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let insert_group = {
|
let insert_group = {
|
||||||
@ -861,16 +685,6 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
Icon::ListingNumber,
|
Icon::ListingNumber,
|
||||||
click_handler.clone(),
|
click_handler.clone(),
|
||||||
);
|
);
|
||||||
/*let field_id = values.field_id.clone();
|
|
||||||
let sub_listing_button = styled_rte_button(
|
|
||||||
"Sub Listing",
|
|
||||||
Icon::SubListing,
|
|
||||||
mouse_ev(Ev::Click, move |ev| {
|
|
||||||
ev.prevent_default();
|
|
||||||
None as Option<Msg>
|
|
||||||
}),
|
|
||||||
);*/
|
|
||||||
|
|
||||||
let mut table_button = Self::styled_rte_button(
|
let mut table_button = Self::styled_rte_button(
|
||||||
"Table",
|
"Table",
|
||||||
ButtonId::Table,
|
ButtonId::Table,
|
||||||
@ -879,12 +693,6 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
);
|
);
|
||||||
table_button.add_child(table_tooltip);
|
table_button.add_child(table_tooltip);
|
||||||
|
|
||||||
let paragraph_button = Self::styled_rte_button(
|
|
||||||
"Paragraph",
|
|
||||||
ButtonId::Paragraph,
|
|
||||||
Icon::Paragraph,
|
|
||||||
click_handler.clone(),
|
|
||||||
);
|
|
||||||
let mut code_alt_button = Self::styled_rte_button(
|
let mut code_alt_button = Self::styled_rte_button(
|
||||||
"Insert code",
|
"Insert code",
|
||||||
ButtonId::CodeAlt,
|
ButtonId::CodeAlt,
|
||||||
@ -895,12 +703,10 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
|
|
||||||
div![
|
div![
|
||||||
C!["group insert"],
|
C!["group insert"],
|
||||||
paragraph_button,
|
|
||||||
table_button,
|
table_button,
|
||||||
code_alt_button,
|
code_alt_button,
|
||||||
listing_dots,
|
listing_dots,
|
||||||
listing_number,
|
listing_number,
|
||||||
// sub_listing_button,
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -919,7 +725,6 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
div![
|
div![
|
||||||
C!["row secondRow"],
|
C!["row secondRow"],
|
||||||
font_group,
|
font_group,
|
||||||
// align_group,
|
|
||||||
insert_group,
|
insert_group,
|
||||||
indent_outdent
|
indent_outdent
|
||||||
]
|
]
|
||||||
@ -1125,14 +930,75 @@ impl<'outer> StyledRte<'outer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_into(name: &str) -> Option<()> {
|
fn wrap_into(name: &str) {
|
||||||
|
try_wrap_into(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_wrap_into(name: &str) -> Option<()> {
|
||||||
let sel = document().get_selection().ok()??;
|
let sel = document().get_selection().ok()??;
|
||||||
let r = sel.get_range_at(0).ok()?;
|
let r = sel.get_range_at(0).ok()?;
|
||||||
|
|
||||||
let el: web_sys::Element = document().create_element(name).unwrap();
|
let start = r.start_container();
|
||||||
let node = el.dyn_ref::<web_sys::Node>().unwrap();
|
let end = r.end_container();
|
||||||
if let Err(e) = r.surround_contents(&node) {
|
|
||||||
error!("{}", e);
|
if let Some(node) = is_wrapped(start.clone().ok(), end.clone().ok(), name) {
|
||||||
|
let el = node.dyn_ref::<web_sys::HtmlElement>()?;
|
||||||
|
let parent = el.parent_element()?;
|
||||||
|
let children = el.child_nodes();
|
||||||
|
let mut len: u32 = children.length();
|
||||||
|
|
||||||
|
len = len.checked_sub(1)?;
|
||||||
|
let last = children.item(len)?;
|
||||||
|
parent.replace_child(&last, &node).ok();
|
||||||
|
r.set_end_after(&last).ok();
|
||||||
|
let mut prev = last;
|
||||||
|
while len > 0 {
|
||||||
|
len -= 1;
|
||||||
|
let current = children.item(len)?;
|
||||||
|
parent.replace_child(¤t, &prev).ok();
|
||||||
|
prev = current;
|
||||||
|
}
|
||||||
|
sel.collapse_to_end().ok()
|
||||||
|
} else {
|
||||||
|
let el: web_sys::Element = document().create_element(name).unwrap();
|
||||||
|
let node = el.dyn_ref::<web_sys::Node>().unwrap();
|
||||||
|
if let Err(e) = r.surround_contents(&node) {
|
||||||
|
error!("{}", e);
|
||||||
|
}
|
||||||
|
r.set_end_after(node).ok();
|
||||||
|
sel.collapse_to_end().ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_wrapped(
|
||||||
|
start: Option<web_sys::Node>,
|
||||||
|
end: Option<web_sys::Node>,
|
||||||
|
name: &str,
|
||||||
|
) -> Option<web_sys::Element> {
|
||||||
|
let start = start?;
|
||||||
|
let end: web_sys::Node = end?;
|
||||||
|
|
||||||
|
if start == end
|
||||||
|
&& start
|
||||||
|
.dyn_ref::<web_sys::HtmlElement>()
|
||||||
|
.filter(|x| x.tag_name() == name)
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
return Some(
|
||||||
|
start
|
||||||
|
.dyn_into::<web_sys::Element>()
|
||||||
|
.expect("All HTMLElement are by definition Element"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
let start = start.parent_element()?;
|
||||||
|
let start_parent = start.dyn_ref::<web_sys::HtmlElement>()?;
|
||||||
|
|
||||||
|
let end = end.parent_element()?;
|
||||||
|
let end_parent = end.dyn_ref::<web_sys::HtmlElement>()?;
|
||||||
|
|
||||||
|
if start_parent == end_parent && start_parent.tag_name().as_str() == name {
|
||||||
|
Some(start)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
sel.collapse(Some(node)).ok()
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user