ChordPro / chordpro

Reference implementation of the ChordPro standard for musical lead sheets.
Other
310 stars 51 forks source link

Handling missing {image} assets #398

Open gwyndaf opened 2 months ago

gwyndaf commented 2 months ago

This arises from the use case of #394 , but seems like a separate, more general issue and possible enhancement.

If the asset referenced by {image: id="myasset"} doesn't exist (hasn't been created), the error message is in PDF output (not standard error), and a feature to create dummy assets might help avoid such errors.

Scenario: I have several conditional {textblock-instrument: id="solotab"} directives, to create solo tab for some, but not all, fretted instruments. The relevant tab is then inserted with a simple {image: id="solotab"} line in the song body.

That works nicely for instruments where a {textblock} asset is defined. It also allows a {start_of_abc-keyboard: id="solotab"} asset for keyboard (although scaling challenges mean I need a separate {image-keyboard} to insert it).

However, for instruments where I'm not providing tab, so no "solotab" asset, I get an error message, which is - unusually - in the PDF output: Unhandled image type: asset=solotab.

The message seems perfectly correct, but it's odd to see it in the PDF. Maybe that's a temporary development/debug step to identify the missing asset's position.

I can work around it by creating a default solotab asset for 'other' instruments: either a trivial textblock with just a space, or a single white pixel PNG image, but both seem quite inelegant.

So, might a useful enhancement be the facility to create dummy assets? Maybe something like {image id="solotab" src=null}

It's maybe a niche case that wouldn't legitimately arise for a single instrument/user, but avoids issues arising from "insert asset here", where creating the asset is conditional, rather than inserting it.

sciurius commented 2 months ago

That is, indeed, something that could be handled better. I'll look into it.

Even if a message is written to stderr, should the {image} (or <img>) just be ignored?

In some situations, a message is written to stderr and an 'alert' image is inserted. E.g.

{image chord="Ax"}

In your specific use case I think what you're looking for is an image property to skip the {image} completely if the id is unknown. Do you still want a message in this case?

{image id="solotab" ifmissing="ignore"}
{image src="notexisting.jpg" ifmissing="warn"}

Personally I'd say that a missing image is another category of error than an undefined id.

gwyndaf commented 2 months ago

If there's no image or asset to insert, ignoring the directive/tag seems most flexible, but a stderr warning would retain some rigour. That way, accidental oversights can still be flagged.

It's an interesting idea to provide user control over the missing image/asset response, although perhaps that's more sensible as a config option than a directive parameter? It seems to shift the directive's focus away from "what's in the song / on the page" to "how the software behaves."

Fundamentally, though, it might be counter-productive, because a user can't necessarily predict the circumstances in which they need those responses. That is

1) Sometimes I make stupid mistakes and forget to define an asset, so a warning message is useful.

2) Sometimes I have complex conditional scenarios, so some assets are missing by design (as here) and I already know which are 'missing'. But that's my responsibility, hence the 'dummy asset' idea, so a valid id gets created (and messages avoided), but the asset is empty or trivial. Equally, though, I suppose the 'dummy asset' could simply signal that the inserting {image} directive should ignore it. The effect would be the same, but allows the user to think in terms of assets (real or dummy) on the page, rather than program control/flow.

I'm not sure whether those two correspond exactly to your 'missing image' and 'undefined id', but I agree it's useful to differentiate the two situations.

sciurius commented 2 months ago

There are two (related byt distinct) topics here.

First, what to do if the user refers to an image (via src or id) that does not exist for some reason. Typo in the filename, network error, or forgot to define the image with the given id. ChordPro should write a decent warning to standard error and include an alarm image to visually signal that something went wrong, and where.

Second is your sophisticated case of multiple conditional directives that may or may not lead to the definition of an image with a specified id. As you suggested, the easiest way to deal with this is by being able to define a dummy image. A very small (1x1px transparent image):

{image id="dummy" src="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=="}

This will result in a 1-pixel line advance for {image}, and in the case of <img>, a 1-pixel horizontal advance. A kind of 'special' image that will result in the{image}or` being skipped completely will be a bit harder to implement.

gwyndaf commented 2 months ago

Yes, I agree that for genuine 'error' cases a stderr message makes sense. Given that we're in 'page layout' rather than 'line-based' territory, I guess the alarm image is logical and promotes rigour.

Also, yes, my case is so niche I agree it's not worth significant development effort.

Thanks for the one-line GIF solution, which seems a bit more elegant than my trivial textblock. I'll try that out.