[英]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
。
之后我們只定義不同的具體解析器並將它們添加到視圖中。 我們可以逐個傳遞狀態( View
的nextState
)或在單個方法調用中傳遞所有狀態( View
的parse
)。 我們可以動態添加新的解析器。
可以批准的東西包括用於管理解析器的flyweight工廠。
在實現像Template方法這樣的不同模式時,使用“抽象”構造函數的方法也非常有用。
也許您想使用現有的庫,例如http://www.showdown.im/上的Markdown庫
如果您更喜歡自己編寫,那么我建議您查看源代碼以了解它是如何解析的(也許是Markdown處理器在其他語言中的源代碼)。 一些建議:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.