Skip to content

Adds foundation for rich text feature with styleRanges approach #354

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

phinity
Copy link

@phinity phinity commented Mar 8, 2025

Adds feature for Rich Text using styleRanges API

Example

'This is a Rich Text example with bold and italic text in Caxton font family. Font fallbacks still work 😃'
styleRanges = {
          10: { length: 9, font: '/font/BoldItalic.woff' },
          33: { length: 4, font: '/font/Bold.woff' },
          42: { length: 6, font: '/font/Italic.woff' }
}
  • Currently supports color and font properties
  • optional length property should return to previous style for each supported property
  • Updated TextExample with "Rich Text" option

Also addressed:

  • Fixed 'undefined' string bug
  • Fixed start color issue when using ColorRange (0 to first non-zero range is black)

TODOs noted

Addresses Issues:
#278
#65

Screenshot 2025-03-07 at 4 28 33 PM

@lojjic
Copy link
Collaborator

lojjic commented Mar 8, 2025

🤩🤩🤩 Amazing! I look forward to reviewing this soon!

@phinity
Copy link
Author

phinity commented Mar 10, 2025

Resolved issues with the example and some other cleanup. The example is looking proper now:
Screenshot 2025-03-09 at 11 58 08 PM

@Utopiah
Copy link

Utopiah commented Mar 17, 2025

Thanks, could be exactly what's needed for lojjic/aframe-troika-text#85 and more!

@phinity
Copy link
Author

phinity commented Mar 19, 2025

Utopiah

Based on the discussion that prompted this update, Yes, this PR is just move towards true rich text with a markdown or HTM type syntax. #334

@lojjic
Copy link
Collaborator

lojjic commented Apr 1, 2025

Aploogies for the delay on this, I haven't forgotten about it but haven't found time to dig in yet. Soon, I hope. 🙂

@phinity
Copy link
Author

phinity commented Apr 8, 2025

Aploogies for the delay on this, I haven't forgotten about it but haven't found time to dig in yet. Soon, I hope. 🙂

Hey thanks, looking forward to it being merged whenever you have time for a proper review. I don't want to rely on a fork in the long run! I may add a minor cleanup commit but all the logic has been working good for my use cases.

One consideration about this update is the length property — is that something we could expect to support for all other properties added in the future or should it be axed now? Are we okay with the extra let vars to support that from a performance pov? I tested not using it and relying on users defining the reset values. It's much more verbose of an api and puts the weight on the applications' logic. It's a handy feature to solve once!

I was considering how to get styleRanges[].fontSize working and it may be tricky because it seems the font dimensions may be calculated only only once for each character. Seems the area may be in TextBuilder around line 270. I think it would need to be re calculated or kept in memory with fontGlyphMaps. just considering how that feature would work with this API since fontSize is the next most useful property to support.

@lojjic
Copy link
Collaborator

lojjic commented Apr 24, 2025

Apologies again for the delay!

One consideration about this update is the length property — is that something we could expect to support for all other properties added in the future or should it be axed now?

I do think we should remove it. My main concern is that it introduces ambiguity where the .length may exceed the distance to the next style diff index, and resolving those conflicts would add complexity especially as we add more style properties. And we'll need to be evaluating these style diffs in at least three places (font resolution, font size metrics when typesetting, and visual shader styling) so I'd rather keep this format as simple as possible.

Of course pure diffs are more verbose and harder to write as a user, but I'm increasingly thinking users shouldn't ever be writing them -- we'd expose and document it but only as a hook for other tools. I've already prototyped a simple htm binding to produce the indexed diff format that I think would work nicely as the default user-facing API.

Would you mind adjusting this PR to remove .length? I think we'll be looking good as a starting point then. Thanks again!

@phinity
Copy link
Author

phinity commented Apr 25, 2025

Okay, i agree, length does add some complexity that can be handled better at a higher level and more reliably parse those style diff edge cases. And yea styleRanges was just intended as a hook for other tools. There honestly isn't that much that needs to be removed, see latest commit. The example api changes to this:

'This is a Rich Text example with Bold and Italic text in Caxton font family. Font fallbacks still work! 😃'
        styleRanges = {
          0: { color: 0x775500, font: FONTS['Caxton'] },

          10: { color: 0x997700, font: FONTS['Caxton Bold Italic'] },
          19: { color: 0x775500, font: FONTS['Caxton'] },

          33: { font: FONTS['Caxton Bold'] },
          37: { font: FONTS['Caxton'] },

          42: { font: FONTS['Caxton Italic'] },
          48: { font: FONTS['Caxton'] },

          104: { color: 0x997700 },
          105: { color: 0x775500 },
        }

@phinity
Copy link
Author

phinity commented Apr 26, 2025

@lojjic I am thinking about the higher level syntax; I'd love get an idea of the API for your POC if you are willing to share an example? would it parse html like: <span class="style1">bold text</span≥? I don't want to make assumptions of your prototype but I'll say a template literal is a an interesting way to parse the rich text feature. I'm not sure if HTM goes too far with full jsx like parsing using "html``"? Just spitballing, a tag template limited to text formatting may be more appropriate? I really like markdown, so i'd love: "md`**bold text**`" with sensible defaults and customizable like styles={bold:{font:'bold.ttf'} }, or something super simple just to define ranges for generic styles which is more flexible, like"rt`%style1%bold text%%`" styles={style1:{font:'bold.ttf'}} - inspired by wikistyles. Or both simply by allowing custom definitions of tagged templates that basically return a format to generate styleRanges and other font props.

@phinity
Copy link
Author

phinity commented May 3, 2025

Added small update to return to the default color and font with styleRanges using a 'false' value. Thought is any other styleRanges keys added could optionally follow this approach to returning a range to the default value, but not required that they do like the previous 'length' prop approach. This way the example can retain the colorCycle animation.

      newState.styleRanges = {
          10: { font: FONTS['Caxton Bold Italic'] },
          19: { font: false },

          33: { color: 0x997700, font: FONTS['Caxton Bold'] },
          37: { color: false, font: false },

          42: { color: 0x997700, font: FONTS['Caxton Italic'] },
          48: { color: false, font: false },

          104: { color: 0x997700 },
          105: { color: false },
      }

Screenshot 2025-05-03 at 1 04 46 AM

@iv-rid
Copy link

iv-rid commented May 19, 2025

Could it be possible to add inline images to the text with this feature?

@phinity
Copy link
Author

phinity commented May 21, 2025

Could it be possible to add inline images to the text with this feature?

IDK about full color images but a custom icon font could render single color vector images inline

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants