私は非常にうまく機能しているように見えるバージョンを実装しましたが、テキストから html タグを抽出するためにまだ (かなり一般的で見掛け倒しの) 正規表現を使用しています。ここでは、コメント付きの JavaScript になっています。
方法
/**
* Manipulate text inside HTML according to passed function
* @param html the html string to manipulate
* @param manipulator the funciton to manipulate with (will be passed single word)
* @returns manipulated string including unmodified HTML
*
* Currently limited in that manipulator operates on words determined by regex
* word boundaries, and must return same length manipulated word
*
*/
var manipulate = function(html, manipulator) {
var block, tag, words, i,
final = '', // used to prepare return value
tags = [], // used to store tags as they are stripped from the html string
x = 0; // used to track the number of characters the html string is reduced by during stripping
// remove tags from html string, and use callback to store them with their index
// then split by word boundaries to get plain words from original html
words = html.replace(/<.+?>/g, function(match, index) {
tags.unshift({
match: match,
index: index - x
});
x += match.length;
return '';
}).split(/\b/);
// loop through each word and build the final string
// appending the word, or manipulated word if not a boundary
for (i = 0; i < words.length; i++) {
final += i % 2 ? words[i] : manipulator(words[i]);
}
// loop through each stored tag, and insert into final string
for (i = 0; i < tags.length; i++) {
final = final.slice(0, tags[i].index) + tags[i].match + final.slice(tags[i].index);
}
// ready to go!
return final;
};
上記で定義された関数は、HTML の文字列と、HTML 要素によって分割されているかどうかに関係なく、文字列内の単語に作用する操作関数を受け入れます。
最初にすべての HTML タグを削除し、取得元のインデックスと共にタグを保存し、次にテキストを操作して、タグを元の位置に逆の順序で追加します。
テスト
/**
* Test our function with various input
*/
var reverse, rutherford, shuffle, text, titleCase;
// set our test html string
text = "<h2>Header</h2><p>all the <span class=\"bright\">content</span> here</p>\nQuick<em>Draw</em>McGraw\n<em>going</em><i>home</i>";
// function used to reverse words
reverse = function(s) {
return s.split('').reverse().join('');
};
// function used by rutherford to return a shuffled array
shuffle = function(a) {
return a.sort(function() {
return Math.round(Math.random()) - 0.5;
});
};
// function used to shuffle the middle of words, leaving each end undisturbed
rutherford = function(inc) {
var m = inc.match(/^(.?)(.*?)(.)$/);
return m[1] + shuffle(m[2].split('')).join('') + m[3];
};
// function to make word Title Cased
titleCase = function(s) {
return s.replace(/./, function(w) {
return w.toUpperCase();
});
};
console.log(manipulate(text, reverse));
console.log(manipulate(text, rutherford));
console.log(manipulate(text, titleCase));
見出しと段落のテキストが別々の単語として認識されないなど、まだいくつかの癖があります (インライン タグではなく、別々のブロック レベルのタグにあるため)。
また、文字列操作式を実際にテキストを置換/移動するのではなく、実際に追加および削除できるようにしたいと考えています (したがって、操作後の文字列の長さは可変です)。 .
今、私はコードにいくつかのコメントを追加し、javascript の要点としてそれを載せました。誰かがそれを改善することを願っています - 特に誰かが正規表現部分を削除してより良いものに置き換えることができれば!
(コンソールに出力)
そして最後に HTML パーサーを使用する
(http://ejohn.org/files/htmlparser.js)
デモ: http://jsfiddle.net/EDJyU/