[Tạo Markdown to HTML Converter : Vue.js] Markdown to HTML Converter có thể thêm Class Prefix


Bối cảnh xây dựng

Khi bạn càng phát triển markup nhiều, dần dần sẽ phát sinh những công việc phiền toái như là gắn một khối lượng text đồ sộ như điều khoản sử dụng vào từng tag. Tôi nghĩ rằng những công việc như vậy có thể trở nên dễ dàng hơn một chút nếu ta sử dụng markdown mà text format tương đối đơn giản. Tất nhiên có rất nhiều Markdown to HTML Converter (dưới đây gọi là Md2HTML) có thể sử dụng ngay. Tuy vậy, với mong muốn đơn thuần rằng “Liệu có thể cho cả class vào để áp dụng style hay không?”, tôi đã tạo ra Md2HTML sử dụng Vue.js.


Step1. Markup

HTML được tạo nên từ 3 vùng lớn.
(1) Khai báo v-model=”md_text” để nội dung đã nhập tại chỗ nhập markdown chứa biến số md_text. Và tiếp theo, kết quả parsing sẽ được chứa trong previewText, sẽ có nơi khai báo bằng {{previewText}} và có nơi hiện kết quả rendering HTML sau khi dùng (3) v-html directive để có thể hiện ra (2) HTML y nguyên.

<textarea class="viewer__cont" rows="16" v-model="md_text"></textarea> // Where to enter markdown
<textarea class="viewer__cont" rows="16" readonly>{{previewText}}</textarea> // Where to show parsed results (HTML)
<div class="viewer__cont"  v-html="previewText" ></div> // Where to show parsed results (rendering)

Step2. Áp dụng Parser

Có rất nhiều markdown parser có thể sử dụng trong môi trường phát triển node.js. Trong số đó, tôi quyết định sẽ sử dụng Marked package đã được sử dụng trong ví dụ Markdown Editor(https://vuejs.org/v2/examples/index.html) đang được cung cấp trên homepage chính thức của Vue.js.

Homepage chính thức của Marked: https://marked.js.org/

Trước tiên là sẽ phải cài đặt package.

npm install marked --save-dev

Bây giờ sẽ là vùng script.
Ta sẽ gọi package trong source.

const marked = require('marked');

Vì nội dung được nhập trong md_text sẽ biến đổi ngay và được chứa trong previewText nên sẽ nhập thuộc tính computed như phía dưới.
Trong quá trình này ở đây sẽ chỉ định nhiều option đa dạng và có thể kiểm tra nội dung chi tiết về option này trên homepage chính chức của Marked (https://marked.js.org/#/USING_ADVANCED.md#options).

data: function() {
    return{
      md_text: '# hello',
    }
},
computed: {
    previewText() {
       marked.setOptions({
        renderer: new marked.Renderer(),
        gfm: true,
        headerIds: false,
        tables: true,
        breaks: true,
        pedantic: false,
        sanitize: true,
        smartLists: true,
        smartypants: false
      });
      return marked(this.md_text);
   }
}

Và đó là MD2HTML cơ bản.


Step3. Thêm class mong muốn

Bây giờ sẽ là quá trình thêm class mong muốn vào HTML đã parsing và hiện ra code HTML đã đổi.

Thêm input sẽ nhập prefix của class trong HTML. Nội dung đã nhập sẽ được chứa trong prefix.

<input type="text" id="prefix" class="header__inp" v-model="prefix" placeholder="Input Class Prefix"/>

Vì đã sử dụng biến số mới nên sẽ khởi tạo lại giá trị của prefix ở data.

data: function() {
    return{
        md_text: '# hello',
        prefix: '',
    }
},

Bây giờ sẽ thêm class áp dụng prefix đã được nhập.

const tags = ['h1','h2','h3','h4','h5','h6','em','strong','del','u','ul','ol','a','img','pre','code','table','blockquote','hr','p'];

...
    computed: {
        previewText() {
            marked.setOptions({
                renderer: new marked.Renderer(),
                gfm: true,
                headerIds: false,
                tables: true,
                breaks: true,
                pedantic: false,
                sanitize: true,
                smartLists: true,
                smartypants: false
            });
            let changedText =  marked(this.md_text); // Adding the value return from previewText() to changedText
            if (this.prefix != ''){
                for (let tag of tags){ 
                    let classTempName;
                    let regex = new RegExp('<' + tag + '>', 'g'); // Find the start tag
                    switch(tag){ // Used to give some tags a different class name from the tag name
                        case 'h1' : classTempName = 'tit_lv1';break;
                        case 'h2' : classTempName = 'tit_lv2';break;
                        case 'h3' : classTempName = 'tit_lv3';break;
                        case 'h4' : classTempName = 'tit_lv4';break;
                        case 'h5' : classTempName = 'tit_lv5';break;
                        case 'h6' : classTempName = 'tit_lv6';break;
                        case 'strong' : classTempName = 'str';break;
                        case 'ul' : classTempName = 'lst';break;
                        case 'ol' : classTempName = 'olst';break;
                        case 'a' : classTempName = 'link';break;
                        case 'table' : classTempName = 'tb';break;
                        case 'blockquote' : classTempName = 'qt';break;
                        case 'hr' : classTempName = 'bar';break;
                        case 'p' : classTempName = 'txt';break;
                        default: classTempName = '';
                    }
                    changedText = changedText.replace(regex, `<${tag} class="${this.prefix}_${classTempName}">`); // Add class consisting of prefix and tag name
                }
            }
            return changedText; // Returns a new value called changedText
        }
    }
}

Kiểm tra kết quả

Sản phẩm hoàn thiện có thể kiểm tra tại http://fe.hivelab.co.kr/md2html.



🔍 Chúng tôi đang tìm kiếm FE Developer tài năng đồng hành cùng với Hivelab.

Comments

Popular posts from this blog

[React.js trong thực tiễn] Part3 : Tạo list gọi data sử dụng axios

[Activity] Một ngày tới thăm công ty mẹ Hivelab

[Activity] Hành trình du lịch Hàn Quốc của nhân viên Hivelab Vina