javascript - 正则表达式 - 格式化 block 中的文本 - IM

标签 javascript regex algorithm instant-messaging

你好,我正在尝试找出一个正则表达式来替换 innerHTML block 中的文本,以便为类似于 Google IM 操作的文本提供本地格式。

Where: 
_Italics_
!Inderline!
*Bold*
-Strike-

部分条件是文本必须被符号包裹,但如果后面紧跟着一个空格则触发条件无效;所以 * bold* 不会被加粗并且: * notbold但这是 bold

innerHTML 将具有已经转换为 href 的 URL,因此为了不混淆它们,我在正则表达式的前面添加了以下内容。

    (?!(?!.*?<a)[^<]*<\/a>)

以下 javascript 不会捕获所有结果,并且会根据我执行替换的顺序产生不同的结果。

var boldPattern          = /(?!(?!.*?<a)[^<]*<\/a>)\*([^\s]+[\s\S]?[^\s]+)\*([\s_!-]?)/gi;
var italicsPattern       = /(?!(?!.*?<a)[^<]*<\/a>)_([^\s]+[\s\S]?[^\s]+)_([\s-!\*]?)/gi;
var strikethroughPattern = /(?!(?!.*?<a)[^<]*<\/a>)-([^\s]+[\s\S]?[^\s]+)-([\s_!\*]?)/gi;
var underlinePattern     = /(?!(?!.*?<a)[^<]*<\/a>)!([^\s]+[\s\S]?[^\s]+)!([\s-_\*]?)/gi;
str = str.replace(strikethroughPattern, '<span style="text-decoration:line-through;">$1</span>$2');
str = str.replace(boldPattern, '<span style="font-weight:bold;">$1</span>$2');
str = str.replace(underlinePattern, '<span style="text-decoration:underline;">$1</span>$2');
str = str.replace(italicsPattern, '<span style="font-style:italic;">$1</span>$2');

3 选 4 的测试数据如下所示:

1 _-*ISB*-_ 2 _-!ISU!-_ 3 _*-IBS-*_ 4 _*!IBU!*_
5 _!-IUS-!_ 6 _!*IUB*!_ 7 -_*SIB*_- 8 -_!SIU!_-
9 -*_SBI_*- 10 -*!SBU!*- 11 -!_SUI_!- 12 -!*SIB*!-
13 *_-BIS-_* 14 *_!BIU!_* 15 *-_BSI_-* 16 *-!BSU!-*
17 *!_BUI_!* 18 *!-BUS-!* 19 !_-UIS-_! 20 !_*UIB*_!
21 !-_USI_-! 22 !-*USB*-! 23 !*_UBI_*! 24 !*-UBS-*!

你能不能像选择所有 4 种模式的 24 种排列中的任何一种那样拥有 4 级深度嵌套样式跨度,例如:

    -!_*SUIB*_!-

谢谢,我已经为此奋斗了大约一个星期。

避免 Mozilla 对“标记不应动态传递给 innerHTML”的不良反馈的加分。 (我不知道在更改格式时这怎么可能)。

感谢百万正则表达式向导!我欠你的债。

姆沃尔夫。

更新

使用与上述相同的 href 检测和@talemyn 帮助我们现在处于:

var boldPattern          = /(?!(?!.*?<a)[^<]*<\/a>)\*([^\s][^\*]*)\*/gi;
var italicsPattern       = /(?!(?!.*?<a)[^<]*<\/a>)_([^\s][^_]*)_/gi;
var strikethroughPattern = /(?!(?!.*?<a)[^<]*<\/a>)-([^\s][^-]*)-/gi;
var underlinePattern     = /(?!(?!.*?<a)[^<]*<\/a>)!([^\s][^!]*)!/gi;
str = str.replace(strikethroughPattern, '<s>$1</s>');
str = str.replace(italicsPattern, '<span style="font-style:italic;">$1</span>');
str = str.replace(boldPattern, '<strong>$1</strong>');
str = str.replace(underlinePattern, '<u>$1</u>');

这似乎涵盖了一个极端的例子:

    _wow *a real* !nice *person! on -stackoverflow* figured- it out_ cool beans.

我认为可以使用样式跨度并进行正则表达式回顾以确定先前未关闭的跨度,关闭它,打开一个具有旧格式和新属性的新跨度,在假定时关闭并打开一个新跨度以完成格式化。 . 但正如@NovaDenizen 指出的那样,这可能会变得困惑或无法使用正则表达式。

谢谢大家的帮助。如果有任何改进,请告诉我。注意:我无法使用,因为网站上的 CSS 无法呈现它。可以重载吗? [这是一个 firefox/greasemonkey/chrome 插件]

更新(几乎)最终

使用我的“损坏的”测试短语,正如@MikeM 正确指出的那样,作为一个示例,无论嵌套是否正确,它都会在 Google IM 中正确呈现(减去下划线)。因此,查看 Google IM 中文本的 HTML 输出,我注意到它很高兴地没有预先格式化字符串,而是简单地根据需要进行了替换。

因此,在查看使用 resetcss 删除的站点代码后,我需要通过 javascript 插入 CSS 格式。 Stackoverflow 来拯救。 https://stackoverflow.com/questions/707565/how-do-you-add-css-with-javascripthttps://stackoverflow.com/questions/20107/yui- reset-css-makes-strongemthis-not-work-em-strong

所以我的解决方案现在看起来像:

....
var css = document.createElement("style");
css.type = "text/css";
css.innerHTML = "strong, b, strong *, b * { font-weight: bold !important; } \
            em, i, em *, i * { font-style: italic !important; }";
document.body.appendChild(css);
 ....
var boldPattern          = /(?!(?!.*?<a)[^<]*<\/a>)\*([^\s][^\*]*)\*/gi;
var italicsPattern       = /(?!(?!.*?<a)[^<]*<\/a>)_([^\s][^_]*)_/gi;
var strikethroughPattern = /(?!(?!.*?<a)[^<]*<\/a>)-([^\s][^-]*)-/gi;
var underlinePattern     = /(?!(?!.*?<a)[^<]*<\/a>)!([^\s][^!]*)!/gi;
str = str.replace(strikethroughPattern, '<s>$1</s>');
str = str.replace(italicsPattern, '<i>$1</i>');
str = str.replace(boldPattern, '<b>$1</b>');
str = str.replace(underlinePattern, '<u>$1</u>');
.....

tada 大部分情况下都有效!

更新最终解决方案 在对来自@MikeM 的 anchor 元素检查进行最后一分钟的简化并结合来自另一个 stackoverflow 的条件之后发布我们已经达成了一个完整的工作解决方案。

我还需要检查带有结束符号的单字符样式,因为我们要并排替换触发器标记。

正如@acheong87 提醒的那样,小心使用\w,因为它包含 _,所以它被添加到除删除线模式之外的所有条件的包装条件中。

var boldPattern          = /(?![^<]*<\/a>)(^|<.>|[\s\W_])\*(\S.*?\S)\*($|<\/.>|[\s\W_])/g;
var italicsPattern       = /(?![^<]*<\/a>)(^|<.>|[\s\W])_(\S.*?\S)_($|<\/.>|[\s\W])/g;
var strikethroughPattern = /(?![^<]*<\/a>)(^|<.>|[\s\W_])-(\S.*?\S)-($|<\/.>|[\s\W_])/gi;
var underlinePattern     = /(?![^<]*<\/a>)(^|<.>|[\s\W_])!(\S.*?\S)!($|<\/.>|[\s\W_])/gi;
str = str.replace(strikethroughPattern, '$1<s>$2</s>$3');
str = str.replace(italicsPattern, '$1<i>$2</i>$3');
str = str.replace(boldPattern, '$1<b>$2</b>$3');
str = str.replace(underlinePattern, '$1<u>$2</u>$3');

非常感谢大家(@MikeM、@talemyn、@acheong87 等)

姆沃尔夫。

最佳答案

试试这些:

var boldPattern          = /\*([^\s][^\*]*)\*/gi;
var italicsPattern       = /_([^\s][^_]*)_/gi;
var strikethroughPattern = /-([^\s][^-]*)-/gi;
var underlinePattern     = /!([^\s][^!]*)!/gi;

不过,在 replace 中,不要使用 $2,因为这些正则表达式模式中没有第二个匹配项。

关于javascript - 正则表达式 - 格式化 block 中的文本 - IM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15278728/

相关文章:

带连字符的 Java 简单正则表达式

java - 这个简单算法的复杂性

javascript - 任意重新排序和排序对象文字的javascript数组

javascript - X 和 Y 在带有偏移的 Canvas 中不匹配

javascript - JS端了解Tokbox视频分辨率

javascript - 为什么 obj.hasOwnProperty ('prop' ) 返回 false 时 obj.prop 返回 true?

正则表达式匹配两个或多个逗号分隔的整数

java - 在java中为行之间存在的字符串编写正则表达式

javascript - 是否可以通过站点树远程或本地直接爬取站点树?

algorithm - 对论文中的 P2b 证明过程感到困惑 Paxos made simple