How to make a unicode emoji table in typst?

I want to see how many unicode emoji work fine with Typst and Firefox, but Rust main thread panicked at somewhere (2000, 3000):

#let unicode_printer(start, end) = {
  for i in range(start, end) [
    #str.from-unicode(i)]}

//#unicode_printer(0, 1999)  //fine
#unicode_printer(2000, 2999)  //not fine?  
//#unicode_printer(3000, 4999)  //fine

And the stack trace:

$ RUST_BACKTRACE=full typst c unicodeprinter.typ 
thread 'main' panicked at crates/typst-layout/src/inline/shaping.rs:896:51:
begin <= end (4 <= 0) when slicing ` ࣣ ࣤ`
stack backtrace:
   0:     0x7fb2888dd3aa - <unknown>
   1:     0x7fb288567b13 - <unknown>
   2:     0x7fb2888d8bd3 - <unknown>
...
  33:     0x7fb288b3de05 - <unknown>

That’s a bug that should be reported. (Edit: no need, it’s mentioned by mattf it’s fixed in development version of typst, which I also confirmed.)

If you draw them in boxes it seems to avoid the crash, in case you want to continue: for i in range(start, end) {box(stroke: 0.1pt, inset: 0.1em)[#str.from-unicode(i)]}

You can also loop over dictionary(emoji) to list all the top level emojis. Unfortunately I don’t think it’s possible to inspect which variant/subemojis each symbol has, so I can’t list them all (like emoji.airplane.landing etc).

2 Likes

For all code points, except those that raise error:

#for i in range(0xD800) + range(0xE000, 0x110000) {
  str.from-unicode(i)
  sym.zws
}

This took me 11.2 minutes.

Or what @bluss said:

#for ch in dictionary(emoji).values() {
  ch
  sym.zws
}
1 Like
  • Thank you a lot. In fact, the Rust thread issue will gone if change from [#str ] to {str }
  • I use a grid and set columns:16 to label the hex numbers later ( e.g. item:RedApple, row:1F34, col:E ):
#set text(blue)

#let unicode_printer(start, end) = {
	grid(columns: 16, gutter: 5pt,
		..range(start, end).map(str.from-unicode))}

#unicode_printer(9728, 10064)
//#unicode_printer(55296, 57344)  // invalid: (0xd800, 0xdfff)
#unicode_printer(61398, 62178)
#unicode_printer(127744, 129785)
  • Another question I totally don’t know: Why [typst-arm@phone][1] prints unicode emoji very different from typst-amd@computer?

[1]: I use android-termux to run typst-arm

You need to specify which font to use for these Unicode characters, because Typst compiler doesn’t have fonts that have these characters. There is typst fonts.

1 Like

Finally, all unicode-emoji with axis, only 7 pages (A4). The result snapshot and the code:

#set text(blue)

#let dec2hex(num) = {
	let digits = "0123456789abcdef"
	let hex = ""
	let rem = 0
	while true {
		rem = calc.rem(num, 16)
		hex = digits.at(rem) + hex
		num = calc.quo(num, 16)
		if num < 16 {
			hex = digits.at(num) + hex
			break}}
	return hex}

#let row_idx(start, end) = {
	let rowIdx = ()
	while start < end {
		rowIdx.push(dec2hex(start).slice(0,-1))
		start = start + 16}
	return rowIdx}

#let unicode_printer_no_axis(start, end) = {
	grid(columns: 16, gutter: 12pt, 
		..range(start, end).map(str.from-unicode))}

#let unicode_printer(start, end) = {
	let header = "0123456789abcdef".split("").slice(0,-1)
	
	let item = ()
	let rowIdx = 0
	let middle = start

	// special case: first line
	let itemEmpty = ()
	while dec2hex(middle).at(-1) != "0" {
		itemEmpty.push("")
		middle = middle -1}

	let leader = row_idx(middle, end)
	item.push(leader.at(rowIdx))
	
	if itemEmpty.len() > 0 {item.push(itemEmpty)}

	middle = middle + 16
	item.push(range(start, middle).map(str.from-unicode))
	// first row done

	while middle < end {
		rowIdx = rowIdx + 1
		start = middle
		middle = middle + 16

		item.push(leader.at(rowIdx))

		if middle >= end {middle = end}  // special case: last line
		item.push(range(start, middle).map(str.from-unicode))}

	grid(columns: 17, gutter: 12pt, 
		grid.header(..header),
		..item.flatten())}

#line(length:100%)
#unicode_printer(9728, 10064)  // 2600~274f
//invalid unicode (55296, 57344)  // (0xd800, 0xdfff)
#line(length:100%)
#unicode_printer(61398, 62177)  // efd6~f2e0
#line(length:100%)
#unicode_printer(127744, 129202)  // 1f300~1f8b1
#line(length:100%)
#unicode_printer(129280, 129785)  // 1f900~1faf8