-
Notifications
You must be signed in to change notification settings - Fork 55
feat(dom): multi-width unicode character support #121
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| [package] | ||
| name = "minimal" | ||
| version = "0.1.0" | ||
| edition = "2021" | ||
| publish = false | ||
|
|
||
| [dependencies] | ||
| ratzilla = { path = "../../" } | ||
| examples-shared = { path = "../shared" } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| <!doctype html> | ||
| <html lang="en"> | ||
|
|
||
| <head> | ||
| <meta charset="UTF-8" /> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" /> | ||
| <link rel="preload" as="style" crossorigin href="https://fontsapi.zeoseven.com/442/main/result.css" | ||
| onload="this.rel='stylesheet'" onerror="this.href='https://fontsapi-storage.zeoseven.com/442/main/result.css'" /> | ||
| <noscript> | ||
| <link rel="stylesheet" href="https://fontsapi.zeoseven.com/442/main/result.css" /> | ||
| </noscript> | ||
| <title>Ratzilla</title> | ||
| <style> | ||
| body { | ||
| margin: 0; | ||
| width: 100%; | ||
| height: 100vh; | ||
| display: flex; | ||
| flex-direction: column; | ||
| justify-content: center; | ||
| align-items: center; | ||
| align-content: center; | ||
| background-color: #121212; | ||
| } | ||
|
|
||
| pre { | ||
| font-family: "Maple Mono NF CN", monospace; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| font-size: 15px; | ||
| margin: 0px; | ||
| } | ||
| </style> | ||
| </head> | ||
|
|
||
| <body></body> | ||
|
|
||
| </html> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| use std::io; | ||
|
|
||
| use ratzilla::ratatui::{ | ||
| layout::Alignment, | ||
| style::Color, | ||
| widgets::{Block, Paragraph}, | ||
| }; | ||
|
|
||
| use ratzilla::WebRenderer; | ||
|
|
||
| use examples_shared::backend::{BackendType, MultiBackendBuilder}; | ||
|
|
||
| fn main() -> io::Result<()> { | ||
| let terminal = MultiBackendBuilder::with_fallback(BackendType::Dom).build_terminal()?; | ||
|
|
||
| terminal.draw_web(move |f| { | ||
| f.render_widget( | ||
| Paragraph::new( | ||
| [ | ||
| "Hello, world!", | ||
| "你好,世界!", | ||
| "世界、こんにちは。", | ||
| // "헬로우 월드!", | ||
| // "👨💻👋🌐", | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why are the emoji disabled?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah, ofc "As a result, misalignment may occur when displaying Korean text or emojis." - what about enforcing the width as |
||
| ] | ||
| .join("\n"), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. neat and compact :) |
||
| ) | ||
| .alignment(Alignment::Center) | ||
| .block( | ||
| Block::bordered() | ||
| .title("Ratzilla") | ||
| .title_alignment(Alignment::Center) | ||
| .border_style(Color::Yellow), | ||
| ), | ||
| f.area(), | ||
| ); | ||
| }); | ||
|
|
||
| Ok(()) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ use ratatui::{ | |
| layout::{Position, Size}, | ||
| prelude::Backend, | ||
| }; | ||
| use unicode_width::UnicodeWidthStr; | ||
| use web_sys::{ | ||
| wasm_bindgen::{prelude::Closure, JsCast}, | ||
| window, Document, Element, Window, | ||
|
|
@@ -148,27 +149,30 @@ impl DomBackend { | |
| fn prerender(&mut self) -> Result<(), Error> { | ||
| for line in self.buffer.iter() { | ||
| let mut line_cells: Vec<Element> = Vec::new(); | ||
| let mut hyperlink: Vec<Cell> = Vec::new(); | ||
| let mut hyperlink: Vec<(Cell, bool)> = Vec::new(); | ||
| let mut skip = 0; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. shouldn't are there any symbols extending more than double-width - if we stick to terminals? |
||
| for (i, cell) in line.iter().enumerate() { | ||
| let overwritten = skip > 0; | ||
| skip = std::cmp::max(skip, cell.symbol().width()).saturating_sub(1); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would it make sense to cache the width of all encountered symbols? |
||
| if cell.modifier.contains(HYPERLINK_MODIFIER) { | ||
| hyperlink.push(cell.clone()); | ||
| hyperlink.push((cell.clone(), overwritten)); | ||
| // If the next cell is not part of the hyperlink, close it | ||
| if !line | ||
| .get(i + 1) | ||
| .map(|c| c.modifier.contains(HYPERLINK_MODIFIER)) | ||
| .unwrap_or(false) | ||
| { | ||
| let anchor = create_anchor(&self.document, &hyperlink)?; | ||
| for link_cell in &hyperlink { | ||
| let span = create_span(&self.document, link_cell)?; | ||
| for (link_cell, overwritten) in &hyperlink { | ||
| let span = create_span(&self.document, link_cell, *overwritten)?; | ||
| self.cells.push(span.clone()); | ||
| anchor.append_child(&span)?; | ||
| } | ||
| line_cells.push(anchor); | ||
| hyperlink.clear(); | ||
| } | ||
| } else { | ||
| let span = create_span(&self.document, cell)?; | ||
| let span = create_span(&self.document, cell, overwritten)?; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe it would be clearer to have the old create_span() as-is and add a |
||
| self.cells.push(span.clone()); | ||
| line_cells.push(span); | ||
| } | ||
|
|
@@ -192,14 +196,22 @@ impl DomBackend { | |
| /// accordingly. | ||
| fn update_grid(&mut self) -> Result<(), Error> { | ||
| for (y, line) in self.buffer.iter().enumerate() { | ||
| let mut skip = 0; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same comment applies here about |
||
| for (x, cell) in line.iter().enumerate() { | ||
| let overwritten = skip > 0; | ||
| skip = std::cmp::max(skip, cell.symbol().width()).saturating_sub(1); | ||
| if cell.modifier.contains(HYPERLINK_MODIFIER) { | ||
| continue; | ||
| } | ||
| if cell != &self.prev_buffer[y][x] { | ||
| let elem = self.cells[y * self.buffer[0].len() + x].clone(); | ||
| elem.set_inner_html(cell.symbol()); | ||
| elem.set_attribute("style", &get_cell_style_as_css(cell))?; | ||
| if overwritten { | ||
| // If the cell is overwritten, hide it | ||
| elem.set_attribute("style", "display: none;")?; | ||
| } else { | ||
| elem.set_attribute("style", &get_cell_style_as_css(cell))?; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's a 0.2.1 release of unicode-width