Jeg havde en lignende opgave for noget tid siden, men det bliver simpelthen for komplekst og ulæseligt at gøre det udelukkende med et regex, så jeg valgte, at lave en lille parser. Her er min løsning i JavaScript:
- function tokenize(text) {
- var Token = function(text) {
- this.text = text;
- };
- Token.prototype.isTag = function() {
- return this.text.charAt(0) === '<';
- };
-
- Token.prototype.isStartTag = function() {
- return this.isTag() && this.text.charAt(1) !== '/';
- };
-
- Token.prototype.isEndTag = function() {
- return this.isTag() && this.isStartTag() === false;
- };
-
- Token.prototype.getTagName = function() {
- return this.text.replace(/^<\/?([a-zA-Z]+).*$/, '$1').toLowerCase();
- };
-
- var tokens = [],
- idx = 0,
- c;
- for (var i = 0; i < text.length; i++) {
- c = text.charAt(i);
- if (c === '<') {
- if (idx !== i) {
- tokens.push(new Token(text.substring(idx, i)));
- }
- idx = i;
- } else if (c === '>') {
- tokens.push(new Token(text.substring(idx, i + 1)));
- idx = i + 1;
- }
- }
-
- if (idx < text.length - 1) {
- tokens.push(new Token(text.substring(idx, text.length)));
- }
-
- return tokens;
- };
-
- function substituteLinks (text) {
- var identifier = '[a-zA-Z0-9_+]+',
- protocol = '((https?)|(ftp)|(mailto))',
- username_and_optional_password = '(' + identifier + '(:' + identifier + ')?@)?',
- ip_address = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}',
- hostname = '[a-zA-Z0-9_\.]+',
- host = '((' + ip_address + ')|(' + hostname + '))',
- port = '(:[0-9]+)?',
- host_and_port = '(' + host + port + ')',
- key_with_optional_value = identifier + '(=(' + identifier + ')?)?',
- path = '[/a-zA-Z0-9_+\\&;\\.\\-]+',
- query = '(\\?(' + key_with_optional_value + '(&' + key_with_optional_value + ')*' + ')?)?',
- anchor = '(#' + identifier + ')?',
- url = '(' + protocol + '://' + username_and_optional_password + host_and_port + path + query + anchor + ')',
- regex = new RegExp(url, 'g');
-
- return text.replace(regex, '<a href="$1">$1</a>');
- };
-
- function createLinks(text) {
-
- var tokens = tokenize(text),
- t,
- anchorNesting = 0,
- html = '';
-
- for (var i = 0; i < tokens.length; i++) {
- t = tokens[i];
- if (t.isStartTag() && t.getTagName() === 'a') {
- anchorNesting++;
- } else if (t.isEndTag() && t.getTagName() === 'a') {
- anchorNesting--;
- } else if (t.isTag() === false && anchorNesting === 0) {
- t.text = substituteLinks(t.text);
- }
- html += t.text;
- }
- return html;
- }
Du sender bare din HTML kode igennem 'createLinks' funktionen, så får du linkificeret HTML retur.
Det er sikkert ikke så svært at skrive om til C#, hvis ikke JavaScript kan bruges.
Indlæg senest redigeret d. 09.11.2012 21:12 af Bruger #2695