Skip to content

Commit

Permalink
feat: set default config for text style (#669)
Browse files Browse the repository at this point in the history
* feat: set default config for text style

* feat: add config_default_text_style method with optional style configuration

* chore: add changeset

---------

Co-authored-by: Zixuan Chen <remch183@outlook.com>
  • Loading branch information
YngNs and zxch3n authored Feb 27, 2025
1 parent 6cf06e5 commit aab07c6
Show file tree
Hide file tree
Showing 8 changed files with 96 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/shiny-eggs-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"loro-crdt": patch
---

feat: set default config for text style #669
2 changes: 1 addition & 1 deletion crates/loro-ffi/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl StyleConfigMap {

pub fn get(&self, key: &str) -> Option<StyleConfig> {
let m = self.0.read().unwrap();
m.get(&(key.into())).cloned()
m.get(&(key.into()))
}

pub fn default_rich_text_config() -> Self {
Expand Down
14 changes: 13 additions & 1 deletion crates/loro-ffi/src/doc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{
use loro::{
cursor::CannotFindRelativePosition, ChangeTravelError, CounterSpan, DocAnalysis,
FrontiersNotIncluded, IdSpan, JsonPathError, JsonSchema, Lamport, LoroDoc as InnerLoroDoc,
LoroEncodeError, LoroError, LoroResult, PeerID, Timestamp, VersionRange, ID,
LoroEncodeError, LoroError, LoroResult, PeerID, StyleConfig, Timestamp, VersionRange, ID,
};

use crate::{
Expand Down Expand Up @@ -112,6 +112,18 @@ impl LoroDoc {
self.doc.config_text_style(text_style.as_ref().to_loro())
}

/// Configures the default text style for the document.
///
/// This method sets the default text style configuration for the document when using LoroText.
/// If `None` is provided, the default style is reset.
///
/// # Parameters
///
/// - `text_style`: The style configuration to set as the default. `None` to reset.
pub fn config_default_text_style(&self, text_style: Option<StyleConfig>) {
self.doc.config_default_text_style(text_style);
}

/// Attach the document state to the latest known version.
///
/// > The document becomes detached during a `checkout` operation.
Expand Down
15 changes: 9 additions & 6 deletions crates/loro-internal/src/container/richtext/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,15 @@ use super::{ExpandType, TextStyleInfoFlag};

#[derive(Debug, Default, Clone)]
pub struct StyleConfigMap {
map: FxHashMap<InternalString, StyleConfig>,
pub(crate) map: FxHashMap<InternalString, StyleConfig>,
pub(crate) default_style: Option<StyleConfig>,
}

impl StyleConfigMap {
pub fn new() -> Self {
Self {
map: FxHashMap::default(),
default_style: None,
}
}

Expand All @@ -23,8 +25,8 @@ impl StyleConfigMap {
self.map.insert(key, value);
}

pub fn get(&self, key: &InternalString) -> Option<&StyleConfig> {
self.map.get(key)
pub fn get(&self, key: &InternalString) -> Option<StyleConfig> {
self.map.get(key).copied().or(self.default_style)
}

pub fn get_style_flag(&self, key: &InternalString) -> Option<TextStyleInfoFlag> {
Expand All @@ -36,20 +38,21 @@ impl StyleConfigMap {
}

fn _get_style_flag(&self, key: &InternalString, is_del: bool) -> Option<TextStyleInfoFlag> {
let f = |x: &StyleConfig| {
let f = |x: StyleConfig| {
TextStyleInfoFlag::new(if is_del { x.expand.reverse() } else { x.expand })
};
if let Some(index) = key.find(':') {
let key = key[..index].into();
self.map.get(&key).map(f)
self.map.get(&key).copied().or(self.default_style).map(f)
} else {
self.map.get(key).map(f)
self.map.get(key).copied().or(self.default_style).map(f)
}
}

pub fn default_rich_text_config() -> Self {
let mut map = Self {
map: FxHashMap::default(),
default_style: None,
};

map.map.insert(
Expand Down
12 changes: 10 additions & 2 deletions crates/loro-internal/src/loro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use tracing::{debug_span, info, info_span, instrument, warn};
use crate::{
arena::SharedArena,
change::Timestamp,
configure::{Configure, DefaultRandom, SecureRandomGenerator},
configure::{Configure, DefaultRandom, SecureRandomGenerator, StyleConfig},
container::{
idx::ContainerIdx, list::list_op::InnerListOp, richtext::config::StyleConfigMap,
IntoContainerId,
Expand Down Expand Up @@ -343,9 +343,17 @@ impl LoroDoc {

#[inline]
pub fn config_text_style(&self, text_style: StyleConfigMap) {
*self.config.text_style_config.try_write().unwrap() = text_style;
self.config.text_style_config.try_write().unwrap().map = text_style.map;
}

#[inline]
pub fn config_default_text_style(&self, text_style: Option<StyleConfig>) {
self.config
.text_style_config
.try_write()
.unwrap()
.default_style = text_style;
}
pub fn from_snapshot(bytes: &[u8]) -> LoroResult<Self> {
let doc = Self::new();
let ParsedHeaderAndBody { mode, body, .. } = parse_header_and_body(bytes, true)?;
Expand Down
23 changes: 23 additions & 0 deletions crates/loro-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ extern "C" {
pub type MapEntry;
#[wasm_bindgen(typescript_type = "{[key: string]: { expand: 'before'|'after'|'none'|'both' }}")]
pub type JsTextStyles;
#[wasm_bindgen(typescript_type = "{ expand: 'before'|'after'|'none'|'both' } | undefined")]
pub type JsTextStyle;
#[wasm_bindgen(typescript_type = "Delta<string>[]")]
pub type JsDelta;
#[wasm_bindgen(typescript_type = "-1 | 1 | 0 | undefined")]
Expand Down Expand Up @@ -502,6 +504,27 @@ impl LoroDoc {
Ok(())
}

/// Configures the default text style for the document.
///
/// This method sets the default text style configuration for the document when using LoroText.
/// If `None` is provided, the default style is reset.
#[wasm_bindgen(js_name = "configDefaultTextStyle")]
pub fn config_default_text_style(&self, style: JsTextStyle) -> JsResult<()> {
let mut style_config = StyleConfig::new();
if style.is_undefined() {
self.0.config_default_text_style(None);
} else {
let value = style.obj;
let expand = Reflect::get(&value, &"expand".into()).expect("`expand` not specified");
let expand_str = expand.as_string().unwrap();

style_config.expand = ExpandType::try_from_str(&expand_str)
.expect("`expand` must be one of `none`, `start`, `end`, `both`");

self.0.config_default_text_style(Some(style_config));
}
Ok(())
}
/// Create a loro document from the snapshot.
///
/// @see You can learn more [here](https://loro.dev/docs/tutorial/encoding).
Expand Down
23 changes: 23 additions & 0 deletions crates/loro-wasm/tests/basic.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1540,3 +1540,26 @@ it("call toDelta on detached text", () => {
const d = text.toDelta();
expect(d).toMatchSnapshot();
})

it("can allow default config for text style", () => {
{
const doc = new LoroDoc();
const text = doc.getText("text");
text.insert(0, "Hello");
expect(() => {
text.mark({ start: 0, end: 5 }, "size", true);
}).toThrow()
}
{
const doc = new LoroDoc();
doc.configDefaultTextStyle({ expand: "before" })
const text = doc.getText("text");
text.insert(0, "Hello");
text.mark({ start: 0, end: 5 }, "size", true);
}
{
const text = new LoroText();
text.insert(0, "Hello");
text.mark({ start: 0, end: 5 }, "size", true);
}
})
12 changes: 12 additions & 0 deletions crates/loro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,18 @@ impl LoroDoc {
self.doc.config_text_style(text_style)
}

/// Configures the default text style for the document.
///
/// This method sets the default text style configuration for the document when using LoroText.
/// If `None` is provided, the default style is reset.
///
/// # Parameters
///
/// - `text_style`: The style configuration to set as the default. `None` to reset.
pub fn config_default_text_style(&self, text_style: Option<StyleConfig>) {
self.doc.config_default_text_style(text_style);
}

/// Attach the document state to the latest known version.
///
/// > The document becomes detached during a `checkout` operation.
Expand Down

0 comments on commit aab07c6

Please sign in to comment.