Skip to content

Add Script, Language, and Direction classes#205

Closed
khaledhosny wants to merge 3 commits into
mainfrom
script-language-direction
Closed

Add Script, Language, and Direction classes#205
khaledhosny wants to merge 3 commits into
mainfrom
script-language-direction

Conversation

@khaledhosny
Copy link
Copy Markdown
Contributor

Inspired by Feature class introduce in #204, but I’m not sure if it is an overall improvement. It seemed nice in my head, but after doing it things feel a bit verbose.

Leaving it here for others more familiar with JS to voice their opinion.

@khaledhosny khaledhosny force-pushed the script-language-direction branch from b67d05b to 56d895d Compare May 6, 2026 23:47
@lianghai
Copy link
Copy Markdown

lianghai commented May 7, 2026

Quick comment after a brief look: hb_feature_t is a struct with multiple fields therefore it’s helpful to represent it as a class, but these all seem to only provide a validation layer (not even for Language)?

@khaledhosny
Copy link
Copy Markdown
Contributor Author

I hade code like if (dir == "rtl") return Direction.LTR and I thought wouldn’t it be nice if we had Direction("rtl") that uses hb_direction_from_string, and things escalated from there.

@lianghai
Copy link
Copy Markdown

lianghai commented May 7, 2026

Got to have another look:

  • The Language class doesn’t seem to be useful, since it still takes an arbitrary string, while the actual parsing and validation (?) happens inside hb_language_from_string().
  • For hb_script_t, if the intention is only to improve type safety, it can be implemented as a simple union type of string literals: type Script = "Zyyy" | "Zinh" | .... Those human-readable symbols (COMMON, …) don’t seem very useful. May as well just link to https://unicode.org/iso15924/iso15924-codes.html or HB’s source code in type Script’s documentation.

I hade code like if (dir == "rtl") return Direction.LTR and I thought wouldn’t it be nice if we had Direction("rtl") that uses hb_direction_from_string, and things escalated from there.

Oh I thought there’s already type Direction? I can’t find if (dir == "rtl") anywhere.

@khaledhosny
Copy link
Copy Markdown
Contributor Author

khaledhosny commented May 7, 2026

Got to have another look:

  • The Language class doesn’t seem to be useful, since it still takes an arbitrary string, while the actual parsing and validation (?) happens inside hb_language_from_string().

It basically wraps hb_language_from_string() and hb_language_to_string(), yes.

  • For hb_script_t, if the intention is only to improve type safety, it can be implemented as a simple union type of string literals: type Script = "Zyyy" | "Zinh" | .... Those human-readable symbols (COMMON, …) don’t seem very useful. May as well just link to https://unicode.org/iso15924/iso15924-codes.html or HB’s source code in type Script’s documentation.

I like HarfBuzz names, and find Script.ARABIC etc. easier to remember that Arab (OK, I know this one but I don’t know the exact tag for many other scripts).

I hade code like if (dir == "rtl") return Direction.LTR and I thought wouldn’t it be nice if we had Direction("rtl") that uses hb_direction_from_string, and things escalated from there.

Oh I thought there’s already type Direction? I can’t find if (dir == "rtl") anywhere.

We have Direction enum yes, but we don’t bind hb_direction_from_string(). That if check is in my own code not harfbuzzjs.

@lianghai
Copy link
Copy Markdown

lianghai commented May 7, 2026

We have Direction enum yes, but we don’t bind hb_direction_from_string(). That if check is in my own code not harfbuzzjs.

Ah I see, hb_direction_t and hb_script_t are enums (thus integers) that also have a string serialization, which makes them sit in between simple enums (no strings) and complicated structs like hb_feature_t and hb_variation_t (parsable from strings, but there’s no enum integers). A middle ground is that you could hide the not so useful low-level enum integers from users of this project, so both hb_direction_t and hb_script_t are bridged as something like:

export const Direction = {
  LTR: "ltr",
  RTL: "rtl",
  ...
} as const;
export type Direction = ValueOf<typeof Direction>;

Then you convert type Direction with hb_direction_from_string().

This exposes the most useful variants of these values (the strings one can simply input and get type checked, as well as the readable symbols like Script.ARABIC you prefer) to users.

@khaledhosny
Copy link
Copy Markdown
Contributor Author

Lets close this then, since no one complained about the status co. If we ever need to do something similar, I think we can still do it in backwards-compatible way.

@khaledhosny khaledhosny closed this May 8, 2026
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.

2 participants