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.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
|
@ -41,7 +35,8 @@ dependencies = [
|
|||
"cosmic-text",
|
||||
"jotdown",
|
||||
"log",
|
||||
"range-map",
|
||||
"rangemap",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -158,15 +153,6 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.79"
|
||||
|
@ -185,20 +171,14 @@ dependencies = [
|
|||
"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]]
|
||||
name = "rangemap"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f60fcc7d6849342eff22c4350c8b9a989ee8ceabc4b481253e8946b9fe83d684"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "read-fonts"
|
||||
|
|
|
@ -9,4 +9,9 @@ edition = "2021"
|
|||
cosmic-text = "0.11.2"
|
||||
jotdown = { git = "https://git.nations.lol/fnmain/jotdown" }
|
||||
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 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};
|
||||
|
||||
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>>> {
|
||||
djot: T,
|
||||
|
@ -18,13 +26,15 @@ struct JotdownIntoBuffer<'a, 'b, T: Iterator<Item = Event<'a>>> {
|
|||
indent: &'b mut Vec<Indent>,
|
||||
image_url: Option<Cow<'a, str>>,
|
||||
link_start: usize,
|
||||
urls: Vec<(range_map::Range<usize>, &'a str)>,
|
||||
urls: Vec<(std::ops::Range<usize>, Cow<'a, str>)>,
|
||||
location: usize,
|
||||
added: bool,
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Copy)]
|
||||
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
|
||||
pub struct Indent {
|
||||
#[cfg_attr(feature = "serde", serde(with = "ListKindOption"))]
|
||||
pub modifier: Option<ListKind>,
|
||||
pub indent: f32,
|
||||
}
|
||||
|
@ -115,7 +125,7 @@ impl<'a, 'b, T: Iterator<Item = Event<'a>>> Iterator for JotdownIntoBuffer<'a, '
|
|||
}
|
||||
Container::Link(Cow::Borrowed(url), _) => {
|
||||
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));
|
||||
}
|
||||
_ => {}
|
||||
|
@ -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 indent: Indent,
|
||||
pub buffer: Vec<(&'a str, Attrs<'static>)>,
|
||||
pub buffer: Vec<RichText>,
|
||||
#[cfg_attr(feature = "serde", serde(with = "MetricsSerde"))]
|
||||
pub metrics: Metrics,
|
||||
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> {
|
||||
|
@ -154,7 +172,7 @@ impl<'a> JotdownItem<'a> {
|
|||
);
|
||||
buffer.set_rich_text(
|
||||
font_system,
|
||||
self.buffer.iter().cloned(),
|
||||
self.buffer.iter().map(|r| (r.0.as_str(), r.1.as_attrs())),
|
||||
Attrs::new().family(Family::SansSerif),
|
||||
Shaping::Advanced,
|
||||
);
|
||||
|
@ -182,7 +200,9 @@ impl<'a, T: Iterator<Item = Event<'a>>> Iterator for JotdownBufferIter<'a, T> {
|
|||
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 urls = jot.urls;
|
||||
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() {
|
||||
None
|
||||
} else {
|
||||
RangeMap::try_from_iter(urls.into_iter()).ok()
|
||||
let mut map = RangeMap::new();
|
||||
map.extend(urls.into_iter());
|
||||
Some(map)
|
||||
},
|
||||
buffer,
|
||||
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