text/emoji/detect.go

Functions Structs

Functions

func IsBlackFlag

IsBlackFlag returns true for the black flag emoji.

This is the base for subdivision flag sequences.

func IsBlackFlag(r rune) bool {
	return r == 0x1F3F4
}

func IsCancelTag

IsCancelTag returns true for the cancel tag character (U+E007F).

This terminates subdivision flag sequences.

func IsCancelTag(r rune) bool {
	return r == 0xE007F
}

func IsCombiningEnclosingKeycap

IsCombiningEnclosingKeycap returns true for the keycap combining mark.

func IsCombiningEnclosingKeycap(r rune) bool {
	return r == 0x20E3
}

func IsEmoji

IsEmoji returns true if the rune is an emoji character.

This includes characters with Emoji_Presentation=Yes or that are

commonly used as emoji with variation selector.

func IsEmoji(r rune) bool {
	return isEmojiPresentation(r) || isEmojiComponent(r) || isTextPresentationEmoji(r)
}

func IsEmojiModifier

IsEmojiModifier returns true if the rune is a skin tone modifier.

Fitzpatrick scale modifiers: U+1F3FB - U+1F3FF.

func IsEmojiModifier(r rune) bool {
	return r >= 0x1F3FB && r <= 0x1F3FF
}

func IsEmojiModifierBase

IsEmojiModifierBase returns true if the rune can be modified by a skin tone.

This includes humans, body parts, and human activities.

func IsEmojiModifierBase(r rune) bool {
	// Common emoji modifier bases
	switch {
	// People and body parts
	case r >= 0x1F466 && r <= 0x1F469:	// Boy, Girl, Man, Woman
		return true
	case r >= 0x1F46E && r <= 0x1F478:	// Police, Guard, etc.
		return true
	case r >= 0x1F47C && r <= 0x1F47C:	// Baby Angel
		return true
	case r >= 0x1F481 && r <= 0x1F487:	// Information Desk, etc.
		return true
	case r >= 0x1F4AA && r <= 0x1F4AA:	// Flexed Biceps
		return true
	case r >= 0x1F574 && r <= 0x1F575:	// Man in Suit, Detective
		return true
	case r >= 0x1F57A && r <= 0x1F57A:	// Man Dancing
		return true
	case r >= 0x1F590 && r <= 0x1F590:	// Hand with Fingers Splayed
		return true
	case r >= 0x1F595 && r <= 0x1F596:	// Middle Finger, Vulcan
		return true
	case r >= 0x1F645 && r <= 0x1F64F:	// Gestures and Person
		return true
	case r >= 0x1F6A3 && r <= 0x1F6A3:	// Rowing
		return true
	case r >= 0x1F6B4 && r <= 0x1F6B6:	// Cycling, Walking
		return true
	case r >= 0x1F6C0 && r <= 0x1F6C0:	// Bath
		return true
	case r >= 0x1F918 && r <= 0x1F91F:	// Hand signs
		return true
	case r >= 0x1F926 && r <= 0x1F926:	// Face Palm
		return true
	case r >= 0x1F930 && r <= 0x1F939:	// Pregnancy, etc.
		return true
	case r >= 0x1F93C && r <= 0x1F93E:	// Wrestling, etc.
		return true
	// Hands from dingbats range
	case r >= 0x261D && r <= 0x261D:	// Index Pointing Up
		return true
	case r >= 0x26F9 && r <= 0x26F9:	// Person Bouncing Ball
		return true
	case r >= 0x270A && r <= 0x270D:	// Fists, Writing Hand
		return true
	}
	return false
}

func IsEmojiPresentation

IsEmojiPresentation returns true if the rune defaults to emoji presentation.

These characters display as emoji without requiring U+FE0F.

func IsEmojiPresentation(r rune) bool {
	return isEmojiPresentation(r)
}

func IsEmojiVariation

IsEmojiVariation returns true for the emoji variation selector (U+FE0F).

func IsEmojiVariation(r rune) bool {
	return r == 0xFE0F
}

func IsKeycapBase

IsKeycapBase returns true if the rune can form a keycap emoji.

Digits 0-9, # and * can be followed by U+FE0F U+20E3 to form keycaps.

func IsKeycapBase(r rune) bool {
	return (r >= '0' && r <= '9') || r == '#' || r == '*'
}

func IsRegionalIndicator

IsRegionalIndicator returns true if the rune is a Regional Indicator (A-Z).

Two regional indicators form a flag emoji (e.g., U+1F1FA U+1F1F8 = US flag).

func IsRegionalIndicator(r rune) bool {
	return r >= 0x1F1E6 && r <= 0x1F1FF
}

func IsTagCharacter

IsTagCharacter returns true for emoji tag characters.

Tags U+E0020-U+E007E are used in subdivision flag sequences.

func IsTagCharacter(r rune) bool {
	return r >= 0xE0020 && r <= 0xE007E
}

func IsTextPresentation

IsTextPresentation returns true for the text variation selector (U+FE0E).

func IsTextPresentation(r rune) bool {
	return r == 0xFE0E
}

func IsVariationSelector

IsVariationSelector returns true for emoji-related variation selectors.

U+FE0E forces text presentation, U+FE0F forces emoji presentation.

func IsVariationSelector(r rune) bool {
	return r == 0xFE0E || r == 0xFE0F
}

func IsZWJ

IsZWJ returns true if the rune is Zero-Width Joiner (U+200D).

ZWJ is used to join emoji into composite sequences.

func IsZWJ(r rune) bool {
	return r == 0x200D
}

func Segment

Segment splits text into emoji and non-emoji runs.

ZWJ sequences and other multi-codepoint emoji are kept together.

Flag sequences (regional indicators) are combined.

Keycap sequences are combined.

Tag sequences are combined.

func Segment(text string) []Run {
	if text == "" {
		return nil
	}

	runes := []rune(text)
	if len(runes) == 0 {
		return nil
	}

	runs := make([]Run, 0, 4)
	byteOffsets := computeByteOffsets(text, runes)

	i := 0
	for i < len(runes) {
		// Try to parse a complete emoji sequence
		emojiLen, codepoints := parseEmojiSequence(runes[i:])

		if emojiLen > 0 {
			// Found an emoji sequence
			run := Run{
				Text:		text[byteOffsets[i]:byteOffsets[i+emojiLen]],
				IsEmoji:	true,
				Codepoints:	codepoints,
				Start:		byteOffsets[i],
				End:		byteOffsets[i+emojiLen],
			}
			runs = appendOrMergeRun(runs, run)
			i += emojiLen
		} else {
			// Regular text character
			run := Run{
				Text:		text[byteOffsets[i]:byteOffsets[i+1]],
				IsEmoji:	false,
				Start:		byteOffsets[i],
				End:		byteOffsets[i+1],
			}
			runs = appendOrMergeRun(runs, run)
			i++
		}
	}

	return runs
}

Structs

type Run struct

Run represents a contiguous run of text with uniform emoji status.

type Run struct {
	// Text is the substring of the run.
	Text	string

	// IsEmoji is true if this run contains emoji characters.
	// For ZWJ sequences, this will be a single Run with multiple codepoints.
	IsEmoji	bool

	// Codepoints contains the individual runes for emoji runs.
	// For non-emoji runs, this is nil.
	Codepoints	[]rune

	// Start is the byte offset in the original string.
	Start	int

	// End is the byte offset of the end (exclusive).
	End	int
}