diff --git a/src/components/Segment.js b/src/components/Segment.js
index 4602e9ef..4cf0bbe3 100644
--- a/src/components/Segment.js
+++ b/src/components/Segment.js
@@ -1,20 +1,36 @@
export default (props) => {
+ const codePoint = () => {
+ if (props.text.length == 1) {
+ const cp = props.text.codePointAt(0);
+
+ if ((cp >= 0x2580 && cp <= 0x2595) || cp == 0xe0b0 || cp == 0xe0b2) {
+ return cp;
+ }
+ }
+ };
+
+ const text = () => (codePoint() ? " " : props.text);
+
return (
- {props.text}
+ {text()}
);
};
-function className(attrs, extraClass) {
+function className(attrs, codePoint, extraClass) {
const fgClass = colorClass(attrs.get("fg"), attrs.get("bold"), "fg-");
const bgClass = colorClass(attrs.get("bg"), attrs.get("blink"), "bg-");
let cls = extraClass ?? "";
+ if (codePoint !== undefined) {
+ cls += ` cp-${codePoint.toString(16)}`;
+ }
+
if (fgClass) {
cls += " " + fgClass;
}
@@ -60,12 +76,13 @@ function colorClass(color, intense, prefix) {
}
}
-function style(attrs, offset, terminalCols) {
+function style(attrs, offset, textLen, charWidth, terminalCols) {
const fg = attrs.get("fg");
const bg = attrs.get("bg");
let style = {
left: `${(100 * offset) / terminalCols}%`,
+ width: `${textLen * charWidth + 0.01}ch`,
};
if (typeof fg === "string") {
diff --git a/src/components/Terminal.js b/src/components/Terminal.js
index a8928ca0..8de1a751 100644
--- a/src/components/Terminal.js
+++ b/src/components/Terminal.js
@@ -11,6 +11,7 @@ export default (props) => {
"font-size": `${(props.scale || 1.0) * 100}%`,
"font-family": props.fontFamily,
"line-height": `${lineHeight()}em`,
+ "--term-line-height": lineHeight(),
};
});
diff --git a/src/less/partials/_terminal.less b/src/less/partials/_terminal.less
index 7e22aa7d..18ffe9a4 100644
--- a/src/less/partials/_terminal.less
+++ b/src/less/partials/_terminal.less
@@ -33,6 +33,174 @@ pre.ap-terminal {
color: var(--bg);
background-color: var(--fg);
}
+
+ // upper half block
+ .cp-2580 {
+ border-top: calc(0.5em * var(--term-line-height)) solid var(--fg);
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // lower one eighth block
+ .cp-2581 {
+ border-bottom: calc(0.125em * var(--term-line-height)) solid var(--fg);
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // lower one quarter block
+ .cp-2582 {
+ border-bottom: calc(0.25em * var(--term-line-height)) solid var(--fg);
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // lower three eighths block
+ .cp-2583 {
+ border-bottom: calc(0.375em * var(--term-line-height)) solid var(--fg);
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // lower half block
+ .cp-2584 {
+ border-bottom: calc(0.5em * var(--term-line-height)) solid var(--fg);
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // lower five eighths block
+ .cp-2585 {
+ border-bottom: calc(0.625em * var(--term-line-height)) solid var(--fg);
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // lower three quarters block
+ .cp-2586 {
+ border-bottom: calc(0.75em * var(--term-line-height)) solid var(--fg);
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // lower seven eighths block
+ .cp-2587 {
+ border-bottom: calc(0.875em * var(--term-line-height)) solid var(--fg);
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // full block
+ .cp-2588 {
+ background-color: var(--fg);
+ width: 1.01ch;
+ }
+
+ // left seven eighths block
+ .cp-2589 {
+ border-left: 0.875ch solid var(--fg);
+ box-sizing: border-box;
+ width: 1ch;
+ }
+
+ // left three quarters block
+ .cp-258a {
+ border-left: 0.75ch solid var(--fg);
+ box-sizing: border-box;
+ width: 1ch;
+ }
+
+ // left five eighths block
+ .cp-258b {
+ border-left: 0.625ch solid var(--fg);
+ box-sizing: border-box;
+ width: 1ch;
+ }
+
+ // left half block
+ .cp-258c {
+ border-left: 0.5ch solid var(--fg);
+ box-sizing: border-box;
+ width: 1ch;
+ }
+
+ // left three eighths block
+ .cp-258d {
+ border-left: 0.375ch solid var(--fg);
+ box-sizing: border-box;
+ width: 1ch;
+ }
+
+ // left one quarter block
+ .cp-258e {
+ border-left: 0.25ch solid var(--fg);
+ box-sizing: border-box;
+ width: 1ch;
+ }
+
+ // left one eighth block
+ .cp-258f {
+ border-left: 0.125ch solid var(--fg);
+ box-sizing: border-box;
+ width: 1ch;
+ }
+
+ // right half block
+ .cp-2590 {
+ border-right: 0.5ch solid var(--fg);
+ box-sizing: border-box;
+ width: 1ch;
+ }
+
+ // light shade (░)
+ .cp-2591 {
+ background-color: color-mix(in srgb, var(--fg) 25%, var(--bg));
+ width: 1.01ch;
+ }
+
+ // medium shade (▒)
+ .cp-2592 {
+ background-color: color-mix(in srgb, var(--fg) 50%, var(--bg));
+ width: 1.01ch;
+ }
+
+ // dark shade (▓)
+ .cp-2593 {
+ background-color: color-mix(in srgb, var(--fg) 75%, var(--bg));
+ width: 1.01ch;
+ }
+
+ // upper one eighth block
+ .cp-2594 {
+ border-top: calc(0.125em * var(--term-line-height)) solid var(--fg);
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // right one eighth block
+ .cp-2595 {
+ border-right: 0.125ch solid var(--fg);
+ box-sizing: border-box;
+ width: 1ch;
+ }
+
+ // powerline right full triangle
+ .cp-e0b0 {
+ border-left: 1.0ch solid var(--fg);
+ border-top: calc(0.5em * var(--term-line-height)) solid transparent;
+ border-bottom: calc(0.5em * var(--term-line-height)) solid transparent;
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
+
+ // powerline left full triangle
+ .cp-e0b2 {
+ border-right: 1.0ch solid var(--fg);
+ border-top: calc(0.5em * var(--term-line-height)) solid transparent;
+ border-bottom: calc(0.5em * var(--term-line-height)) solid transparent;
+ box-sizing: border-box;
+ width: 1.01ch;
+ }
}
&.ap-cursor-on .ap-line .ap-cursor {
diff --git a/src/vt/Cargo.lock b/src/vt/Cargo.lock
index 0fae4154..c1c82f7d 100644
--- a/src/vt/Cargo.lock
+++ b/src/vt/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
[[package]]
name = "avt"
-version = "0.10.1"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75abd5104739a34dd6d3e3d4ab8a6d8811d8c8c25a1c2762ffbe0652ffdb8da3"
+checksum = "8f453ce6fa1e0820846a95d8b16eb09eeb96e138f31f336b03af5b3fcaa291cc"
dependencies = [
"rgb",
"serde",
diff --git a/src/vt/Cargo.toml b/src/vt/Cargo.toml
index 53d9af5b..7e21685c 100644
--- a/src/vt/Cargo.toml
+++ b/src/vt/Cargo.toml
@@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"]
# default = ["console_error_panic_hook"]
[dependencies]
-avt = "0.10.1"
+avt = "0.10.2"
getrandom = { version = "0.2", features = ["js"] }
rand = "^0.8"
serde-wasm-bindgen = "0.4.5"
diff --git a/src/vt/src/lib.rs b/src/vt/src/lib.rs
index 21a60516..5151b448 100644
--- a/src/vt/src/lib.rs
+++ b/src/vt/src/lib.rs
@@ -4,7 +4,9 @@ use std::ops::RangeInclusive;
use wasm_bindgen::prelude::*;
const BOX_DRAWING_RANGE: RangeInclusive = '\u{2500}'..='\u{257f}';
+const BLOCK_ELEMENTS_RANGE: RangeInclusive = '\u{2580}'..='\u{2595}';
const BRAILLE_PATTERNS_RANGE: RangeInclusive = '\u{2800}'..='\u{28ff}';
+const POWERLINE_TRIANGLES_RANGE: RangeInclusive = '\u{e0b0}'..='\u{e0b3}';
#[wasm_bindgen]
pub struct VtWrapper {
@@ -45,7 +47,13 @@ impl VtWrapper {
let line: Vec<_> = self
.vt
.line(l)
- .group(|c| BOX_DRAWING_RANGE.contains(c) || BRAILLE_PATTERNS_RANGE.contains(c))
+ .group(|c, w| {
+ w > 1
+ || BOX_DRAWING_RANGE.contains(c)
+ || BRAILLE_PATTERNS_RANGE.contains(c)
+ || BLOCK_ELEMENTS_RANGE.contains(c)
+ || POWERLINE_TRIANGLES_RANGE.contains(c)
+ })
.collect();
serde_wasm_bindgen::to_value(&line).unwrap()