繁体   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