Workout builder

Thanks for the great training platform and taking the time to write an API.
I am writing an indoor bike computer in micropython, running on a Waveshare 1.8" Knob Touch device - https://www.waveshare.com/wiki/ESP32-S3-Knob-Touch-LCD-1.8

I am investigating downloading workouts onto the device from intervals.icu. I have this working and the cookbook made it really very easy, so thanks for that - Downloading planned workouts from the API

But I have encountered some parsing errors of the workout descriptions that I don’t think are confined to the API. I.e. I can see these errors when viewing the workout on the web when hovering over the chart that is generated from the list of workout elements.

The errors I am seeing relate mainly to the description text that goes before the actual workout fields. To test my interpretation of the json returned by the API, I created a workout that contained most of the various options. Furthermore, I created all of these workout steps using the ‘Add Step’ dialog, rather than freehand. So if anything that I typed into a field was invalid, it could be picked up here. Here is my test workout:

Just for testing Intervals.ICU developer API.

5x
- 10s 500w
- 10s 100w
- Percentage of FTP 1m 50%
- Percentage of FTP Range 1m 45-55% 
- Zone 2 1m Z2
- Zone 2 to Zone 3 1m Z2-Z3
- 70% of Step Duration MMP 1m 70% MMP 1m
- 60% of 5m MMP 1m 60% MMP 5m
- 55 to 75% of step duration MMP 1m30 55-75% MMP
- 275 Watts 2m 275w
- 270 to 280 Watts 2m30 270-280w
- Percent of Max HR 1m 50% HR
- Percent of Max HR Range 1m 45-55% HR
- Percent of LTHR 1m 70% LTHR
- Percent of LTHR Range 1m 65-75% LTHR
- Zone 4 HR 1m Z4 HR
- Z2 to Z3 HR Range 1m Z2-Z3 HR
- 90RPM 1m 90rpm
- RPM Range 1m 85-95rpm
- Cooldown Ramp 5m ramp 250-150w

Here is my recreation of the workout description from the returned json data:

Just for testing Intervals.ICU developer API.

5x
- 10s 500w
- 10s 100w
- Percentage of FTP 1m 50%
- Percentage of FTP Range 1m 45-55%
- Zone 2 1m Z2
- Zone 2 to Zone 3 1m Z2-Z3
- 1m 70% MMP 1m
- 5m 60% MMP 5m
- 55 to 1m30 55-75% MMP
- 2m 275w
- 270 to 2m30 270-280w
- Percent of Max HR 1m 50% HR
- Percent of Max HR Range 1m 45-55% HR
- Percent of LTHR 1m 70% LTHR
- Percent of LTHR Range 1m 65-75% LTHR
- Zone 1m Z4 HR
- 1m Z2
- 90RPM 1m 1m 90rpm
- RPM Range 1m 85-95rpm
- Cooldown Ramp 5m ramp 250-150w

You can see that the description text is not the same. I first thought I was not parsing the json correctly. But here are the json workout steps…

    "workout_doc": {
      "steps": [
        {
          "reps": 5,
          "text": "5x",
          "steps": [
            {
              "power": {
                "units": "w",
                "value": 500
              },
              "duration": 10
            },
            {
              "power": {
                "units": "w",
                "value": 100
              },
              "duration": 10
            }
          ],
          "distance": 0,
          "duration": 100
        },
        {
          "text": "Percentage of FTP",
          "power": {
            "units": "%ftp",
            "value": 50
          },
          "duration": 60
        },
        {
          "text": "Percentage of FTP Range",
          "power": {
            "end": 55,
            "start": 45,
            "units": "%ftp"
          },
          "duration": 60
        },
        {
          "text": "Zone 2",
          "power": {
            "units": "power_zone",
            "value": 2
          },
          "duration": 60
        },
        {
          "text": "Zone 2 to Zone 3",
          "power": {
            "end": 3,
            "start": 2,
            "units": "power_zone"
          },
          "duration": 60
        },
        { ############# Text field missing altogether. Should read '70% of Step Duration MMP'
          "power": {
            "units": "%mmp",
            "value": 70,
            "mmp_duration": 60
          },
          "duration": 60
        },
        { ############# Text field missing altogether. Should read '60% of 5m MMP'
          "power": {
            "units": "%mmp",
            "value": 60,
            "mmp_duration": 300
          },
          "duration": 300
        },
        {
          "text": "55 to",   ######## Should read '55 to 75%'
          "power": {
            "end": 75,
            "start": 55,
            "units": "%mmp",
            "mmp_duration": null
          },
          "duration": 90
        },
        { ############# Text field missing altogether. Should read '275 Watts'
          "power": {
            "units": "w",
            "value": 275
          },
          "duration": 120
        },
        {
          "text": "270 to",   ################# Should read '270 to 280 Watts'
          "power": {
            "end": 280,
            "start": 270,
            "units": "w"
          },
          "duration": 150
        },
        {
          "hr": {
            "units": "%hr",
            "value": 50
          },
          "text": "Percent of Max HR",
          "duration": 60
        },
        {
          "hr": {
            "end": 55,
            "start": 45,
            "units": "%hr"
          },
          "text": "Percent of Max HR Range",
          "duration": 60
        },
        {
          "hr": {
            "units": "%lthr",
            "value": 70
          },
          "text": "Percent of LTHR",
          "duration": 60
        },
        {
          "hr": {
            "end": 75,
            "start": 65,
            "units": "%lthr"
          },
          "text": "Percent of LTHR Range",
          "duration": 60
        },
        {
          "hr": {
            "units": "hr_zone",
            "value": 4
          },
          "text": "Zone",    ########### Should read 'Zone 4 HR'
          "duration": 60
        },
        {   ###### Text field missing. Should read 'Z2 to Z3 HR Range'
          "hr": {
            "end": 3,
            "start": 2,
            "units": "hr_zone"
          },
          "power": { ############# This power section shouldn't be here at all
            "units": "power_zone",
            "value": 2
          },
          "duration": 60
        },
        {
          "text": "90RPM 1m",
          "cadence": {
            "units": "rpm",
            "value": 90
          },
          "duration": 60
        },
        {
          "text": "RPM Range",
          "cadence": {
            "end": 95,
            "start": 85,
            "units": "rpm"
          },
          "duration": 60
        },
        {
          "ramp": true,
          "text": "Cooldown Ramp",
          "power": {
            "end": 150,
            "start": 250,
            "units": "w"
          },
          "cooldown": true,
          "duration": 300,
          "intensity": "cooldown"
        }
      ],

Apologies if this is already covered. I scrolled all the way through the 684 replies and searched for all instances of ‘parse’, but didn’t see anything similar to this mentioned.

I am wondering if there is a way to quote the text within the description. This would be a sufficient workaround.
Or if this is intended behaviour, is there a list of characters that cannot be used within the text?
But I am inclined to say this is a bug, since I even (above) managed to create a workout step with both a power and a heart rate section.