簡體   English   中英

如何實現在文本中解析自己的html標簽

[英]How to realize parsing of own html tags in text

我有任務要實現自己的標簽,使文本粗體 ,下划線或刪除任何嵌套。 像一個

*bold text* _underlinetext_ -strikethrough-

另外我需要像a一樣創建自己的超鏈接

[link | http://stackoverflow.com]

第一個想法來了 - 它適用於正則表達式。 代碼:

View.prototype.parseText = function(text) {

text = text.replace(/\*([^\*]+)\*/g, '<b>$1</b>');
text = text.replace(/\_([^\_]+)\_/g, '<u>$1</u>');
text = text.replace(/\-([^\-]+)\-/g, '<s>$1</s>');
text = text.replace(/\[([^\|].+)\|(.+)\]/g, '<a href="$2">$1</a>');

return text;};

它工作但我需要可擴展性。 正則表達式不是一個好主意,因為它是硬編碼的。 如何使用有限狀態機(或任何jQuery插件)實現該任務? 我將不勝感激任何幫助。

無論你做什么,為了擴展你的標記系統,你需要:1。定義標記,然后2.用等效的HTML替換它。

即使您在js中編寫自己的解析器,在一天結束時,您仍然必須執行上述2個步驟,因此它不再具有您現在所擁有的可擴展性。

正則表達式是工作的工具,除非你有其他要求(即只在這樣的元素中替換,但在另一個元素中做其他事情,這需要解析)。

您可以在函數中包裝正則表達式調用,並在需要擴展該功能時簡單地將正則表達式替換添加到該函數。 如果需要多個頁面,請將其添加到外部js文件中。

function formatUserContent(text)
{
  text = text.replace(/\*([^\*]+)\*/g, '<b>$1</b>');
  text = text.replace(/\_([^\_]+)\_/g, '<u>$1</u>');
  text = text.replace(/\-([^\-]+)\-/g, '<s>$1</s>');
  text = text.replace(/\[([^\|].+)\|(.+)\]/g, '<a href="$2">$1</a>');
  return text;
}

完成后,擴展功能就像添加一樣簡單

text = text.replace(/\+([^\-]+)\+/g, '<em>$1</em>');

在功能的主體。 我懷疑推出自己的有限狀態機將更容易擴展,恰恰相反。

在有限的狀態機上花費數小時,希望它可能在未來的某個未知時間節省幾分鍾,這不是一個好的投資......除非你當然想借口寫一個有限狀態機,在這種情況下, 前進。

作為旁注,我建議讓你的正則表達式更加簡單。

text = text.replace(/\[([^\|].+)\|\s*(http://.+)\]/g, '<a href="$2">$1</a>');

(除非你有UI元素可以為用戶完成工作)

我可以建議你以下實現http://jsfiddle.net/NwRCm/5/

它使用State設計模式(由於JavaScript和目的很少修改)。 在表面下,所有狀態都使用正則表達式實現,但在我看來,這是最有效的方式。

/* View definition */

function View(container) {
    this.container = container;
    this._parsers = [];
    this._currentState = 0;
};

View.prototype.parse = function(text) {

    var self = this;
    this._parsers.forEach(function (e) {
        self._parse(e);
    });

    return this.container.innerHTML;

};

View.prototype._parse = function (parser) {
    var text = parser.parse(this.container.innerHTML);
    this.container.innerHTML = text;
    return text;
};

View.prototype.nextState = function () {
    if (this._currentState < this._parsers.length) {
        return this._parse(this._parsers[this._currentState++]);
    }
    return null;
};

View.prototype.addParser = function (parser) {
    if (parser instanceof Parser) {
        return this._parsers.push(parser);
    } else {
        throw 'The parser you\'re trying to add is not an instance of Parser';
    }
};
/* end of the View definition */

/* Simulation of interface */
function Parser() {};

Parser.prototype.parse = function () {
    throw 'Not implemented!';
};

/* Implementation of bold parser */
function BoldParser() {};

BoldParser.prototype = new Parser();

BoldParser.prototype.parse = function (text) {
    text = text.replace(/\*([^\*]+)\*/g, '<b>$1</b>');
    return text;
};

/* Implementation of underline parser */
function UnderlineParser() {};

UnderlineParser.prototype = new Parser();

UnderlineParser.prototype.parse = function (text) {
    text = text.replace(/\_([^\_]+)\_/g, '<u>$1</u>');
    return text;
};

/* Link parser */
function LinkParser() {};

LinkParser.prototype = new Parser();

LinkParser.prototype.parse = function (text) {
    text = text.replace(/\[([^\|].+)\|(.+)\]/g, '<a href="$2">$1</a>');
    return text;
};


var v = new View(document.getElementById('container'));
v.addParser(new UnderlineParser());
v.addParser(new BoldParser());
v.addParser(new LinkParser());
v.nextState();
v.nextState();
v.nextState();

讓我更深入地了解一下實施情況。 首先我們有一個基礎“類”(構造函數)視圖。 每個視圖都有它的基本container和解析器列表,它還記得下一個應該應用哪個解析器。

之后我們有了“抽象類”(構造函數與原型中的方法拋出異常),名為Parser它定義了一個必須由每個解析器實現的方法parse

之后我們只定義不同的具體解析器並將它們添加到視圖中。 我們可以逐個傳遞狀態( ViewnextState )或在單個方法調用中傳遞所有狀態( Viewparse )。 我們可以動態添加新的解析器。

可以批准的東西包括用於管理解析器的flyweight工廠。

在實現像Template方法這樣的不同模式時,使用“抽象”構造函數的方法也非常有用。

  • 由於所有這些構造函數和對象的定義,編輯可能會有一點開銷。 一切都可以通過回調來完成,即每個狀態都是不同的功能。 我使用這種方法是因為我正在尋找最簡單的理解,從語言特定的功能答案清楚。 我希望我實現了它。

也許您想使用現有的庫,例如http://www.showdown.im/上的Markdown庫

如果您更喜歡自己編寫,那么我建議您查看源代碼以了解它是如何解析的(也許是Markdown處理器在其他語言中的源代碼)。 一些建議:

  • 使用jQuery來操作標記
  • 不要使用正則表達式來解析語言。 當標記元素混合在一起時,您會遇到問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM