Tất cả bài viết
Lập trìnhAstroMarkdownLập trình WebPhát triển giao diệnDX - Trải nghiệm lập trình viênSvelte

Tối ưu hóa Markdown cho mọi Framework Web với Utility của Astro: Giải pháp xử lý khoảng trắng thông minh

Tối ưu hóa Markdown cho mọi Framework Web với Utility của Astro: Giải pháp xử lý khoảng trắng thông minh

Khám phá cách sử dụng công cụ Markdown utility từ Splendid Labz để giải quyết triệt để lỗi định dạng do khoảng trắng thụt lề trong các Framework như Astro, Svelte hay React. Bài viết cung cấp hướng dẫn chi tiết giúp cải thiện trải nghiệm lập trình (DX) và làm sạch mã nguồn HTML đầu ra.

Thách thức khi sử dụng Markdown trong các Component Framework

Trong bài viết trước, tác giả Zell Liew đã chia sẻ về lý do và cách thức tích hợp một component Markdown trong môi trường Astro. Tuy nhiên, nhu cầu thực tế thường lớn hơn thế: chúng ta muốn sử dụng Markdown linh hoạt ở mọi nơi, bất kể framework bạn đang dùng là React, Vue hay Svelte. Một vấn đề phổ biến mà các lập trình viên frontend tại Việt Nam và trên thế giới thường gặp phải là sự xung đột giữa việc viết code sạch (clean code) với cách các thư viện Markdown xử lý khoảng trắng. Thông thường, chúng ta thích thụt lề nội dung bên trong các thẻ HTML để dễ theo dõi cấu trúc cây DOM, nhưng chính điều này lại gây ra lỗi hiển thị không mong muốn.

Vấn đề về khoảng trắng thụt lề trong Markdown truyền thống

Đa số các thư viện Markdown hiện nay không tự động xử lý các khoảng trắng thụt lề (whitespace indentation). Khi bạn viết nội dung Markdown bên trong một block code lồng nhau, chẳng hạn như để trong một thẻ div, bạn thường thụt lề vào vài dòng để code trông đẹp hơn như ví dụ dưới đây:

code
<div>
  <div>
    <!-- prettier-ignore -->
    <Markdown>
      This is a paragraph

      This is a second paragraph
    </Markdown>
  </div>
</div>

Tuy nhiên, do quy chuẩn của Markdown coi các dòng có độ thụt đầu dòng quá bốn khoảng trắng là một khối mã (code block), kết quả đầu ra sẽ bị bao bọc trong các thẻ <pre> và <code> thay vì các thẻ <p> thông thường. Đây là một hành vi mặc định gây khó chịu vì nó biến văn bản của bạn thành định dạng mã nguồn một cách ngoài ý muốn:

code
<div>
  <div>
    <pre><code>  This is a paragraph

      This is a second paragraph
    </code></pre>
  </div>
</div>

Để khắc phục, thông thường bạn buộc phải xóa sạch mọi khoảng trắng thụt lề, đưa nội dung Markdown về sát lề trái. Cách làm này khiến mã nguồn trở nên cực kỳ khó đọc và gây ức chế trong quá trình bảo trì dự án lâu dài, đặc biệt là với các dự án lớn có nhiều lớp lồng nhau.

code
<div>
  <div>
    <!-- prettier-ignore -->
    <Markdown>
  This is a paragraph

  This is a second paragraph
    </Markdown>
  </div>
</div>

Giải pháp với Markdown Utility từ Splendid Labz

Công cụ Markdown utility được phát triển cho Splendid Labz ra đời nhằm giải quyết triệt để lỗi khoảng trắng này. Nó cho phép bạn viết code theo phong cách thụt lề tự nhiên nhất mà vẫn đảm bảo đầu ra HTML là các thẻ đoạn văn chuẩn xác. Khi sử dụng công cụ này, kết quả nhận được sẽ sạch sẽ như sau, bất kể bạn có thụt lề bao nhiêu đi chăng nữa:

code
<div>
  <div>
    <p>This is a paragraph</p>
    <p>This is a second paragraph</p>
  </div>
</div>

Hướng dẫn tích hợp vào Astro và các Framework khác

Việc sử dụng thư viện này rất đơn giản. Bạn chỉ cần truyền chuỗi văn bản Markdown vào hàm utility. Nếu bạn đặt thuộc tính `inline: true`, hàm sẽ trả về kết quả mà không có các thẻ <p> bao quanh. Dưới đây là cách triển khai cụ thể trong một component Astro để bạn có thể tái sử dụng trên toàn hệ thống.

typescript
---
import { markdown } from '@splendidlabz/utils'
const { inline = false, content } = Astro.props
const slotContent = await Astro.slots.render('default')

// Process content
const html = markdown(content || slotContent, { inline })
---

<Fragment set:html={html} />

Sau khi thiết lập xong component trên, bạn có thể gọi nó ở bất cứ đâu trong dự án Astro của mình một cách cực kỳ gọn gàng:

code
<Markdown>
   <!-- Your content here -->
</Markdown>

Đối với các framework như Svelte, do hạn chế trong việc đọc nội dung động trực tiếp từ 'slots', chúng ta sẽ truyền nội dung Markdown qua thuộc tính (props) thay vì đặt giữa cặp thẻ mở/đóng. Dưới đây là đoạn mã thực thi trong Svelte:

typescript
<script>
  import { markdown } from '@splendidlabz/utils'
  const { content, inline = false } = $props()
  const html = markdown(content, { inline })
</script>

<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html html}

Và cách sử dụng component Markdown này trong Svelte sẽ trông như thế này, sử dụng dấu backtick để bao bọc chuỗi văn bản nhiều dòng:

code
<Markdown content=`
  ### This is a header

  This is a paragraph
`/>

Nâng tầm trải nghiệm lập trình (DX)

Tác giả Zell Liew cũng nhấn mạnh rằng việc xây dựng các công cụ này xuất phát từ mong muốn chấm dứt sự lặp lại nhàm chán trong quá trình phát triển web. Bằng cách gom nhóm các giải pháp vào thư viện như Splendid Utils, lập trình viên có thể tập trung vào logic nghiệp vụ thay vì sa đà vào việc sửa lỗi định dạng. Tại thị trường Việt Nam, nơi các dự án mã nguồn mở và nền tảng CMS Headless đang phát triển mạnh, việc ứng dụng các utility nhỏ nhưng hiệu quả như thế này sẽ giúp đội ngũ dev tiết kiệm hàng giờ debug định dạng văn bản thô. Bạn có thể tham khảo thêm các bộ thư viện khác của cùng tác giả dành cho layout, Astro và Svelte components trên blog cá nhân của ông để cải thiện quy trình làm việc của mình.

Chia sẻ: