<commit_before>#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Flows the text into tspans
#------------------------------------------------------------------------------
module.exports = (vars) ->

  newLine = (w, append) ->
    w = "" unless w
    if not reverse or append
      tspan = vars.container.value.append("tspan")
    else
      tspan = vars.container.value.insert("tspan", "tspan")

    tspan
      .attr "x", x + "px"
      .attr "dx", dx + "px"
      .attr "dy", dy + "px"
      .attr "dominant-baseline", if valign is "middle" then "central" else "ideographic"
      .text w

  if vars.shape.value is "circle"
    anchor = "middle"
    dx = 0
  else
    anchor = vars.align.value or vars.container.align or "start"
    if anchor is "end"
      dx = vars.width.value
    else if anchor is "middle"
      dx = vars.width.value/2
    else
      dx = 0

  valign   = vars.valign.value or "top"
  x        = parseFloat(vars.container.value.attr("x"), 10) or 0
  fontSize = if vars.resize.value then vars.size.value[1] else vars.container.fontSize or vars.size.value[0]
  dy       = vars.container.dy or fontSize
  textBox  = null
  progress = null
  reverse  = false
  yOffset = 0
  if vars.shape.value is "circle"
    if valign is "middle"
      yOffset = ((vars.height.value/dy % 1) * dy)/2
    else if valign is "end"
      yOffset = (vars.height.value/dy % 1) * dy

  vars.container.value
    .attr "text-anchor", anchor
    .attr "font-size", fontSize + "px"

  truncate = ->
    textBox.remove()
    line--
    if line isnt 1
      if reverse
        textBox = vars.container.value.select("tspan")
      else
        textBox = d3.select(vars.container.value.node().lastChild)
    unless textBox.empty()
      words = textBox.text().match(/[^\s-]+-?/g)
      ellipsis()

  lineWidth = () ->
    if vars.shape.value is "circle"
      b = ((line - 1) * dy) + yOffset
      b += dy if b > vars.height.value/2
      (2 * Math.sqrt(b * ((2 * (vars.width.value / 2)) - b)))
    else
      vars.width.value

  ellipsis = ->
    if words and words.length
      lastWord = words.pop()
      lastChar = lastWord.charAt(lastWord.length - 1)
      if lastWord.length is 1 and vars.text.split.value.indexOf(lastWord) >= 0
        ellipsis()
      else
        if vars.text.split.value.indexOf(lastChar) >= 0
          lastWord = lastWord.substr(0, lastWord.length - 1)
        textBox.text words.join(" ") + " " + lastWord + " ..."
        ellipsis() if textBox.node().getComputedTextLength() > lineWidth()
    else
      truncate()

  placeWord = (word) ->

    current   = textBox.text()

    if reverse
      next_char = vars.text.current.charAt(vars.text.current.length - progress.length - 1)
      joiner    = if next_char is " " then " " else ""
      progress  = word + joiner + progress
      textBox.text word + joiner + current
    else
      next_char = vars.text.current.charAt(progress.length)
      joiner    = if next_char is " " then " " else ""
      progress += joiner + word
      textBox.text current + joiner + word

    if textBox.node().getComputedTextLength() > lineWidth()
      textBox.text current
      textBox = newLine(word)
      if reverse then line-- else line++

  start = 1
  line  = null
  lines = null
  words = null
  wrap  = ->

    vars.container.value.html ""
    words    = vars.text.words.slice(0)
    words.reverse() if reverse
    progress = words[0]
    textBox  = newLine words.shift(), true
    line = start

    for word in words

      if line * dy > vars.height.value
        truncate()
        break

      placeWord word

      unsafe = true
      while unsafe
        next_char = vars.text.current.charAt(progress.length + 1)
        unsafe = vars.text.split.value.indexOf(next_char) >= 0
        placeWord next_char if unsafe

    lines = Math.abs(line - start) + 1

  wrap()

  lines = line
  if vars.shape.value is "circle"
    space = vars.height.value - lines * dy
    if space > dy<commit_msg>fixed safari dominant-baseline style bugs<commit_after>#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# Flows the text into tspans
#------------------------------------------------------------------------------
module.exports = (vars) ->

  newLine = (w, append) ->
    w = "" unless w
    if not reverse or append
      tspan = vars.container.value.append("tspan")
    else
      tspan = vars.container.value.insert("tspan", "tspan")

    tspan
      .attr "x", x + "px"
      .attr "dx", dx + "px"
      .attr "dy", dy + "px"
      .style "baseline-shift", if valign is "middle" then "-32%" else "10%"
      .text w

  if vars.shape.value is "circle"
    anchor = "middle"
    dx = 0
  else
    anchor = vars.align.value or vars.container.align or "start"
    if anchor is "end"
      dx = vars.width.value
    else if anchor is "middle"
      dx = vars.width.value/2
    else
      dx = 0

  valign   = vars.valign.value or "top"
  x        = parseFloat(vars.container.value.attr("x"), 10) or 0
  fontSize = if vars.resize.value then vars.size.value[1] else vars.container.fontSize or vars.size.value[0]
  dy       = vars.container.dy or fontSize
  textBox  = null
  progress = null
  reverse  = false
  yOffset = 0
  if vars.shape.value is "circle"
    if valign is "middle"
      yOffset = ((vars.height.value/dy % 1) * dy)/2
    else if valign is "end"
      yOffset = (vars.height.value/dy % 1) * dy

  vars.container.value
    .attr "text-anchor", anchor
    .attr "font-size", fontSize + "px"

  truncate = ->
    textBox.remove()
    line--
    if line isnt 1
      if reverse
        textBox = vars.container.value.select("tspan")
      else
        textBox = d3.select(vars.container.value.node().lastChild)
    unless textBox.empty()
      words = textBox.text().match(/[^\s-]+-?/g)
      ellipsis()

  lineWidth = () ->
    if vars.shape.value is "circle"
      b = ((line - 1) * dy) + yOffset
      b += dy if b > vars.height.value/2
      (2 * Math.sqrt(b * ((2 * (vars.width.value / 2)) - b)))
    else
      vars.width.value

  ellipsis = ->
    if words and words.length
      lastWord = words.pop()
      lastChar = lastWord.charAt(lastWord.length - 1)
      if lastWord.length is 1 and vars.text.split.value.indexOf(lastWord) >= 0
        ellipsis()
      else
        if vars.text.split.value.indexOf(lastChar) >= 0
          lastWord = lastWord.substr(0, lastWord.length - 1)
        textBox.text words.join(" ") + " " + lastWord + " ..."
        ellipsis() if textBox.node().getComputedTextLength() > lineWidth()
    else
      truncate()

  placeWord = (word) ->

    current   = textBox.text()

    if reverse
      next_char = vars.text.current.charAt(vars.text.current.length - progress.length - 1)
      joiner    = if next_char is " " then " " else ""
      progress  = word + joiner + progress
      textBox.text word + joiner + current
    else
      next_char = vars.text.current.charAt(progress.length)
      joiner    = if next_char is " " then " " else ""
      progress += joiner + word
      textBox.text current + joiner + word

    if textBox.node().getComputedTextLength() > lineWidth()
      textBox.text current
      textBox = newLine(word)
      if reverse then line-- else line++

  start = 1
  line  = null
  lines = null
  words = null
  wrap  = ->

    vars.container.value.selectAll("tspan").remove()
    vars.container.value.html ""
    words    = vars.text.words.slice(0)
    words.reverse() if reverse
    progress = words[0]
    textBox  = newLine words.shift(), true
    line = start

    for word in words

      if line * dy > vars.height.value
        truncate()
        break

      placeWord word

      unsafe = true
      while unsafe
        next_char = vars.text.current.charAt(progress.length + 1)
        unsafe = vars.text.split.value.indexOf(next_char) >= 0
        placeWord next_char if unsafe

    lines = Math.abs(line - start) + 1

  wrap()

  lines = line
  if vars.shape.value is "circle"
    space = vars.height.value - lines * dy
    if space > dy
{'fraction_non_alphanumeric': 0.16032811334824756, 'fraction_numerical': 0.008451404424558787, 'mean_word_length': 2.102158828064765, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6939727', 'n_tokens_mistral': 2652, 'n_tokens_neox': 2549, 'n_words': 678}