Skip to content

วิธีการทำงานของ Markdown

การทำความเข้าใจวิธีการทำงานของ Markdown จะช่วยให้คุณใช้เครื่องมือที่มีประสิทธิภาพนี้ได้ดียิ่งขึ้น บทนี้จะอธิบายอย่างละเอียดว่า Markdown แปลงจากข้อความธรรมดาเป็นเอกสารที่มีการจัดรูปแบบที่สวยงามได้อย่างไร

เวิร์กโฟลว์พื้นฐาน

เวิร์กโฟลว์ของ Markdown สามารถสรุปเป็นขั้นตอนต่อไปนี้:

ไฟล์ต้นฉบับ Markdown (.md) → ตัวแยกวิเคราะห์ Markdown → เอกสาร HTML → การแสดงผลในเบราว์เซอร์

1. เขียนไฟล์ต้นฉบับ Markdown

คุณใช้โปรแกรมแก้ไขข้อความใดๆ ในการสร้างไฟล์ .md และใช้ไวยากรณ์ Markdown ในการเขียนเนื้อหา:

markdown
# เอกสารของฉัน

นี่คือย่อหน้าที่**สำคัญ**

## ตัวอย่างรายการ

- รายการ 1
- รายการ 2
- รายการ 3

2. การประมวลผลตัวแยกวิเคราะห์ Markdown

ตัวแยกวิเคราะห์อ่านไฟล์ Markdown ระบุองค์ประกอบไวยากรณ์และแปลงเป็น HTML ที่เกี่ยวข้อง:

html
<h1>เอกสารของฉัน</h1>
<p>นี่คือย่อหน้าที่<strong>สำคัญ</strong></p>
<h2>ตัวอย่างรายการ</h2>
<ul>
  <li>รายการ 1</li>
  <li>รายการ 2</li>
  <li>รายการ 3</li>
</ul>

3. การแสดงผลในเบราว์เซอร์

HTML ที่สร้างขึ้นจะแสดงเป็นเอกสารที่มีการจัดรูปแบบในเบราว์เซอร์

กลไกการทำงานของตัวแยกวิเคราะห์

การวิเคราะห์คำศัพท์

ตัวแยกวิเคราะห์ดำเนินการวิเคราะห์คำศัพท์ก่อน โดยแยกข้อความ Markdown ออกเป็นโทเค็น (tokens):

  • # ระบุเป็นโทเค็นหัวข้อ
  • **text** ระบุเป็นโทเค็นข้อความหนา
  • - item ระบุเป็นโทเค็นรายการ

การแยกวิเคราะห์ไวยากรณ์

จากนั้นดำเนินการแยกวิเคราะห์ไวยากรณ์ สร้างแผนผังโครงสร้างไวยากรณ์แบบนามธรรม (AST):

เอกสาร
├── หัวข้อ(ระดับ1): "เอกสารของฉัน"
├── ย่อหน้า
│   ├── ข้อความ: "นี่คือย่อหน้าที่"
│   ├── ข้อความหนา: "สำคัญ"
│   └── ข้อความ: ""
├── หัวข้อ(ระดับ2): "ตัวอย่างรายการ"
└── รายการแบบไม่มีลำดับ
    ├── รายการ: "รายการ 1"
    ├── รายการ: "รายการ 2"
    └── รายการ: "รายการ 3"

การสร้าง HTML

สุดท้ายข้ามแผนผังไวยากรณ์ สร้าง HTML เอาต์พุตที่เกี่ยวข้อง

ตัวแยกวิเคราะห์หลัก

CommonMark

  • มาตรฐาน - ให้มาตรฐานการแยกวิเคราะห์ Markdown ที่เป็นมาตรฐาน
  • คำจำกัดความที่เข้มงวด - กำจัดความคลุมเครือระหว่างการใช้งานต่างๆ
  • การรองรับอย่างกว้างขวาง - ถูกนำมาใช้โดยตัวแยกวิเคราะห์หลายตัว

GitHub Flavored Markdown (GFM)

อิงตาม CommonMark เพิ่ม:

  • การรองรับตาราง
  • ขีดฆ่า
  • รายการงาน
  • การระบุลิงก์อัตโนมัติ
  • บล็อกโค้ดที่มีการเน้นไวยากรณ์

ตัวแยกวิเคราะห์อื่นๆ

ตัวแยกวิเคราะห์ภาษาคุณสมบัติ
markedJavaScriptเร็ว น้ำหนักเบา
markdown-itJavaScriptสามารถเสียบได้ รองรับส่วนขยาย
Python-MarkdownPythonฟีเจอร์ครบถ้วน ระบบปลั๊กอิน
kramdownRubyรองรับรูปแบบเอาต์พุตหลายแบบ
PandocHaskellตัวแปลงเอกสารสากล

เอ็นจินการแสดงผล

การแสดงผลฝั่งไคลเอนต์

แยกวิเคราะห์ Markdown ในเบราว์เซอร์แบบเรียลไทม์:

javascript
// ใช้ marked.js
const html = marked.parse('# Hello World');
document.body.innerHTML = html;

ข้อดี:

  • ไม่จำเป็นต้องประมวลผลฝั่งเซิร์ฟเวอร์
  • ผลการแสดงตัวอย่างแบบเรียลไทม์
  • ลดภาระของเซิร์ฟเวอร์

ข้อเสีย:

  • ขึ้นกับ JavaScript
  • ไม่เป็นมิตรกับ SEO
  • โหลดครั้งแรกช้า

การแสดงผลฝั่งเซิร์ฟเวอร์

สร้าง HTML ไว้ล่วงหน้าบนเซิร์ฟเวอร์:

javascript
// ตัวอย่าง Node.js
const fs = require('fs');
const marked = require('marked');

const markdown = fs.readFileSync('document.md', 'utf8');
const html = marked.parse(markdown);

ข้อดี:

  • เป็นมิตรกับ SEO
  • โหลดเร็ว
  • ไม่ขึ้นกับ JavaScript ฝั่งไคลเอนต์

ข้อเสีย:

  • ภาระการประมวลผลของเซิร์ฟเวอร์
  • การจัดการแคชซับซ้อน

การสร้างไซต์แบบคงที่

สร้างหน้าทั้งหมดล่วงหน้าในตอน build:

bash
# ใช้ VitePress
npm run build

ข้อดี:

  • โหลดเร็วที่สุด
  • SEO ดีที่สุด
  • ความปลอดภัยสูง
  • ติดตั้งง่าย

ข้อเสีย:

  • การรองรับเนื้อหาแบบไดนามิกมีจำกัด
  • เวลาสร้างนาน

กลไกการขยาย

ระบบปลั๊กอิน

ตัวแยกวิเคราะห์หลายตัวรองรับการขยายด้วยปลั๊กอิน:

javascript
// ตัวอย่างปลั๊กอิน markdown-it
const md = require('markdown-it')()
  .use(require('markdown-it-footnote'))
  .use(require('markdown-it-deflist'))
  .use(require('markdown-it-abbr'));

ตัวแสดงผลแบบกำหนดเอง

javascript
// การแสดงผลลิงก์แบบกำหนดเอง
const renderer = new marked.Renderer();
renderer.link = function(href, title, text) {
  return `<a href="${href}" target="_blank">${text}</a>`;
};

การปรับปรุงประสิทธิภาพ

กลยุทธ์แคช

javascript
const cache = new Map();

function parseMarkdown(content) {
  const hash = generateHash(content);
  if (cache.has(hash)) {
    return cache.get(hash);
  }
  
  const result = marked.parse(content);
  cache.set(hash, result);
  return result;
}

โหลดขี้เกียจ

javascript
// แยกวิเคราะห์เฉพาะเนื้อหาในพื้นที่ที่มองเห็นได้
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      parseAndRender(entry.target);
    }
  });
});

การประมวลผลแบบสตรีม

javascript
// แยกวิเคราะห์ไฟล์ขนาดใหญ่แบบสตรีม
const fs = require('fs');
const { Transform } = require('stream');

const markdownTransform = new Transform({
  transform(chunk, encoding, callback) {
    const html = marked.parse(chunk.toString());
    callback(null, html);
  }
});

fs.createReadStream('large-document.md')
  .pipe(markdownTransform)
  .pipe(fs.createWriteStream('output.html'));

ปัญหาที่พบบ่อย

1. ปัญหาการขึ้นบรรทัดใหม่

ตัวแยกวิเคราะห์ต่างๆ อาจจัดการกับการขึ้นบรรทัดใหม่ต่างกัน:

markdown
บรรทัด 1
บรรทัด 2        ← ที่นี่อาจถูกแยกเป็นย่อหน้าเดียวกัน

บรรทัด 1  
บรรทัด 2        ← เว้นวรรคสองช่องที่ท้ายบรรทัดบังคับขึ้นบรรทัดใหม่

บรรทัด 1

บรรทัด 2        ← บรรทัดว่างแยกย่อหน้า

2. การใช้ HTML ผสม

markdown
นี่คือ **Markdown** และ <em>HTML</em> ที่ผสมกัน

ควรระวังการปิดและซ้อนแท็ก HTML ที่ถูกต้อง

3. การหนีอักขระพิเศษ

markdown
ที่นี่ต้องหนี \* และ \_ อักขระ

สถานการณ์การใช้งานจริง

1. ระบบบล็อก

บทความ Markdown → ตัวสร้างไซต์แบบคงที่ → เว็บไซต์ HTML

2. เว็บไซต์เอกสาร

เอกสาร .md → VitePress/Docusaurus → เอกสารออนไลน์

3. ไฟล์ README

README.md → GitHub/GitLab → หน้าแรกโปรเจ็กต์

4. แอปพลิเคชันบันทึก

บันทึก Markdown → การแสดงผลแบบเรียลไทม์ → การแสดงข้อความที่อุดมไปด้วย

ขั้นตอนต่อไป

ตอนนี้คุณเข้าใจวิธีการทำงานของ Markdown แล้ว คุณสามารถ:

สร้างโดย www.markdownlang.com