2015-12-26 10 views
6

Ho questo codice che rompe le righe più lunghe in una matrice di stringhe di lunghezza uguale mantenendo le parole tiene anche conto della formattazione come [[u;#fff;]some text], divide il testo in modo che ogni stringa possa essere convertita in html indipendentemente :Suddividi il testo in stringhe di uguale lunghezza mantenendo le parole intatte

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; 
}; 

funziona quasi subito, ma alcune linee sono più brevi allora dovrebbe avere:

is cracker.The term 

in questo FIDDLE, funziona proprio quando si striscia la formattazione, il controllo casella di controllo. Lavoro su questo per un paio d'ore e non ho idea di perché questa linea sia più breve, ogni aiuto sarà molto apprezzato.

+0

Che cosa dovrebbe accadere con '[[u; #fff;] del testo]' 'se Text' avvolge nella riga successiva? Vuoi ripetere la formattazione come ''[[u; #fff;] some]', '[[u; #fff;] testo]''? –

+0

@WouterHuysentruit si. – jcubic

+0

@Valijon Hai usato fiddle https://jsfiddle.net/bjrdamgg/2/? Devi includere terminale jQuery e jQuery. – jcubic

risposta

4

Ecco come risolvere il codice originale:

Aggiungere la seguente dopo la riga 40:

in_text = false; 

La bandiera in_text viene utilizzato dal codice per determinare se la posizione corrente è nel testo normale. Tuttavia, non stava cancellando il flag quando è entrato in una regione di marcatura di formattazione. Questa è stata la causa del problema principale descritto nella domanda con la linea ultra-breve.

Modificare l'istruzione if alla riga 76/77 a:

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

Questo si prende cura di un problema minore, in cui le interruzioni di linea non stavano accadendo su spazi tra il testo normale e testo formattato. violino

Lavorare qui: https://jsfiddle.net/2w10xp3m/1/

+1

Mille grazie per avermi aiutato con questo premio assegnerà la taglia dopo 22 ore. – jcubic

+1

Sì, ho appena notato che è per questo che ho cancellato il commento. – jcubic

+0

@jcubic Ho aggiunto alcune spiegazioni alla risposta per riferimento futuro. – heenenee

4

Penso di aver risolto il problema utilizzando un approccio molto più semplice. Per prima cosa separa tutte le parole, quindi riassembla le linee tenendo traccia del formato corrente. Vedi JsFiddle.

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' è un flag che disabilita il word wrapping se è impostato su false e può spezzarsi nel mezzo della parola. – jcubic

+0

Non hai specificato questo nella tua domanda. Ad ogni modo questa potrebbe essere una semplice modifica che potrei lasciare a voi, immagino :) –

Problemi correlati