2015-12-26 10 views
6

長い行を同じ長さの文字列の配列に分割するこのコードは、[[u;#fff;]some text]のような書式も考慮に入れて、各文字列を独立してHTMLに変換できるように:単語をそのままの長さの文字列に分割する

var format_re = /\[\[([!gbiuso]*;[^;\]]*;[^;\]]*(?:;|[^\]()]*);?[^\]]*)\]([^\]]*\\\][^\]]*|[^\]]*|[^\[]*\[[^\]]*)\]?/gi; 
var format_begin_re = /(\[\[[!gbiuso]*;[^;]*;[^\]]*\])/i; 
var format_last_re = /\[\[[!gbiuso]*;[^;]*;[^\]]*\]?$/i; 
$.terminal.split_equal = function(str, length, words) { 
    var formatting = false; 
    var in_text = false; 
    var prev_format = ''; 
    var result = []; 
    // add format text as 5th paramter to formatting it's used for 
    // data attribute in format function 
    var array = str.replace(format_re, function(_, format, text) { 
    var semicolons = format.match(/;/g).length; 
    // missing semicolons 
    if (semicolons == 2) { 
     semicolons = ';;'; 
    } else if (semicolons == 3) { 
     semicolons = ';'; 
    } else { 
     semicolons = ''; 
    } 
    // return '[[' + format + ']' + text + ']'; 
    // closing braket will break formatting so we need to escape 
    // those using html entity equvalent 
    return '[[' + format + semicolons + 
     text.replace(/\\\]/g, ']').replace(/\n/g, '\\n') + ']' + 
     text + ']'; 
    }).split(/\n/g); 
    for (var i = 0, len = array.length; i < len; ++i) { 
    if (array[i] === '') { 
     result.push(''); 
     continue; 
    } 
    var line = array[i]; 
    var first_index = 0; 
    var count = 0; 
    var space = -1; 
    for (var j=0, jlen=line.length; j<jlen; ++j) { 
     if (line[j] === '[' && line[j+1] === '[') { 
     formatting = true; 
     } else if (formatting && line[j] === ']') { 
     if (in_text) { 
      formatting = false; 
      in_text = false; 
     } else { 
      in_text = true; 
     } 
     } else if ((formatting && in_text) || !formatting) { 
     if (line[j] === '&') { // treat entity as one character 
      var m = line.substring(j).match(/^(&[^;]+;)/); 
      if (!m) { 
      // should never happen if used by terminal, 
      // because it always calls $.terminal.encode 
      // before this function 
      throw new Error("Unclosed html entity in line " + 
          (i+1) + ' at char ' + (j+1)); 
      } 
      j+=m[1].length-2; // because continue adds 1 to j 
      // if entity is at the end there is no next loop 
      // issue #77 
      if (j === jlen-1) { 
      result.push(output + m[1]); 
      } 
      continue; 
     } else if (line[j] === ']' && line[j-1] === '\\') { 
      // escape \] counts as one character 
      --count; 
     } else { 
      ++count; 
     } 
     } 
     function is_space() { 
     return line.substring(j-6, j) == '&nbsp;' || 
      line.substring(j-1, j) == ' '; 
     } 
     if (is_space() && ((formatting && in_text) || !formatting)) { 
     space = j; 
     } 
     if ((count === length || j === jlen-1) && 
      ((formatting && in_text) || !formatting)) { 
     var output; 
     var after = line.substring(space, j+length+1); 
     var text = $('<span>' + after + '</span>').text(); 
     var can_break = text.match(/\s/); 
     if (words && space != -1 && j !== jlen-1 && can_break) { 
      // get text to last space 
      output = line.substring(first_index, space); 
      j = space-1; 
      space = -1; 
     } else { 
      output = line.substring(first_index, j+1); 
     } 
     if (words) { 
      output = output.replace(/^(&nbsp;|\s)+|(&nbsp;|\s)+$/g, ''); 
     } 
     first_index = j+1; 
     count = 0; 
     if (prev_format) { 
      output = prev_format + output; 
      if (output.match(']')) { 
      prev_format = ''; 
      } 
     } 
     // Fix output if formatting not closed 
     var matched = output.match(format_re); 
     if (matched) { 
      var last = matched[matched.length-1]; 
      if (last[last.length-1] !== ']') { 
      prev_format = last.match(format_begin_re)[1]; 
      output += ']'; 
      } else if (output.match(format_last_re)) { 
      var line_len = output.length; 
      // why this line ??? 
      //var f_len = line_len-last[last.length-1].length; 
      output = output.replace(format_last_re, ''); 
      prev_format = last.match(format_begin_re)[1]; 
      } 
     } 
     result.push(output); 
     } 
    } 
    } 
    return result; 
}; 

それはほとんど右動作しますが、いくつかの行はそれが好きでなければならないよりも短いです:あなたは、チェックボックスをチェックし、書式設定を削除するとき、このFIDDLE

is cracker.The term 

は、それが正しく動作。私はこれを数時間働いて、なぜその行が短いのかわからない、どんな助けも非常に高く評価されるでしょう。

+0

'をどうするか、[[U; #FFF;]テキスト]' text'が次の行に折り返さ 'か?あなたは '' [[u; #fff;] some]、 '[[u; #fff;] text]' 'のような書式を繰り返すでしょうか? –

+0

@WouterHuysentruitはい。 – jcubic

+0

@Valijonあなたはfiddle https://jsfiddle.net/bjrdamgg/2/を使いましたか? jQueryとjQueryのターミナルを含める必要があります。 – jcubic

答えて

4

はここで、元のコードを修正する方法です

in_text = false; 

in_textフラグを決定するために、コードで使用されています現在の位置が通常のテキストの場合ただし、マークアップの書式設定領域に入ったときにフラグをクリアしていませんでした。これは、超短線での質問に記載されている主な問題の原因です。

変更行76/77のif文はへ:

if (is_space() && ((formatting && in_text) || !formatting || (line[j] === '[' && line[j+1] === '['))) { 

これは、改行は通常のテキストと書式付きテキストの間のスペースには起きていないし、あまり問題の世話をします。ここ

の作業フィドル:https://jsfiddle.net/2w10xp3m/1/

+1

22時間後に賞金を授与されることに多くの感謝をします。 – jcubic

+1

はい私は気づいたので、コメントを削除しました。 – jcubic

+0

@jcubic私は将来の参考のために答えにいくつかの説明を追加しました。 – heenenee

4

私はもっと簡単な方法で問題を解決したと思います。最初にすべての単語を分割してから、現在の書式を追跡しながら行を再アセンブルします。 JsFiddleを参照してください。ライン40の後に以下を追加し

はJavaScript

$.terminal.split_equal = function(str, length, words) { 
    var result = [], 
    currentFormat = null, 
    currentLine = '', 
    currentLineLengthWithoutFormatting = 0; 

    // 1. Split words on &nbsp; 
    words = str.split(/&nbsp;/g); 

    // 2. Re-assemble lines while keeping track of current formats 
    words.forEach(function(word) { 
    // Keep track of current format 
    var format = word.match(/^\[\[([^\]]+)\]/g), 
     wordWithFormatting, wordLength; 
    if (format !== null && format[0]) { 
     currentFormat = format[0]; 
     word = word.slice(format[0].length); 
    } 
    // Apply current format to each word separatly 
    wordLength = word.length; 
    wordWithFormatting = (currentFormat || '') + word; 
    if (currentFormat) { 
     if (word.indexOf(']') !== -1) { 
     wordLength--; 
     currentFormat = null; 
     } else { 
     wordWithFormatting += ']'; 
     } 
    } 
    // Assemble line 
    if (currentLineLengthWithoutFormatting + wordLength <= length) { 
     // Word still fits on current line 
     if (currentLineLengthWithoutFormatting > 0) { 
     currentLine += ' '; 
     currentLineLengthWithoutFormatting++; 
     } 
    } else { 
     // Need to start new line 
     result.push(currentLine); 
     currentLine = ''; 
     currentLineLengthWithoutFormatting = 0; 
    } 

    currentLine += wordWithFormatting; 
    currentLineLengthWithoutFormatting += wordLength; 
    }); 

    if (currentLineLengthWithoutFormatting > 0) 
    result.push(currentLine); 

    return result; 
}; 
+0

'words'は、falseに設定されている場合、単語の折り返しを無効にするフラグです。 – jcubic

+0

これはあなたの質問では指定していません。とにかく簡単に修正できるかもしれないと思いますが、私はあなたに任せます。 –

関連する問題