britzl / defold-richtext

Defold-RichText is a system to create styled text based on an HTML inspired markup language
MIT License
75 stars 12 forks source link

is_empty tags improperly being added to preceding words since 5.8.0 #57

Closed subsoap closed 4 years ago

subsoap commented 4 years ago

If I do

local last_word = richtext.truncate(words, length, {words = false})

then

pprint(last_word.tags)

for the text

text...,,,,,,,,,,,,,,,,,,,,,,,,,,,,<br/>

I will get

DEBUG:SCRIPT: 
{ --[[0000019E1A974C90]]
  br = true
}
DEBUG:SCRIPT: 
{ --[[0000019E1A974C90]]
  br = true
}
DEBUG:SCRIPT: 
{ --[[0000019E1A974C90]]
  br = true
}
etc.

Same is true for other is_empty like

subsoap commented 4 years ago

RichTextTruncateBug.zip

Reproduction project

local richtext = require("richtext.richtext")

function init(self)
    local text = "This is a test <br/>"
    local settings = {
        parent = gui.get_node("root"),
    }

    local words, metrics = richtext.create(text, "font", settings)
    local last_word = richtext.truncate(words, 1, {words = false})
    pprint(last_word)
end
DEBUG:SCRIPT: 
{ --[[0000029E3235E980]]
  outline = vmath.vector4(0, 0, 0, 0),
  size = 1,
  color = vmath.vector4(1, 1, 1, 1),
  metrics = { --[[0000029E32361010]]
    width = 9,
    max_descent = 4,
    max_ascent = 13,
    height = 17,
    total_width = 17
  },
  text = "This ",
  tags = { --[[0000029E3235E610]]
    br = true
  },
  node = T@(0, 0, 0),
  font = "font",
  shadow = vmath.vector4(0, 0, 0, 0)
}
subsoap commented 4 years ago

It's not actually a problem with truncate, the words themselves are getting the wrong tags with richtext.create() when there are is_empty tags present before the words.

subsoap commented 4 years ago

The issue appeared within the release https://github.com/britzl/defold-richtext/releases/tag/5.8.0 previous versions to that do not appear to incorrectly add is_empty tags to words where they do not belong.

subsoap commented 4 years ago

If there are any other open/close tags like "Hello <b>this</b> is<br/>" the words before and including the <b></b> do not improperly get the <br/> tag in their list of tags, but in this case the "is" would get the improper tag.

subsoap commented 4 years ago

I think the problem line is

dst.tags[tag] = (params == "") and true or params

but at the moment I don't understand why.

subsoap commented 4 years ago

The settings in split_text needs to be deep copied I think?

This seems to fix it to avoid adding is_empty tags improperly on a simple test. But I don't know if you rely on this behavior for the nested tags to work right. I also still don't fully understand why it was breaking in the first place.

local function split_text(text, settings, words)
    assert(text)
    assert(settings)
    assert(words)

    settings = deepcopy(settings)