您好,我正在尝试找出一个正则表达式来替换innerHTML块中的文本,以便为类似于Google IM的操作的文本提供本地格式。
Where:
_Italics_
!Inderline!
*Bold*
-Strike-
部分条件是文本必须由符号包裹,但如果紧随其后的是空格,则触发条件无效;所以 * 粗体 * 不会加粗并且: * 不加粗但这是大胆的
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
动态地。”(我不明白当人们改变格式时这是如何可能的)。
感谢一百万正则表达式向导!我欠你的情。
mwolfe.
Update
使用与上面相同的 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-javascript
and https://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>');
.....
And tada
它大部分有效!
更新最终解决方案在对 @MikeM 的锚元素检查进行最后一刻的简化并结合另一个的条件之后堆栈溢出 https://stackoverflow.com/questions/15288276/regex-query-help-lookbehind发布后我们已经达成了一个完整的工作解决方案。
我还需要添加对带有结束符号的单字符样式的检查,因为我们要并排替换触发标记。
正如 @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 等)
mwolfe.