> For the complete documentation index, see [llms.txt](https://overleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://overleaf-pro.ayaka.space/latex/vi/bai-viet-chuyen-sau/36-pandora-s-hbox-using-luatex-to-lift-the-lid-of-tex-boxes.md).

# \hbox của Pandora: Dùng LuaTeX để mở nắp các hộp TeX

## Giới thiệu

Hộp và glue là hai khái niệm then chốt đặt nền tảng cho mô hình và khả năng dàn trang của TeX. Kế thừa phần giới thiệu trong một bài trước, [Hộp và Glue: Giới thiệu ngắn gọn, nhưng trực quan, bằng LuaTeX](/latex/vi/bai-viet-chuyen-sau/11-boxes-and-glue-a-brief-but-visual-introduction-using-luatex.md), bài viết minh họa phong phú này xem xét hộp và glue chi tiết hơn. Chúng tôi cũng giới thiệu một [dự án Overleaf](https://www.overleaf.com/latex/examples/exploring-the-structure-of-tex-boxes-with-luatex/pwdrypmtdbgs) cho phép bạn khám phá cấu trúc nội tại sâu bên trong của các hộp TeX—cung cấp những hiểu biết sẽ giúp bạn thực sự hiểu cách chúng hoạt động. Việc tạo ra dự án Overleaf này đã được hỗ trợ rất nhiều bởi công trình của Patrick Gundlach, vì vậy chúng tôi xin gửi [lời cảm ơn tới ông](#credits-thanks-patrick).

## Vì sao chọn LuaTeX?

Trước hết, đáng để nhắc lại sự khác biệt giữa LuaTeX và LuaLaTeX:

* LuaTeX là tên của một bộ máy dàn trang dựa trên TeX có thể thực thi;
* LuaLaTeX chỉ việc sử dụng gói macro LaTeX với bộ máy LuaTeX.

Sự phân biệt này cực kỳ quan trọng vì, trong bài viết này, chúng tôi đang khai thác các khả năng tích hợp sẵn của chính bộ máy LuaTeX, chứ không chỉ tận dụng các tính năng/chức năng của các lệnh do gói macro LaTeX cung cấp.

Những độc giả chưa rõ sự khác biệt giữa một bộ máy TeX và gói macro LaTeX có thể muốn đọc một trong các bài đã đăng trước của chúng tôi, [Tên gọi là gì: Hướng dẫn về nhiều biến thể của TeX](/latex/vi/bai-viet-chuyen-sau/55-what-s-in-a-name-a-guide-to-the-many-flavours-of-tex.md), bài viết đó giải thích những khác biệt ấy khá chi tiết. Bài viết đó cũng bàn về “TeX” như một ngôn ngữ lập trình và rằng các bộ máy dàn trang dựa trên TeX (ví dụ, pdfTeX, XeTeX và LuaTeX) không chỉ khác nhau về các tính năng và chức năng của chúng, mà còn có những biến thể trong “hương vị” của ngôn ngữ TeX mà chúng hỗ trợ. Điều này đưa chúng ta đến với lựa chọn LuaTeX. Ngoài việc hỗ trợ một ngôn ngữ lập trình dựa trên TeX, LuaTeX còn nhúng sẵn ngôn ngữ kịch bản Lua bên trong nó—cung cấp quyền truy cập vào một ngôn ngữ lập trình truyền thống đơn giản nhưng cực kỳ mạnh mẽ. Thông qua Lua và các chức năng tích hợp sẵn của LuaTeX, bạn có thể khám phá và điều khiển các hoạt động dàn trang của LuaTeX theo những cách mà không bộ máy TeX nào khác cung cấp—và điều này bao gồm cả khả năng thăm dò các cấu trúc bên trong của các hộp TeX; vì vậy LuaTeX là lựa chọn lý tưởng (duy nhất) cho bài viết này và dự án Overleaf đi kèm.

### pdfTeX/XeTeX vs LuaTeX: bằng hình ảnh

Các *sơ đồ* được dùng để làm nổi bật một so sánh quan trọng giữa thiết kế của pdfTeX/XeTeX và LuaTeX. Cả pdfTeX và XeTeX dĩ nhiên đều cho phép người dùng viết mã TeX có thể ảnh hưởng đến hành vi dàn trang; tuy nhiên, các cấu trúc nội bộ sâu hơn nằm trong những bộ máy TeX đó, và dữ liệu mức thấp được tạo ra trong quá trình dàn trang, phần lớn không thể truy cập được bằng các lệnh và macro người dùng. Theo nghĩa đó, chúng là *tương đối* những hệ thống khép kín khi so với LuaTeX.

#### pdfTeX/XeTeX

![{{{alt}}}](/files/caf7e5a95f0c3d6de1ea865842a723f711b0fdfd)

#### LuaTeX

LuaTeX giới thiệu một lệnh nguyên thủy mới có tên là `\directlua{...}` thông qua đó bạn có thể viết mã không chỉ cho phép truy cập đầy đủ vào ngôn ngữ Lua mà còn cho phép bạn mở rộng khả năng của LuaTeX bằng cách viết các plug-in sử dụng các ngôn ngữ như C và C++. Trên Windows, các plug-in như vậy được gọi là *Thư viện liên kết động* (.DLL); trên Linux chúng được gọi là *Thư viện đối tượng chia sẻ* (.so). Tuy nhiên, sức mạnh thực sự của LuaTeX bắt nguồn từ một bộ lớn các hàm Lua tích hợp sẵn, cung cấp quyền truy cập vào các phần bên trong của LuaTeX—cho phép điều khiển và lập trình dàn trang dựa trên TeX ở mức cực kỳ tinh vi. Một tập hợp các hàm như vậy được gọi là API (Giao diện lập trình ứng dụng), và chính thông qua API của LuaTeX mà bạn dùng các chương trình Lua để giao tiếp với bộ máy dàn trang dựa trên TeX và các cấu trúc dữ liệu của nó.

![{{{alt}}}](/files/e4a2b972b576d97eab7e1dcf59a1c720c6dc8bb7)

Với `\directlua{...}` lệnh của LuaTeX, chẳng hạn, bạn có thể truy cập các cấu trúc dữ liệu nội bộ mức thấp của TeX bị che giấu trong các bộ máy TeX khác. Ngoài ra, bạn có thể dùng các script Lua để thực hiện đủ loại phép tính lập trình, thao tác chuỗi, v.v. và chuyển kết quả trở lại cho TeX: khả năng gần như vô tận. Tuy nhiên, bài viết này không nhằm là một trình bày chi tiết hay một bài hướng dẫn về LuaTeX—dù rất muốn đưa ra các ví dụ thể hiện tính linh hoạt đáng kinh ngạc của bộ máy TeX mạnh mẽ phi thường này.

## Hộp và glue: Nhắc lại ngắn gọn

Như đã giới thiệu trong bài viết [Hộp và Glue: Giới thiệu ngắn gọn, nhưng trực quan, bằng LuaTeX](https://www.overleaf.com/blog/511-boxes-and-glue-a-brief-but-visual-introduction-using-luatex) hộp và glue là hai khái niệm then chốt đặt nền tảng cho khả năng dàn trang của TeX. Sơ đồ sau được đưa ra như một ghi nhớ rất ngắn về cách hoạt động của các loại hộp ngang và hộp dọc của TeX. Lưu ý: các hộp ngang dĩ nhiên có thể chứa văn bản được dàn trang bằng các ngôn ngữ viết từ phải sang trái, chẳng hạn như tiếng Ả Rập hoặc tiếng Do Thái, điều đó có nghĩa là hướng phát triển của hộp có thể ngược với hướng được minh họa cho hộp ngang trong sơ đồ dưới đây.

![{{{alt}}}](/files/f721430fff63a8e5a646a026d5f5fb32228c0069)

### Các nguyên thủy TeX để tạo hộp

Ngày nay, hầu hết mọi người soạn tài liệu TeX của mình bằng gói macro LaTeX, vốn được thiết kế để cung cấp các lệnh giúp tách người dùng khỏi phần lớn ngôn ngữ mức thấp của TeX—cái gọi là *các nguyên thủy*—những lệnh lõi được tích hợp sẵn trong các bộ máy TeX (xem bài viết [Tên gọi là gì: Hướng dẫn về nhiều biến thể của TeX](/latex/vi/bai-viet-chuyen-sau/55-what-s-in-a-name-a-guide-to-the-many-flavours-of-tex.md) để thảo luận về các nguyên thủy TeX). Bộ macro LaTeX cung cấp nhiều macro để tạo và lưu trữ hộp, nhưng nếu gạt bỏ toàn bộ mã macro, bạn sẽ thấy chỉ có 4 lệnh nguyên thủy mức thấp để tạo hộp:

Để tạo danh sách ngang:

* \hbox{...}

Để tạo và xếp chồng danh sách dọc:

* \vbox{...}
* \vtop{...}
* \vcenter{...}

Chúng tôi sẽ không giải thích cách dùng tất cả các lệnh tạo hộp này vì có rất nhiều ví dụ và hướng dẫn ở nơi khác trên web hoặc trong các sách TeX/LaTeX—nhưng chúng tôi sẽ xem xét cách các hộp được biểu diễn và lưu trữ bên trong các cấu trúc dữ liệu của TeX.

### Glue: khoảng cách linh hoạt

Glue, thực chất, là một dạng khoảng cách mà TeX dùng để căn chỉnh/vị trí các mục theo chiều ngang hoặc chiều dọc. Là người dùng TeX, ta có thể yêu cầu TeX chèn một lượng glue có kích thước cố định hoặc dùng glue linh hoạt—có độ linh hoạt đúng như ta cần, để giãn ra hoặc co lại tùy theo yêu cầu. Một trong các lệnh của TeX để tạo glue cho khoảng cách ngang được gọi là `\hskip` có dạng

`**\hskip** <natural width> **plus** <amount to stretch> **minus** <amount to shrink>`

`**plus**` và `**minus**` là các từ khóa TeX nhưng bạn không cần dùng chúng cho mọi glue. Nếu `**plus**` hoặc `**minus**` vắng mặt thì phần tương ứng `<amount to stretch>` hoặc `<amount to shrink>` được xem là bằng 0. Ví dụ, `\hskip 3pt` chèn một glue có độ rộng cố định, không có thành phần giãn ra hay co lại.

Hiện tại, hãy coi `<amount to stretch>` và `<amount to shrink>` như các *khuyến nghị* gửi cho TeX, vì lượng giãn ra hay co lại chính xác sẽ do TeX tính toán.

Để giúp hiểu các ý tưởng này, đây là một sơ đồ biểu diễn glue như một lò xo.  `<natural width>` là chiều dài của lò xo khi không có lực căng (giãn) hay nén (co).  `<amount to stretch>` và `<amount to shrink>` được thể hiện tương đối so với chiều dài tự nhiên của lò xo.

![{{{alt}}}](/files/974d8dd275e48d83a47fa73dee38a4398f170855)

#### Một ví dụ \hbox

Giả sử chúng ta muốn tạo một `\hbox{...}` chứa chỉ các chữ cái A, B, C và D, và chúng ta cần hộp này rộng 100pt (100 điểm TeX). Ngoài ra, có thể giả định rằng tổng độ rộng của bốn ký tự đó nhỏ hơn rất nhiều so với 100pt, điều đó cho thấy TeX cần một cách nào đó để lấp đầy phần không gian còn lại trong hộp: chúng ta sẽ dùng một ít glue để làm việc đó. Tuy nhiên, vì không biết chính xác lượng glue cần để lấp đầy hộp, nên nên thêm một vài glue linh hoạt và để TeX lo việc tính toán lượng không gian mà các glue đó cần chiếm. Trong đoạn mã sau, lưu ý việc dùng “%” để triệt tiêu các khoảng trắng giữa các từ phát sinh từ các ký tự xuống dòng.

```
\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt B%
\hskip 0pt plus 2fil C%
\hskip 0pt plus 2fill D%
\hskip 0pt plus 3fill}
```

Hộp kết quả trông như sau (phóng to cho rõ):

![{{{alt}}}](/files/8314eaf87a299dc36de1cfa6fc6e1ebca16e1dca)

Tệp này `\hbox` được phủ lên bằng các hộp nét đứt (màu đỏ) để chỉ độ rộng của các ký tự (theo cách TeX nhìn thấy chúng). Về mặt dàn trang, các ký tự được xem như những hộp nhỏ và lượng glue cần để lấp đầy `\hbox`được xác định (tính toán) bằng cách tính đến độ rộng của từng ký tự.

Hóa ra TeX đã không giãn hay co glue giữa A và B (được đặt là 4pt) và cũng không có glue giữa B và C (được đặt là 0pt). Tuy nhiên, glue giữa C và D và glue giữa D và cuối hộp đều đã giãn ra đáng kể vì những glue đó có thành phần giãn linh hoạt nhất—thực chất, chúng đã hấp thụ toàn bộ phần giãn cần thiết để lấp đầy hộp.

## Quay lại LuateX

Cho đến nay chúng ta đã khám phá hộp và glue và thấy rằng LuaTeX cho phép truy cập vào các cấu trúc nội bộ của TeX vốn bị che giấu khi dùng pdfTeX và XeTeX. Đã đến lúc có một ví dụ để làm điều này rõ hơn, nhưng trước hết, chúng ta cần làm quen nhanh với cách TeX lưu trữ các hộp trong bộ nhớ—chúng ta sẽ bắt đầu bằng một phép so sánh.

### Cách TeX lưu hộp trong bộ nhớ: một phép so sánh

Giả sử, vì một lý do nào đó, bạn cần tạo một mô hình dữ liệu mô tả một chiếc hộp vật lý. Bạn có thể chọn những dữ liệu nào để đưa vào mô tả đó? Một cách tiếp cận là chia thông tin thành hai phần: dữ liệu về chính chiếc hộp vật lý và dữ liệu cung cấp danh sách các đồ vật bên trong hộp. Vì vậy, mô hình đơn giản của chúng ta có thể trông như sau:

1. Dữ liệu về hộp vật lý (“siêu dữ liệu”):

* width
* chiều cao
* độ sâu
* trọng lượng
* màu sắc
* loại (gỗ, nhựa, bìa cứng)

3. Dữ liệu về nội dung hộp: một dạng danh sách mô tả các vật chứa bên trong—có lẽ được liệt kê mà không theo thứ tự đặc biệt nào.

Và có một phép tương tự rất gần với cách TeX lưu trữ các hộp.

### Cách TeX lưu hộp trong bộ nhớ: hlists và vlists

Về mặt nội bộ, TeX tạo ra các “container” gọi là *hlists* (horizontal lists) và *vlists* (vertical lists) để biểu diễn hbox và vbox tương ứng. Các đối tượng hlist/vlist này cung cấp một tập hợp “siêu dữ liệu” về hộp, đồng thời cho phép truy cập vào danh sách các đối tượng mà hộp thực sự chứa—danh sách đó được gọi là một *node list*. Không giống như một chiếc hộp vật lý, nơi bạn có thể đặt các vật vào bên trong theo bất kỳ thứ tự nào, đối với TeX, thứ tự của nội dung hộp là cực kỳ quan trọng—đó là những mục sẽ được dàn trang. Nếu bạn có chút nền tảng về lập trình hoặc khoa học máy tính thì sẽ không ngạc nhiên khi biết rằng các đối tượng trong một hộp TeX được lưu trữ, và thứ tự tạo ra của chúng được giữ nguyên, bằng một [doubly-linked list](https://en.wikipedia.org/wiki/Doubly_linked_list). Chúng tôi sẽ không bàn sâu hơn về danh sách liên kết vì trên web có rất nhiều hướng dẫn, ví dụ và giải thích.

Khái niệm về các node và node list là một khía cạnh cơ bản của cách TeX hoạt động, nhưng trong phạm vi bài viết này chúng tôi chỉ nêu rất ngắn gọn. Về bản chất, node là một loại “container nhỏ” và (tính đến LuaTeX 1.04) có khoảng 50 loại node khác nhau: phản ánh các kiểu dữ liệu và thành phần bên trong mà LuaTeX dùng để dàn trang. Ví dụ, có các node biểu diễn: glyph (phát sinh từ “ký tự”), glue, đường kẻ ngang/dọc, penalty, “whatsits”, kern, v.v. Tất cả vật liệu đã dàn trang cuối cùng sẽ trở thành một phần của một node list khổng lồ và LuaTeX cho phép bạn truy cập trực tiếp vào các cấu trúc dữ liệu bên trong đó. LuaTeX cũng cho phép bạn thêm, chỉnh sửa, bổ sung hoặc tạo node list, để chẳng hạn bạn có thể tạo hộp trực tiếp bên trong mã Lua mà không cần dùng bất kỳ mã TeX nào. Tuy nhiên, việc viết về điều đó xin để dịp khác.

### Một ví dụ đơn giản về \directlua{...} đang hoạt động

Ví dụ sau tạo ra một `\hbox` và lưu nó vào thanh ghi hộp 0. Sau đó, chúng tôi báo cáo độ rộng của hộp bằng mã TeX truyền thống và thu được cùng thông tin bằng phương pháp thứ hai qua `\directlua{}`. Ở đây, chúng tôi chạy một script Lua nhỏ truy cập vào vùng lưu trữ hộp nội bộ của TeX để lấy độ rộng của hộp—dĩ nhiên, hai giá trị là giống hệt nhau: 2412092sp (sp=scaled point: 65536sp = 1 điểm TeX). Cuối cùng, trong ví dụ cực kỳ đơn giản này, cả mã TeX lẫn mã Lua đều xem cùng một cấu trúc dữ liệu nội bộ để lấy độ rộng của hộp, nhưng chính qua đường truy cập trực tiếp mà LuaTeX mở ra một kho thông tin và khả năng điều khiển mà các bộ máy khác không có.

![{{{alt}}}](/files/4a601bc4a8cad175faf9cab219b61f6e0218764f)

```latex
\documentclass{article}
\begin{document}
\setbox0=\hbox{A\hskip 5pt B\hskip 10pt C}
\fontsize{18}{22}\selectfont
\noindent Dùng mã \TeX{}, hộp 0 có độ rộng \number\wd0\relax \space sp\par
\noindent Chúng ta cũng có thể dùng Lua và gọi một trong các hàm của Lua\TeX{} để lấy cùng
thông tin.\vskip10mm
\noindent Từ mã Lua, hộp 0 có độ rộng
\directlua{
local boxwidth = tex.box[0].width
tex.print(boxwidth.." sp")
} mà dĩ nhiên trùng với giá trị thu được từ mã \TeX{}.
\end{document}
```

## Kết hợp tất cả: Một dự án Overleaf

Chúng tôi đã lưu ý rằng, về mặt nội bộ, TeX biểu diễn các hộp như các “container” gọi là hlists/vlists, lưu “siêu dữ liệu” về hộp và cung cấp quyền truy cập vào danh sách các thành phần từ đó hộp được cấu thành. Dùng LuaTeX, bạn có thể truy cập “siêu dữ liệu” của hộp và danh sách các mục chứa trong một hộp TeX: glyph, glue, penalty, các hộp khác, v.v. Bằng các script Lua, có thể kiểm tra một hộp đang nằm trong bộ nhớ của TeX và vẽ ra một biểu diễn chi tiết của những gì hộp đó chứa. Một biểu diễn phù hợp của một hộp TeX và nội dung của nó được thực hiện bằng *đồ thị nút* và chúng tôi đã chuẩn bị một [dự án Overleaf](https://www.overleaf.com/latex/examples/exploring-the-structure-of-tex-boxes-with-luatex/pwdrypmtdbgs) làm điều đó bằng cách tận dụng một script Lua tuyệt vời do Patrick Gundlach viết (xem phần ghi công). Chúng tôi sẽ không mô tả chi tiết các quy trình cần để kiểm tra hộp và tạo đồ thị nút—ngoại trừ việc lưu ý rằng bất kỳ chương trình/script nào xử lý các hộp TeX đều phải *đệ quy* vì các hộp có thể lồng nhau: tức là, bạn có thể có hbox nằm trong vbox, nằm trong hbox… kết hợp mọi loại hộp ở mức lồng rất sâu.

![{{{alt}}}](/files/666406c558edc347c52929e52f3c93e375dedc97)

### Dự án cung cấp gì?

Nó chỉ triển khai 1 lệnh có tên là `\dobox{box command}`, chẳng hạn:

```latex
\dobox{\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt
B\hskip 0pt plus 2fil
C\hskip 0pt plus 2fill
D\hskip 0pt plus 3fill}}
```

Tính năng `\dobox{...}` lệnh này thực hiện một số tác vụ:

1. trong tài liệu của bạn, nó dàn trang nguyên văn mã TeX cho hộp của bạn;
2. nó tạo ra một đồ họa SVG của hộp TeX—bạn có thể nhúng nó vào một trang web (như chúng tôi đã làm trong bài blog này);
3. nó tạo ra một đồ họa SVG của danh sách nút—bạn cũng có thể nhúng nó vào các trang web (như chúng tôi đã làm trong bài blog này);
4. nó xuất ra một đồ họa PDF của danh sách nút, sau đó được nhập vào tài liệu PDF chính do dự án tạo ra.

Đồ thị nút có thể nhanh chóng trở nên cực kỳ lớn do lượng dữ liệu khổng lồ mà LuaTeX cần lưu trữ để biểu diễn các hộp TeX phức tạp—chẳng hạn như trang đang được tạo, hoặc toán học đã dàn trang. Với các node list lớn hơn, đồ họa PDF được nhập có thể bị cắt theo ranh giới trang của tài liệu—nếu bạn muốn xem một đồ thị nút lớn, bạn có thể tải xuống một tệp ZIP của dự án và giải nén đồ họa PDF mà bạn quan tâm. Khi tải tệp ZIP của dự án, hãy chắc chắn chọn “Input and Output Files” từ danh sách tùy chọn thả xuống:

![{{{alt}}}](/files/4f7aaaab04acdbc194b588c10b8b27a833579001)

### Đồ họa từ dự án Overleaf: Mô tả ngắn gọn

Trước khi chúng tôi đưa ra một vài ví dụ, đáng để nêu vài nhận xét về các đồ họa do dự án Overleaf tạo ra—chúng tôi sẽ dùng cùng một `\hbox` ví dụ đã nhắc đến trước đó trong bài viết. Ở đây nó được bao bọc trong `\dobox{...}` lệnh:

```latex
\dobox{\hbox to100pt{%
A\hskip4pt plus3pt minus 2pt
B\hskip 0pt plus 2fil
C\hskip 0pt plus 2fill
D\hskip 0pt plus 3fill}}
```

Đây là `\hbox` được TeX tạo ra—để rõ hơn, hộp đã được phóng lớn nhưng viền được bao gồm trong các đồ họa do dự án Overleaf tạo ra.

![{{{alt}}}](/files/704c8ed70757ddadab512608876b36868ba12fef)

Đây là một *có chú thích* sơ đồ SVG của danh sách nút biểu diễn hộp ở trên—các chú thích đã được thêm vào để làm nổi bật “siêu dữ liệu” của hộp và danh sách các đối tượng nó chứa: những chú thích đó không có trong các đồ họa do dự án Overleaf tạo ra.

[![{{{alt}}}](/files/610eaca1c3c786f0da6d9bf4d9c7fd7361093a8c)](https://www.filepicker.io/api/file/ZSwIylUR66eFYPMo0suX)

Nếu nhìn vào phần “siêu dữ liệu”, bạn có thể thấy một số tham số lạ:

* `glue_set`
* `glue_sign`
* `glue_order`

Các tham số này là các thiết lập mà TeX dùng để tính xem glue phải giãn ra hay co lại bao nhiêu trong hộp này và chỉ là một ví dụ về dữ liệu mà bạn có thể dễ dàng lấy được qua LuaTeX nhưng không thể bằng các bộ máy TeX khác. Lưu ý rằng các node glue nằm trong các thành phần của hộp *giữ lại* các giá trị glue ban đầu mà chúng ta đã nhập để tạo hộp. Điều này rất quan trọng vì TeX cung cấp các lệnh `\unhbox`, `\unvbox`, `\unhcopy`, `\unvcopy` để “mở hộp” nội dung của hộp và giải phóng chúng trở lại luồng nhập để một lần nữa tham gia vào các thao tác dàn trang. Chỉ khi TeX cuối cùng xuất (ship out) hộp sang một tệp PDF hoặc DVI thì `glue_set`, `glue_sign` và `glue_order` được áp dụng cho bất kỳ glue nào chứa trong hộp—để tính toán lượng giãn hoặc co thực tế cần để định vị các thành phần trong hộp rồi tạo dữ liệu PDF hoặc mã lệnh DVI thích hợp.

Một tham số khác được liệt kê trong “siêu dữ liệu” là `shift`: đây là giá trị dịch chuyển của hộp do áp dụng các lệnh TeX:

* `\raise`, `\lower` (áp dụng cho một `\hbox`);
* `\moveleft`, `\moveright` (áp dụng cho một `\vbox`).

Trong ví dụ của chúng tôi, `shift` là 0pt vì chúng tôi không dịch chuyển `\hbox` khỏi vị trí tự nhiên của nó.

Tính năng [dự án Overleaf](https://www.overleaf.com/latex/examples/exploring-the-structure-of-tex-boxes-with-luatex/pwdrypmtdbgs) cũng xuất ra các sơ đồ đồ thị nút ở định dạng PDF: đây là liên kết để tải về một [phiên bản tệp PDF](https://www.filepicker.io/api/file/bezigXESC2FSasvjoh8A) của đồ thị nút ở trên.

### Dự án Overleaf tạo những đồ họa đó như thế nào?

Dự án Overleaf tận dụng khả năng chạy các công cụ phần mềm và tiện ích được cài đặt trên máy chủ của Overleaf—xem [bài blog này](/latex/vi/bai-viet-chuyen-sau/52-using-luatex-to-run-tools-and-utilities-installed-on-overleaf-s-servers.md) để biết thêm chi tiết và một dự án mẫu. Để tạo một đồ họa SVG biểu diễn một hộp TeX, mã TeX của hộp được ghi ra một tệp nhỏ, rồi tệp đó được dàn trang bằng pdfTeX để tạo ra một tệp DVI—lưu ý rằng chương trình pdfTeX được LuaTeX thực thi thông qua vài dòng script Lua. Tệp DVI đó sau đó được chuyển đổi tức thời sang SVG bằng `dvisvgm` tiện ích—đi kèm với bản phân phối TeX Live được cài đặt trên các máy chủ của Overleaf. `dvisvgm` được thực thi với tùy chọn dòng lệnh `-n` để đảm bảo rằng mọi văn bản đã dàn trang được chuyển thành các đường/đường cong, nhờ đó việc hiển thị đúng tệp SVG không phụ thuộc vào việc phông TeX đã được cài đặt.

Để tạo các đồ thị nút, chúng tôi dùng một script Lua có tên là `hiviznodelist.lua` dựa trên công trình của Patrick Gundlach. Script đó ghi ra một tệp được gọi là `.gv` (Graphviz), tức một tệp văn bản chứa một đồ thị nút được mô tả bằng `dot` ngôn ngữ dot.  `.gv` tệp này được xử lý bởi một chương trình tiện ích có tên là `dot` chương trình này xuất ra sơ đồ nút ở cả hai định dạng tệp PDF và SVG.

### Các ví dụ của dự án

Sau đây là một số ví dụ bổ sung với đồ họa SVG được tạo bằng dự án Overleaf. Các hộp chứa rất nhiều văn bản (ví dụ trong một \vbox), hoặc toán học phức tạp, sẽ tạo ra các đồ thị nút khổng lồ—nếu bạn khám phá dự án Overleaf, nên tránh dùng các hộp quá phức tạp không cần thiết để minh họa các tính năng bạn quan tâm.

#### \vbox to 25pt{A}

Ví dụ này minh họa tác động của việc đặt văn bản trực tiếp vào một `\vbox`: lưu ý rằng cấu trúc nút khá phức tạp, ngay cả với một hộp đơn giản như vậy. Lý do cho sự phức tạp này là văn bản đặt trực tiếp vào một `\vbox` khiến TeX tiến hành ngắt dòng. Bạn có thể thấy rằng `\vbox` có độ rộng 345pt: giá trị của `\hsize` tại thời điểm hộp này được tạo. Cũng lưu ý rằng ký tự “A” nằm trong một `hlist` cũng rộng 345 điểm, và hãy quan sát hình phạt lớn (10000) cùng với `\parfillskip` và `\rightskip` các glue ở cuối nội dung hộp. Hình phạt đó và hai mục glue được TeX chèn vào trong quá trình ngắt dòng. Nếu bạn nhìn vào `glue_set` giá trị của dòng đoạn (`hlist`) chứa chữ “A”, bạn sẽ thấy nó cực lớn (322.500000): tại sao vậy? Là vì dòng đoạn rộng 345pt nhưng chỉ chứa một `\parindent` và chữ “A”: phần không gian còn lại phải được lấp đầy bởi `\parfillskip` glue phải giãn ra một khoảng khá lớn để lấp đầy phần không gian còn lại trên dòng.

![{{{alt}}}](/files/77b764905bde60c6a0baa615fd9151a8dedf7759)

[![{{{alt}}}](/files/482abf878c5f9a6ef66e7f1616527fca7a09816f)](https://www.filepicker.io/api/file/pVtHsNGSQ4m09vBZuOpQ)

[Tải xuống tệp PDF](https://www.filepicker.io/api/file/nBS0uDs2QjqKCKljAm7r)

#### \vbox to 25pt{\hbox{A}}

Rất bổ ích khi so sánh ví dụ này với ví dụ trước. Ở đây, không chỉ đồ thị nút nhỏ hơn đáng kể, mà độ rộng của `\vbox` chỉ là 7.50002pt: đúng bằng độ rộng của ký tự “A”. Lý do là chữ “A” đã được bọc trong một `\hbox` điều này ngăn `\vbox` TeX kích hoạt ngắt dòng—một đặc tính quan trọng của các hộp được tạo với `\vbox`.

![{{{alt}}}](/files/9a6169526e93d0e8e9266dbd3932de17d3538d63)

[![{{{alt}}}](/files/ebd56deb01eacac2585a3f7e0da617d421dd4eb5)](https://www.filepicker.io/api/file/LHepknjnRGOVEdghW4qH)

[Tải xuống tệp PDF](https://www.filepicker.io/api/file/Yk3uCCQR5ao8Yd3TJCdE)

#### Toán học đơn giản: \hbox{$$\displaystyle \int f(x) dx$$}, hộp phức tạp!

Ví dụ này cho thấy rằng ngay cả toán học được dàn trang rất đơn giản cũng tạo ra một cấu trúc hộp chi tiết: dàn trang toán học tạo ra *cực kỳ* các cấu trúc dữ liệu phức tạp trong TeX!

![{{{alt}}}](/files/a51118b1390e89c93d2b417cd78ac19a624dad56)

[![{{{alt}}}](/files/cfeaaa07819267e82a314fc395e612eee6ef1055)](https://www.filepicker.io/api/file/oVFNNvCqT0eZP0qS2odk)

[Tải xuống tệp PDF](https://www.filepicker.io/api/file/D5TepsdaSdeYZvkuSEJt)

## Ghi công: cảm ơn Patrick!

Chúng tôi xin cảm ơn [Patrick Gundlach](https://twitter.com/patrickgundlach) người đã cho phép Overleaf sử dụng và phân phối một phiên bản đã chỉnh sửa của script Lua của ông, `viznodelist.lua`, script này xử lý các hộp TeX và xuất ra một tệp (bằng `dot` ngôn ngữ) có thể được xử lý để vẽ một đồ thị nút. Dự án Overleaf chứa một script Lua có tên là `hiviznodelist.lua`—một phiên bản đã đổi tên và chỉnh sửa của mã gốc của Patrick, vốn có sẵn trên [GitHub](http://gist.github.com/556247). Patrick đã tạo ra một hệ thống dàn trang mã nguồn mở dựa trên LuaTeX có tên là [speedata Publisher](https://speedata.github.io/publisher/index.html) mà bạn có thể tải xuống và sử dụng miễn phí—các tùy chọn hỗ trợ thương mại cũng có sẵn.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://overleaf-pro.ayaka.space/latex/vi/bai-viet-chuyen-sau/36-pandora-s-hbox-using-luatex-to-lift-the-lid-of-tex-boxes.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
