Add serde support
This commit is contained in:
parent
7f245acf66
commit
b3339bc4c7
4 changed files with 237 additions and 35 deletions
30
Cargo.lock
generated
30
Cargo.lock
generated
|
@ -2,12 +2,6 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.5.0"
|
version = "2.5.0"
|
||||||
|
@ -41,7 +35,8 @@ dependencies = [
|
||||||
"cosmic-text",
|
"cosmic-text",
|
||||||
"jotdown",
|
"jotdown",
|
||||||
"log",
|
"log",
|
||||||
"range-map",
|
"rangemap",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -158,15 +153,6 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num-traits"
|
|
||||||
version = "0.2.18"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.79"
|
version = "1.0.79"
|
||||||
|
@ -185,20 +171,14 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "range-map"
|
|
||||||
version = "0.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "12a5a2d6c7039059af621472a4389be1215a816df61aa4d531cfe85264aee95f"
|
|
||||||
dependencies = [
|
|
||||||
"num-traits",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rangemap"
|
name = "rangemap"
|
||||||
version = "1.5.1"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684"
|
checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "read-fonts"
|
name = "read-fonts"
|
||||||
|
|
|
@ -9,4 +9,9 @@ edition = "2021"
|
||||||
cosmic-text = "0.11.2"
|
cosmic-text = "0.11.2"
|
||||||
jotdown = { git = "https://git.nations.lol/fnmain/jotdown" }
|
jotdown = { git = "https://git.nations.lol/fnmain/jotdown" }
|
||||||
log = "0.4.21"
|
log = "0.4.21"
|
||||||
range-map = "0.2.0"
|
serde = { version = "1.0.197", features = ["derive"], optional = true }
|
||||||
|
rangemap = "1.5.1"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["serde"]
|
||||||
|
serde = ["dep:serde", "rangemap/serde1"]
|
||||||
|
|
40
src/lib.rs
40
src/lib.rs
|
@ -1,10 +1,18 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use cosmic_text::{Attrs, Buffer, Color, Family, FontSystem, Metrics, Shaping, Style, Weight};
|
use cosmic_text::{
|
||||||
|
Attrs, AttrsOwned, Buffer, Color, Family, FontSystem, Metrics, Shaping, Style, Weight,
|
||||||
|
};
|
||||||
use jotdown::{Container, Event, ListKind};
|
use jotdown::{Container, Event, ListKind};
|
||||||
|
|
||||||
pub use jotdown;
|
pub use jotdown;
|
||||||
use range_map::RangeMap;
|
use rangemap::RangeMap;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
mod serde_suck;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
pub use serde_suck::*;
|
||||||
|
|
||||||
pub struct JotdownBufferIter<'a, T: Iterator<Item = Event<'a>>> {
|
pub struct JotdownBufferIter<'a, T: Iterator<Item = Event<'a>>> {
|
||||||
djot: T,
|
djot: T,
|
||||||
|
@ -18,13 +26,15 @@ struct JotdownIntoBuffer<'a, 'b, T: Iterator<Item = Event<'a>>> {
|
||||||
indent: &'b mut Vec<Indent>,
|
indent: &'b mut Vec<Indent>,
|
||||||
image_url: Option<Cow<'a, str>>,
|
image_url: Option<Cow<'a, str>>,
|
||||||
link_start: usize,
|
link_start: usize,
|
||||||
urls: Vec<(range_map::Range<usize>, &'a str)>,
|
urls: Vec<(std::ops::Range<usize>, Cow<'a, str>)>,
|
||||||
location: usize,
|
location: usize,
|
||||||
added: bool,
|
added: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||||
pub struct Indent {
|
pub struct Indent {
|
||||||
|
#[cfg_attr(feature = "serde", serde(with = "ListKindOption"))]
|
||||||
pub modifier: Option<ListKind>,
|
pub modifier: Option<ListKind>,
|
||||||
pub indent: f32,
|
pub indent: f32,
|
||||||
}
|
}
|
||||||
|
@ -115,7 +125,7 @@ impl<'a, 'b, T: Iterator<Item = Event<'a>>> Iterator for JotdownIntoBuffer<'a, '
|
||||||
}
|
}
|
||||||
Container::Link(Cow::Borrowed(url), _) => {
|
Container::Link(Cow::Borrowed(url), _) => {
|
||||||
self.urls
|
self.urls
|
||||||
.push((range_map::Range::new(self.link_start, self.location), url));
|
.push((self.link_start..self.location, Cow::Borrowed(url)));
|
||||||
self.attrs = self.attrs.color(Color::rgb(255, 255, 255));
|
self.attrs = self.attrs.color(Color::rgb(255, 255, 255));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -130,12 +140,20 @@ impl<'a, 'b, T: Iterator<Item = Event<'a>>> Iterator for JotdownIntoBuffer<'a, '
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||||
|
pub struct RichText(
|
||||||
|
String,
|
||||||
|
#[cfg_attr(feature = "serde", serde(with = "AttrsSerde"))] AttrsOwned,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||||
pub struct JotdownItem<'a> {
|
pub struct JotdownItem<'a> {
|
||||||
pub indent: Indent,
|
pub indent: Indent,
|
||||||
pub buffer: Vec<(&'a str, Attrs<'static>)>,
|
pub buffer: Vec<RichText>,
|
||||||
|
#[cfg_attr(feature = "serde", serde(with = "MetricsSerde"))]
|
||||||
pub metrics: Metrics,
|
pub metrics: Metrics,
|
||||||
pub image_url: Option<Cow<'a, str>>,
|
pub image_url: Option<Cow<'a, str>>,
|
||||||
pub url_map: Option<RangeMap<usize, &'a str>>,
|
pub url_map: Option<RangeMap<usize, Cow<'a, str>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> JotdownItem<'a> {
|
impl<'a> JotdownItem<'a> {
|
||||||
|
@ -154,7 +172,7 @@ impl<'a> JotdownItem<'a> {
|
||||||
);
|
);
|
||||||
buffer.set_rich_text(
|
buffer.set_rich_text(
|
||||||
font_system,
|
font_system,
|
||||||
self.buffer.iter().cloned(),
|
self.buffer.iter().map(|r| (r.0.as_str(), r.1.as_attrs())),
|
||||||
Attrs::new().family(Family::SansSerif),
|
Attrs::new().family(Family::SansSerif),
|
||||||
Shaping::Advanced,
|
Shaping::Advanced,
|
||||||
);
|
);
|
||||||
|
@ -182,7 +200,9 @@ impl<'a, T: Iterator<Item = Event<'a>>> Iterator for JotdownBufferIter<'a, T> {
|
||||||
urls: Vec::new(),
|
urls: Vec::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let buffer: Vec<(&str, Attrs<'static>)> = (&mut jot).collect();
|
let buffer = (&mut jot)
|
||||||
|
.map(|r| RichText(r.0.to_owned(), AttrsOwned::new(r.1)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
let image_url = jot.image_url;
|
let image_url = jot.image_url;
|
||||||
let urls = jot.urls;
|
let urls = jot.urls;
|
||||||
let added = jot.added;
|
let added = jot.added;
|
||||||
|
@ -196,7 +216,9 @@ impl<'a, T: Iterator<Item = Event<'a>>> Iterator for JotdownBufferIter<'a, T> {
|
||||||
url_map: if urls.is_empty() {
|
url_map: if urls.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
RangeMap::try_from_iter(urls.into_iter()).ok()
|
let mut map = RangeMap::new();
|
||||||
|
map.extend(urls.into_iter());
|
||||||
|
Some(map)
|
||||||
},
|
},
|
||||||
buffer,
|
buffer,
|
||||||
image_url,
|
image_url,
|
||||||
|
|
195
src/serde_suck.rs
Normal file
195
src/serde_suck.rs
Normal file
|
@ -0,0 +1,195 @@
|
||||||
|
use cosmic_text::{
|
||||||
|
Align, Attrs, AttrsOwned, CacheKeyFlags, Color, FamilyOwned, Metrics, Stretch, Style, Weight,
|
||||||
|
};
|
||||||
|
|
||||||
|
use jotdown::{ListKind, OrderedListNumbering, OrderedListStyle};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "Option<ListKind>")]
|
||||||
|
pub enum ListKindOption {
|
||||||
|
Some(#[serde(with = "ListKindSerde")] ListKind),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "jotdown::ListKind")]
|
||||||
|
pub enum ListKindSerde {
|
||||||
|
Unordered,
|
||||||
|
Ordered {
|
||||||
|
numbering: OrderedListNumbering,
|
||||||
|
style: OrderedListStyle,
|
||||||
|
start: u64,
|
||||||
|
},
|
||||||
|
Task,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "jotdown::OrderedListNumbering")]
|
||||||
|
pub enum OrderedListNumberingSerde {
|
||||||
|
Decimal,
|
||||||
|
AlphaLower,
|
||||||
|
AlphaUpper,
|
||||||
|
RomanLower,
|
||||||
|
RomanUpper,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "jotdown::OrderedListStyle")]
|
||||||
|
pub enum OrderedListStyleSerde {
|
||||||
|
Period,
|
||||||
|
Paren,
|
||||||
|
ParenParen,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "Metrics")]
|
||||||
|
pub struct MetricsSerde {
|
||||||
|
pub font_size: f32,
|
||||||
|
pub line_height: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "FamilyOwned")]
|
||||||
|
pub enum FamilySerde {
|
||||||
|
Name(String),
|
||||||
|
Serif,
|
||||||
|
SansSerif,
|
||||||
|
Cursive,
|
||||||
|
Fantasy,
|
||||||
|
Monospace,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "Stretch")]
|
||||||
|
pub enum StretchSerde {
|
||||||
|
UltraCondensed,
|
||||||
|
ExtraCondensed,
|
||||||
|
Condensed,
|
||||||
|
SemiCondensed,
|
||||||
|
Normal,
|
||||||
|
SemiExpanded,
|
||||||
|
Expanded,
|
||||||
|
ExtraExpanded,
|
||||||
|
UltraExpanded,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "Style")]
|
||||||
|
pub enum StyleSerde {
|
||||||
|
Normal,
|
||||||
|
Italic,
|
||||||
|
Oblique,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "Weight")]
|
||||||
|
pub struct WeightSerde(pub u16);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "Color")]
|
||||||
|
pub struct ColorSerde(pub u32);
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "Option<Color>")]
|
||||||
|
pub enum ColorOpt {
|
||||||
|
Some(#[serde(with = "ColorSerde")] Color),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
mod cache_key_flags {
|
||||||
|
use cosmic_text::CacheKeyFlags;
|
||||||
|
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||||
|
|
||||||
|
pub fn serialize<S>(_: &CacheKeyFlags, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
().serialize(serializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<'de, D>(deserializer: D) -> Result<CacheKeyFlags, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let _: () = <()>::deserialize(deserializer)?;
|
||||||
|
Ok(CacheKeyFlags::empty())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "AttrsOwned")]
|
||||||
|
pub struct AttrsSerde {
|
||||||
|
#[serde(with = "ColorOpt")]
|
||||||
|
pub color_opt: Option<Color>,
|
||||||
|
#[serde(with = "FamilySerde")]
|
||||||
|
pub family_owned: FamilyOwned,
|
||||||
|
#[serde(with = "StretchSerde")]
|
||||||
|
pub stretch: Stretch,
|
||||||
|
#[serde(with = "StyleSerde")]
|
||||||
|
pub style: Style,
|
||||||
|
#[serde(with = "WeightSerde")]
|
||||||
|
pub weight: Weight,
|
||||||
|
pub metadata: usize,
|
||||||
|
#[serde(with = "cache_key_flags")]
|
||||||
|
pub cache_key_flags: CacheKeyFlags,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<Attrs<'a>> for AttrsSerde {
|
||||||
|
fn from(value: Attrs<'a>) -> Self {
|
||||||
|
Self {
|
||||||
|
color_opt: value.color_opt,
|
||||||
|
family_owned: FamilyOwned::new(value.family),
|
||||||
|
stretch: value.stretch,
|
||||||
|
style: value.style,
|
||||||
|
weight: value.weight,
|
||||||
|
metadata: value.metadata,
|
||||||
|
cache_key_flags: value.cache_key_flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "Option<Align>")]
|
||||||
|
pub enum AlignSerde {
|
||||||
|
Some(#[serde(with = "AlignRef")] Align),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
#[serde(remote = "Align")]
|
||||||
|
pub enum AlignRef {
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Center,
|
||||||
|
Justified,
|
||||||
|
End,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AttrsSerde {
|
||||||
|
pub fn as_attrs(&self) -> Attrs<'_> {
|
||||||
|
Attrs {
|
||||||
|
color_opt: self.color_opt,
|
||||||
|
family: self.family_owned.as_family(),
|
||||||
|
stretch: self.stretch,
|
||||||
|
style: self.style,
|
||||||
|
weight: self.weight,
|
||||||
|
metadata: self.metadata,
|
||||||
|
cache_key_flags: CacheKeyFlags::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AttrsOwned> for AttrsSerde {
|
||||||
|
fn from(value: AttrsOwned) -> Self {
|
||||||
|
Self {
|
||||||
|
color_opt: value.color_opt,
|
||||||
|
family_owned: value.family_owned,
|
||||||
|
stretch: value.stretch,
|
||||||
|
style: value.style,
|
||||||
|
weight: value.weight,
|
||||||
|
metadata: value.metadata,
|
||||||
|
cache_key_flags: value.cache_key_flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue