From: Ian Jackson Date: Sun, 6 Sep 2020 10:53:50 +0000 (+0100) Subject: html X-Git-Tag: otter-0.2.0~998 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=6ace87dcc729f5af39c886532f9bd7abe017c5af;p=otter.git html --- diff --git a/src/api.rs b/src/api.rs index 75e8f0ef..5809498a 100644 --- a/src/api.rs +++ b/src/api.rs @@ -149,9 +149,9 @@ impl ApiPieceOp for ApiPieceGrab { let update = PieceUpdateOp::Modify(()); let logent = LogEntry { - html : format!("{} grasped {}", + html : Html(format!("{} grasped {}", &htmlescape::encode_minimal(&pl.nick), - pc.describe_html(&lens.log_pri(piece, pc))), + pc.describe_html(&lens.log_pri(piece, pc)).0)), }; (update, vec![logent]) @@ -181,9 +181,9 @@ impl ApiPieceOp for ApiPieceUngrab { let update = PieceUpdateOp::Modify(()); let logent = LogEntry { - html : format!("{} released {}", + html : Html(format!("{} released {}", &htmlescape::encode_minimal(&pl.nick), - pc.describe_html(&lens.log_pri(piece, pc))), + pc.describe_html(&lens.log_pri(piece, pc)).0)), }; (update, vec![logent]) diff --git a/src/cmdlistener.rs b/src/cmdlistener.rs index ee17ef23..2ae738cf 100644 --- a/src/cmdlistener.rs +++ b/src/cmdlistener.rs @@ -134,7 +134,8 @@ fn execute_game_insn(cs: &CommandStream, ig.gs.table_size = size; (U{ pcs: vec![], log: vec![ LogEntry { - html: format!("The table was resized to {}x{}", size[0], size[1]), + html: Html(format!("The table was resized to {}x{}", + size[0], size[1])), }], raw: Some(vec![ PreparedUpdateEntry::SetTableSize(size) ]) }, Fine) @@ -145,8 +146,8 @@ fn execute_game_insn(cs: &CommandStream, Err(ME::AlreadyExists)?; } let logentry = LogEntry { - html: format!("The facilitator added a player: {}", - htmlescape::encode_minimal(&pl.nick)), + html: Html(format!("The facilitator added a player: {}", + htmlescape::encode_minimal(&pl.nick))), }; let (player, logentry) = ig.player_new(pl, logentry)?; (U{ pcs: vec![], @@ -168,8 +169,8 @@ fn execute_game_insn(cs: &CommandStream, let old_state = ig.player_remove(player)?; (U{ pcs: vec![], log: old_state.iter().map(|pl| LogEntry { - html: format!("The facilitator removed a player: {}", - htmlescape::encode_minimal(&pl.nick)), + html: Html(format!("The facilitator removed a player: {}", + htmlescape::encode_minimal(&pl.nick))), }).collect(), raw: None}, Fine) @@ -222,8 +223,8 @@ fn execute_game_insn(cs: &CommandStream, p.p.delete_hook(&p, gs); (U{ pcs: vec![(piece, PieceUpdateOp::Delete())], log: vec![ LogEntry { - html: format!("A piece {} was removed from the game", - desc_html), + html: Html(format!("A piece {} was removed from the game", + desc_html.0)), }], raw: None }, Fine) @@ -260,7 +261,8 @@ fn execute_game_insn(cs: &CommandStream, (U{ pcs: updates, log: vec![ LogEntry { - html: format!("The facilitaror added {} pieces", count), + html: Html(format!("The facilitaror added {} pieces", + count)), }], raw: None }, Fine) @@ -365,7 +367,7 @@ impl UpdateHandler { if bulk.logs { buf.log_updates(vec![LogEntry { - html: "The facilitator (re)configured the game".to_owned(), + html: Html::lit("The facilitator (re)configured the game") }]); } diff --git a/src/commands.rs b/src/commands.rs index 902d3aab..143dbe40 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -61,7 +61,7 @@ pub struct MgmtGamePieceInfo { pub piece: PieceId, pub pos: Pos, pub face: FaceId, - pub desc_html: String, + pub desc_html: Html, } #[derive(Debug,Copy,Clone,Serialize,Deserialize)] diff --git a/src/gamestate.rs b/src/gamestate.rs index 1b3b0cbe..c93fa041 100644 --- a/src/gamestate.rs +++ b/src/gamestate.rs @@ -22,6 +22,10 @@ visible_slotmap_key!{ VisiblePieceId('.') } #[serde(try_from="f64")] pub struct ZCoord(pub f64); +#[derive(Clone,Debug,Serialize,Deserialize)] +#[serde(transparent)] +pub struct Html (pub String); + pub const DEFAULT_TABLE_SIZE : Pos = [ 400, 200 ]; // ---------- general data types ---------- @@ -65,7 +69,7 @@ pub struct PlayerState { #[derive(Debug,Serialize,Deserialize)] pub struct LogEntry { - pub html : String, + pub html : Html, } // ---------- piece trait, and rendering ---------- @@ -77,18 +81,18 @@ type SE = SVGProcessingError; #[typetag::serde] pub trait Piece : Send + Debug { // #[throws] doesn't work here for some reason - fn svg_piece(&self, f: &mut String, pri: &PieceRenderInstructions) -> IR; + fn svg_piece(&self, f: &mut Html, pri: &PieceRenderInstructions) -> IR; #[throws(IE)] - fn surround_path(&self, pri : &PieceRenderInstructions) -> String; + fn surround_path(&self, pri : &PieceRenderInstructions) -> Html; - fn svg_x_defs(&self, f: &mut String, pri : &PieceRenderInstructions) -> IR; + fn svg_x_defs(&self, f: &mut Html, pri : &PieceRenderInstructions) -> IR; #[throws(IE)] fn thresh_dragraise(&self, pri : &PieceRenderInstructions) -> Option; - fn describe_html(&self, face : Option) -> String; + fn describe_html(&self, face : Option) -> Html; fn delete_hook(&self, _p: &PieceState, _gs: &mut GameState) -> ExecuteGameChangeUpdates { @@ -170,26 +174,30 @@ impl ClampTable for Pos { } } +impl Html { + pub fn lit(s: &str) -> Self { Html(s.to_owned()) } +} + // ---------- game state - rendering etc. ---------- impl PieceState { #[throws(IE)] - pub fn make_defs(&self, pri : &PieceRenderInstructions) -> String { + pub fn make_defs(&self, pri : &PieceRenderInstructions) -> Html { let pr = self; - let mut defs = String::new(); + let mut defs = Html(String::new()); let dragraise = match pr.p.thresh_dragraise(pri)? { Some(n) if n < 0 => throw!(SE::NegativeDragraise), Some(n) => n, None => -1, }; - write!(defs, + write!(&mut defs.0, r##""##, pri.id, dragraise)?; pr.p.svg_piece(&mut defs, &pri)?; - write!(defs, r##""##)?; - write!(defs, + write!(&mut defs.0, r##""##)?; + write!(&mut defs.0, r##""##, - pri.id, pr.p.surround_path(&pri)?)?; + pri.id, pr.p.surround_path(&pri)?.0)?; pr.p.svg_x_defs(&mut defs, &pri)?; defs } @@ -206,7 +214,7 @@ impl PieceState { } } - pub fn describe_html(&self, pri : &PieceRenderInstructions) -> String { + pub fn describe_html(&self, pri : &PieceRenderInstructions) -> Html { self.p.describe_html(Some(pri.face)) } } diff --git a/src/imports.rs b/src/imports.rs index 18b3d3a3..fb2aca42 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -95,4 +95,4 @@ pub type AE = anyhow::Error; pub type OE = OnlineError; pub type SvgData = Vec; -pub type Colour = String; +pub type Colour = Html; diff --git a/src/pieces.rs b/src/pieces.rs index 092397ff..8203a38b 100644 --- a/src/pieces.rs +++ b/src/pieces.rs @@ -7,9 +7,9 @@ type ColourMap = IndexVec; #[derive(Debug,Serialize,Deserialize)] // todo: this serialisation is rather large struct SimpleShape { - desc : String, - path : String, - scaled_path : String, + desc : Html, + path : Html, + scaled_path : Html, approx_dia : Coord, colours : ColourMap, } @@ -36,7 +36,7 @@ type IE = InternalError; type SE = SVGProcessingError; #[throws(SE)] -pub fn svg_rescale_path(input: &str, scale: f64) -> String { +pub fn svg_rescale_path(input: &Html, scale: f64) -> Html { type BM = u64; type BI = u32; #[derive(Debug,Copy,Clone)] @@ -61,7 +61,7 @@ pub fn svg_rescale_path(input: &str, scale: f64) -> String { let mut map = ALWAYS_MAP; let mut first = iter::once(()); - for w in input.split_ascii_whitespace() { + for w in input.0.split_ascii_whitespace() { if first.next().is_none() { write!(&mut out, " ")?; } match w { "L" | "l" | "M" | "m" | @@ -80,20 +80,20 @@ pub fn svg_rescale_path(input: &str, scale: f64) -> String { write!(&mut out, "{}", w)?; } - trace!("rescaled by {}: {} as {}",scale,&input,&out); - out + trace!("rescaled by {}: {:?} as {:?}",scale,input,&out); + Html(out) } #[typetag::serde] impl Piece for SimpleShape { #[throws(IE)] - fn svg_piece(&self, f: &mut String, pri: &PieceRenderInstructions) { - write!(f, r##""##, - self.colours[pri.face], - &self.path)?; + fn svg_piece(&self, f: &mut Html, pri: &PieceRenderInstructions) { + write!(&mut f.0, r##""##, + self.colours[pri.face].0, + &self.path.0)?; } #[throws(IE)] - fn surround_path(&self, _pri : &PieceRenderInstructions) -> String { + fn surround_path(&self, _pri : &PieceRenderInstructions) -> Html { self.scaled_path.clone() } #[throws(IE)] @@ -102,19 +102,19 @@ impl Piece for SimpleShape { Some(self.approx_dia / 2) } #[throws(IE)] - fn svg_x_defs(&self, _f: &mut String, _pri : &PieceRenderInstructions) { + fn svg_x_defs(&self, _f: &mut Html, _pri : &PieceRenderInstructions) { } - fn describe_html(&self, face : Option) -> String { - if let Some(face) = face { - format!("a {} {}", self.colours[face], self.desc) + fn describe_html(&self, face : Option) -> Html { + Html(if let Some(face) = face { + format!("a {} {}", self.colours[face].0, self.desc.0) } else { - format!("a {}", self.desc) - } + format!("a {}", self.desc.0) + }) } } impl SimpleShape { - fn new_from_path(desc: String, path: String, approx_dia: Coord, + fn new_from_path(desc: Html, path: Html, approx_dia: Coord, faces: &IndexVec) -> Result,SpecError> { let scaled_path = svg_rescale_path(&path, SELECT_SCALE)?; @@ -141,12 +141,13 @@ fn simple_resolve_spec_face(faces: &IndexSlice, impl PieceSpec for piece_specs::Disc { #[throws(SpecError)] fn load(&self) -> Box { - let unit_path = + let unit_path = Html::lit( "M 0 1 a 1 1 0 1 0 0 -2 \ - a 1 1 0 1 0 0 2 z"; + a 1 1 0 1 0 0 2 z" + ); let scale = (self.diam as f64) * 0.5; let path = svg_rescale_path(&unit_path, scale)?; - SimpleShape::new_from_path("circle".to_owned(), path, self.diam, + SimpleShape::new_from_path(Html::lit("circle"), path, self.diam, &self.faces)? } #[throws(SpecError)] @@ -164,9 +165,9 @@ impl PieceSpec for piece_specs::Square { [x, y] => (x,y), _ => throw!(SpecError::ImproperSizeSpec), }; - let path = format!("M {} {} h {} v {} h {} z", - -(x as f64)*0.5, -(y as f64)*0.5, x, y, -x); - SimpleShape::new_from_path("square".to_owned(), path, (x+y+1)/2, + let path = Html(format!("M {} {} h {} v {} h {} z", + -(x as f64)*0.5, -(y as f64)*0.5, x, y, -x)); + SimpleShape::new_from_path(Html::lit("square"), path, (x+y+1)/2, &self.faces)? } #[throws(SpecError)] diff --git a/src/session.rs b/src/session.rs index 26a486b5..5b66144f 100644 --- a/src/session.rs +++ b/src/session.rs @@ -9,7 +9,7 @@ struct SessionRenderContext { gen : Generation, table_size : Pos, uses : Vec, - defs : Vec<(VisiblePieceId,String)>, + defs : Vec<(VisiblePieceId,Html)>, nick : String, load : String, log : Vec<(Generation,Arc)>, diff --git a/src/spec.rs b/src/spec.rs index d8a72ced..4034146d 100644 --- a/src/spec.rs +++ b/src/spec.rs @@ -163,7 +163,7 @@ pub mod implementation { if !RE.is_match(s) { throw!(SpecError::UnsupportedColourSpec); } - spec.0.clone() + Html(spec.0.clone()) } } } diff --git a/src/updates.rs b/src/updates.rs index 9f736ed1..8fbadf27 100644 --- a/src/updates.rs +++ b/src/updates.rs @@ -51,7 +51,7 @@ pub enum PreparedUpdateEntry { #[derive(Debug,Clone,Serialize)] pub struct PreparedPieceState { pub pos : Pos, - pub svg : String, + pub svg : Html, pub held : Option, pub z : ZCoord, pub zg : Generation, @@ -126,10 +126,10 @@ impl PreparedUpdateEntry { match self { Piece { ref op, .. } => { 50 + - op.new_state().map(|x| x.svg.len()).unwrap_or(0) + op.new_state().map(|x| x.svg.0.len()).unwrap_or(0) }, Log(logent) => { - logent.html.as_bytes().len() * 3 + logent.html.0.as_bytes().len() * 3 }, SetTableSize(_) | Error(_,_) => { diff --git a/templates/session.tera b/templates/session.tera index ad3d5bcc..90c136d8 100644 --- a/templates/session.tera +++ b/templates/session.tera @@ -4,7 +4,7 @@ data-gen="{{gen}}" data-load="{{ load | escape }}" > -

Hi {{nick}}!

+

Hi {{nick | escape}}!


 

nothing