您好,我正在尝试找出一个正则表达式来替换innerHTML块中的文本,以提供类似于Google IM的文本本地格式。
Where:
_Italics_
!Inderline!
*Bold*
-Strike-
部分条件是必须用符号将文本包裹起来,但是如果紧随其后是空格,则触发条件将无效;因此,*粗体*不会被粗体显示,并且:* notbold但这是粗体
innerHTML将具有已经转换为hrefs的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-javascript
和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>');
.....
和
tada
大部分有效!更新最终解决方案
在最后一分钟简化了@MikeM中的 anchor 元素检查并结合了另一个stackoverflow帖子中的条件之后,我们得出了一个完整的工作解决方案。
我还需要添加一个带有结束符号的char类型的检查,因为我们要并排替换触发器 token 。
正如@ acheong87提醒您注意\ w,因为它包含
_
,因此已将其添加到除strikethroughPattern之外的所有包装条件中。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等)
狼人。
最佳答案
我建议您从否定前瞻中删除内部否定前瞻:
/(?!(?!.*?<a)[^<]*<\/a>)_it_/.test( ' _it_ <a></a>' ); // true (correct)
/(?!(?!.*?<a)[^<]*<\/a>)_it_/.test( '<a> _it_ </a>' ); // false (correct)
/(?!(?!.*?<a)[^<]*<\/a>)_it_/.test( '<a> _it_ </a> <a></a>' ); // true (wrong)
/(?![^<]*<\/a>)_it_/.test( ' _it_ <a></a>' ); // true (correct)
/(?![^<]*<\/a>)_it_/.test( '<a> _it_ </a>' ); // false (correct)
/(?![^<]*<\/a>)_it_/.test( '<a> _it_ </a> <a></a>' ); // false (correct)