Fix terminal box alignment in carousel demo YAML files

- Add proper padding to account for emoji display width (2 columns)
- Ensure all box content lines are exactly 100 characters wide
- Update fix-box-alignment.py to calculate display width correctly
- Apply fixes to all 4 carousel demo YMLs

This ensures the terminal box borders align properly in generated GIFs.
This commit is contained in:
Vijay Janapa Reddi
2025-11-17 00:03:44 -05:00
parent 8c51a72ae5
commit 35998a25aa
5 changed files with 144 additions and 113 deletions

View File

@@ -357,21 +357,21 @@ records:
- delay: 600
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Python 3.11.9\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Python 3.11.9 \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ NumPy 1.26.4\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ NumPy 1.26.4 \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Jupyter Lab 4.0.9\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Jupyter Lab 4.0.9 \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ All dependencies installed\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ All dependencies installed \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m🎉 Ready to build ML systems!\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m 🎉 Ready to build ML systems! \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 2000

View File

@@ -103,25 +103,25 @@ records:
- delay: 600
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m📓 Opening module in Jupyter Lab...\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m📓 Opening module in Jupyter Lab... \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32mBuild the foundation:\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m Build the foundation: \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m • Implement Tensor class \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m • Implement Tensor class \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m • Array operations (add, mul, reshape) \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m • Array operations (add, mul, reshape) \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m • Broadcasting & indexing \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m • Broadcasting & indexing \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36mTest inline, iterate fast 🚀\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m Test inline, iterate fast 🚀 \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 800
@@ -141,11 +141,11 @@ records:
- delay: 400
content: "\e[1;36m┌─────────────────────────────────────────────────────────┐\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m💡 Tip:\e[0m Code → Run tests → See results instantly \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m💡 Tip: Code → Run tests → See results instantly \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m💡 NBGrader:\e[0m Automated feedback as you code \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m💡 NBGrader: Automated feedback as you code \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m💡 When done:\e[0m tito module complete 01 \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m💡 When done: tito module complete 01 \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m└─────────────────────────────────────────────────────────┘\e[0m\r\n"
- delay: 2000

View File

@@ -109,11 +109,11 @@ records:
- delay: 600
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m🔍 Step 1/3: Running tests...\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m🔍 Step 1/3: Running tests... \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 800
@@ -151,11 +151,11 @@ records:
- delay: 400
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m📦 Step 2/3: Exporting to tinytorch/...\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m📦 Step 2/3: Exporting to tinytorch/... \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 600
@@ -169,11 +169,11 @@ records:
- delay: 400
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m💾 Step 3/3: Tracking completion...\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m💾 Step 3/3: Tracking completion... \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 400
@@ -185,25 +185,25 @@ records:
- delay: 600
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32mYour code is now part of TinyTorch!\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m Your code is now part of TinyTorch! \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33mTry it:\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33mTry it: \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;37mpython\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;37mpython \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;37m>>> from tinytorch import Tensor\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;37m>>> from tinytorch import Tensor \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;37m>>> t = Tensor([1, 2, 3])\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;37m>>> t = Tensor([1, 2, 3]) \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33mNext:\e[0m tito module start 02 \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33mNext: tito module start 02 \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 2000

View File

@@ -105,27 +105,27 @@ records:
- delay: 600
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m🔍 Checking prerequisites...\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m🔍 Checking prerequisites... \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Module 01: Tensor\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Module 01: Tensor \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Module 02: Activations\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Module 02: Activations \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Module 03: Layers\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Module 03: Layers \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Module 04: Losses\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Module 04: Losses \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Module 05: Autograd\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Module 05: Autograd \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Module 06: Optimizers\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Module 06: Optimizers \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Module 07: Training\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Module 07: Training \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 800
@@ -133,15 +133,15 @@ records:
- delay: 600
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m📊 Dataset:\e[0m MNIST (60k train, 10k test) \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m📊 Dataset: MNIST (60k train, 10k test) \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m🏗 Model:\e[0m 784 → 128 → 64 → 10 \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m🏗 Model: 784 → 128 → 64 → 10 \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m⚙ Using:\e[0m YOUR TinyTorch implementation \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m⚙ Using: YOUR TinyTorch implementation \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 800
@@ -181,13 +181,13 @@ records:
- delay: 600
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Test Accuracy: 96.3%\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Test Accuracy: 96.3% \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m✅ Threshold Met: >95% (1986 baseline)\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m ✅ Threshold Met: >95% (1986 baseline) \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 800
@@ -195,37 +195,37 @@ records:
- delay: 600
content: "\e[1;36m╭──────────────────────────────────────────────────────────────────────────────────────────────────╮\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33m🎉 Milestone 03: MLP (1986) COMPLETE!\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33m🎉 Milestone 03: MLP (1986) COMPLETE! \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m You've recreated Rumelhart's breakthrough using \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m You've recreated Rumelhart's breakthrough using \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m YOUR OWN implementation of: \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m YOUR OWN implementation of: \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m • Tensor operations \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m • Tensor operations \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m • Activation functions \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m • Activation functions \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m • Neural network layers \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m • Neural network layers \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m • Backpropagation \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m • Backpropagation \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m • Gradient descent optimization \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m • Gradient descent optimization \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;32m💡 You didn't import it. You BUILT it.\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m 💡 You didn't import it. You BUILT it. \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;33mNext milestone:\e[0m tito milestone run 04 \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;33mNext milestone: tito milestone run 04 \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;90m(CNN Revolution - 1998)\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;90m(CNN Revolution - 1998) \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
content: "\e[1;36m│\e[0m \e[1;36m│\e[0m\r\n"
- delay: 100
content: "\e[1;36m╰──────────────────────────────────────────────────────────────────────────────────────────────────╯\e[0m\r\n"
- delay: 2000

105
site/_static/demos/fix-box-alignment.py Normal file → Executable file
View File

@@ -4,74 +4,105 @@ Fix box-drawing alignment in Terminalizer YAML files.
This script ensures all box lines have consistent width by:
1. Finding all box-drawing content lines
2. Calculating the correct width based on terminal columns
2. Calculating the correct width based on terminal columns (100)
3. Padding text to fit within the box
"""
import re
import yaml
from pathlib import Path
# Terminal width from configs
COLS = 100
def fix_box_line(content, cols=COLS):
"""Fix a single box-drawing line to have correct width."""
# Extract ANSI codes and actual text
ansi_pattern = r'\x1b\[[0-9;]+m'
def get_display_width(text):
"""
Calculate display width accounting for emoji and special characters.
Emojis typically take 2 display columns.
"""
# Remove ANSI escape codes
text = re.sub(r'\\e\[[0-9;]+m', '', text)
# Box top/bottom patterns
if '' in content and '' in content:
# Top line: ╭─...─╮
return f"\\e[1;36m╭{'' * (cols - 2)}\\e[0m\\r\\n"
width = 0
for char in text:
# Emoji and other wide characters
if ord(char) > 0x1F300: # Approximate emoji range
width += 2
else:
width += 1
return width
if '' in content and '' in content:
# Bottom line: ╰─...─╯
return f"\\e[1;36m╰{'' * (cols - 2)}\\e[0m\\r\\n"
def fix_box_content_line(content):
"""Fix a box content line to be exactly 100 characters wide."""
# This is a line like: │ ✅ Python 3.11.9 │
if '' in content:
# Side line with content: │ text... │
# Strip ANSI codes to measure actual content
text_only = re.sub(ansi_pattern, '', content.replace('\\e', '\x1b'))
text_only = text_only.replace('\\r\\n', '').replace('', '')
# Calculate padding needed
content_width = len(text_only)
total_padding = cols - 2 - content_width # -2 for the │ on each side
if total_padding < 0:
# Content too wide, truncate
text_only = text_only[:cols - 5] + '...'
total_padding = 0
# Keep original ANSI-formatted content but adjust spacing
# This is a simplified version - you may need to preserve exact ANSI codes
if '' not in content:
return content
return content
# Extract the content between the │ characters
# Pattern: \e[color]│\e[reset] content \e[color]│\e[reset]
# Remove escape sequences to get clean content
clean = content.replace('\\e[1;36m', '').replace('\\e[0m', '').replace('\\e[1;32m', '')
clean = clean.replace('\\r\\n', '')
if not clean.startswith('') or not clean.endswith(''):
return content
# Get the inner content
inner = clean[1:-1]
# Calculate how much padding we need
# Total width should be 100: │ (1) + content (98) + │ (1)
target_inner_width = 98
current_width = get_display_width(inner)
if current_width > target_inner_width:
# Content is too wide, we need to truncate
# This shouldn't happen with our content, but handle it
print(f"Warning: Content too wide ({current_width} > {target_inner_width}): {inner[:50]}...")
return content
# Add padding spaces to the right
padding_needed = target_inner_width - current_width
padded_inner = inner + (' ' * padding_needed)
# Reconstruct with ANSI codes
result = f"\\e[1;36m│\\e[0m{padded_inner}\\e[1;36m│\\e[0m\\r\\n"
return result
def process_yaml_file(filepath):
"""Process a single YAML file to fix box alignment."""
print(f"Processing {filepath.name}...")
with open(filepath, 'r') as f:
lines = f.readlines()
content = f.read()
# Find all content lines with box characters
lines = content.split('\n')
modified = False
for i, line in enumerate(lines):
if 'content:' in line and any(char in line for char in ['', '', '', '', '']):
# This line contains box-drawing characters
if 'content:' in line and '' in line:
# Extract the content string
match = re.search(r'content: "(.*)"', line)
if match:
original = match.group(1)
fixed = fix_box_line(original)
# Skip top and bottom lines (they're already correct)
if '' in original or '' in original:
continue
fixed = fix_box_content_line(original)
if fixed != original:
lines[i] = line.replace(original, fixed)
modified = True
print(f" Fixed line {i}: {original[:50]}...")
if modified:
with open(filepath, 'w') as f:
f.writelines(lines)
f.write('\n'.join(lines))
print(f" ✅ Fixed {filepath.name}")
else:
print(f" No changes needed for {filepath.name}")
@@ -81,12 +112,12 @@ def main():
demos_dir = Path(__file__).parent
yaml_files = list(demos_dir.glob('[0-9][0-9]-*.yml'))
print(f"Found {len(yaml_files)} YAML files to process\\n")
print(f"Found {len(yaml_files)} YAML files to process\n")
for yaml_file in sorted(yaml_files):
process_yaml_file(yaml_file)
print("\\n✨ Done!")
print("\n✨ Done!")
if __name__ == '__main__':
main()