iT邦幫忙

2021 iThome 鐵人賽

DAY 27
0
Modern Web

Web Component 網頁元件之路系列 第 27

[day27] - Vue 的 Html 字串處理 ( 簡易版 parser 實作 )

今天要將昨天的 tagList 轉換成 ast

// input tagList
const tagList = [
  { type: 'tagStart', tagName: 'div' },
  { type: 'text', content: 'Hello World' },
  { type: 'tagEnd', tagName: 'div' }
]

// output ast
const ast = {
  "type": "Root",
  "children": [
    {
      "type": "tag",
      "tag": "div",
      "children": [
        {
          "type": "text",
          "content": "Hello World"
        }
      ]
    }
  ]
}

結論 - parser

/**
 * For our parser we're going to take our array of tokens and turn it into an
 * AST.
 *
 *   [{ type: 'tagStart', tagName: 'div' }, ...]   =>   { type: 'tag', tag:'div', children: [...] }
 * @param tagList {array} - [{ type: 'tagStart', tagName: 'div' }, ...]
 * @returns {object} { type: 'tag', tag:'div', children: [...] }
 */
const parser = tagList => {

  const result = {type: 'Root', children: []};

  // stack 控制目前的 element 的狀況
  const stack = [result];

  for (let i = 0; i < tagList.length; i++) {

    // 目前的 element 元素
    let current = tagList[i];

    if (current.type === 'tagStart') {

      const last = stack[stack.length - 1];
      const child = { type : 'tag' , tag : current.tagName };
      (last.children) ? last.children.push(child) : last.children = [child];
      stack.push(child);
    }

    // 直接跳出一個
    else if (current.type === 'tagEnd') {

      stack.pop();
    }

    // text 元素 , 必定是最底層 , 存後立即跳出
    else if (current.type === 'text') {

      const last = stack[stack.length - 1];
      const child = { type : 'text' , content : current.content };
      (last.children) ? last.children.push(child) : last.children = [child];
      stack.pop();
    }
  }

  return result;
}

const tagList01 = [
  { type: 'tagStart', tagName: 'div' },
  { type: 'text', content: 'Hello World' },
  { type: 'tagEnd', tagName: 'div' }
]

console.log(JSON.stringify(parser(tagList01), null, 2));
/*
    {
      "type": "Root",
      "children": [
        {
          "type": "tag",
          "tag": "div",
          "children": [
            {
              "type": "text",
              "content": "Hello World"
            }
          ]
        }
      ]
    }
*/

s


上一篇
[day26] - Vue 的 Html 字串處理 ( 簡易版 tokenizer 實作 )
下一篇
[Day28] - Vue 的 Html 字串處理 ( renderer 介紹 )
系列文
Web Component 網頁元件之路30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言