RichTextUtilities - A user-friendly RichText module so you don't have to

A user-friendly RichText module to help assist with RichText formatting using functions so you don’t have to memorize the formatting.

I’m releasing this early as a part of my future utilities package because for some reason I cant find anyone who has made this yet.

It’s free and fully strictly typed.


RichTextUtilities.lua
--!strict

--[=[
	local RichTextUtilities = require(script.RichTextUtilities)
	
	local tag = RichTextUtilities.tag
	local fontToFaceFormat = RichTextUtilities.fontToFaceFormat
	local fontToFamilyFormat = RichTextUtilities.fontToFamilyFormat
	local colorToRgbFormat = RichTextUtilities.colorToRgbFormat
	local colorToHexFormat = RichTextUtilities.colorToHexFormat

	local font = RichTextUtilities.font
	local fontFunction = RichTextUtilities.fontFunction
	local fontFace = RichTextUtilities.fontFace
	local fontFamily = RichTextUtilities.fontFamily
	local fontWeight = RichTextUtilities.fontWeight
	local fontColor = RichTextUtilities.fontColor
	local fontSize = RichTextUtilities.fontSize
	local fontTransparency = RichTextUtilities.fontTransparency

	local stroke = RichTextUtilities.stroke
	local strokeFunction = RichTextUtilities.strokeFunction
	local strokeColor = RichTextUtilities.strokeColor
	local strokeThickness = RichTextUtilities.strokeThickness
	local strokeTransparency = RichTextUtilities.strokeTransparency
	local strokeJoins = RichTextUtilities.strokeJoins

	local bold = RichTextUtilities.bold
	local italic = RichTextUtilities.italic
	local underline = RichTextUtilities.underline
	local strikethrough = RichTextUtilities.strikethrough
	local uppercase = RichTextUtilities.uppercase
	local smallcaps = RichTextUtilities.smallcaps
	local comment = RichTextUtilities.comment
	local linebreak = RichTextUtilities.linebreak
]=]

local RichTextUtilities = {}
local MappedFontEnumToFamily: {[Enum.Font]: string} = {}

do
	pcall(function(): ()
		for _: number, fontEnum: Enum.Font in Enum.Font:GetEnumItems() do
			local font: Font = Font.fromEnum(fontEnum)
			MappedFontEnumToFamily[fontEnum] = font.Family
		end
	end)
end

function RichTextUtilities.fontToFaceFormat(font: Enum.Font): string
	return if font ~= Enum.Font.Unknown then font.Name else Enum.Font.BuilderSans.Name
end

function RichTextUtilities.fontToFamilyFormat(font: Enum.Font): string
	return MappedFontEnumToFamily[font] or MappedFontEnumToFamily[Enum.Font.BuilderSans]
end

function RichTextUtilities.colorToRgbFormat(color: Color3): string
	return `rgb({math.round(color.R * 255)}, {math.round(color.G * 255)}, {math.round(color.B * 255)})`
end

function RichTextUtilities.colorToHexFormat(color: Color3): string
	return `#{color:ToHex()}`
end

function RichTextUtilities.tag(text: string, tag: string, attributes: {[string]: string | number}?): string
	local attributesString: string = ``
	
	if attributes ~= nil then
		for attribute: string, value: string | number in attributes do
			attributesString = `{attributesString} {attribute}="{value}"`
		end
	end
	
	return `<{tag}{attributesString}>{text}</{tag}>`
end

local function generateFontAttributes(font: Enum.Font?, weight: Enum.FontWeight?, color: Color3?, size: number?, transparency: number?, fontUsesFamily: boolean?, colorUsesHex: boolean?): {[string]: string | number}?
	local fontAttributes: {[string]: string | number} = {}

	if font ~= nil then
		fontAttributes[if fontUsesFamily == true then `family` else `face`] = if fontUsesFamily == true then RichTextUtilities.fontToFamilyFormat(font) else RichTextUtilities.fontToFaceFormat(font)
	end

	if weight ~= nil then
		fontAttributes[`weight`] = weight.Value
	end

	if color ~= nil then
		fontAttributes[`color`] = if colorUsesHex == true then RichTextUtilities.colorToHexFormat(color) else RichTextUtilities.colorToRgbFormat(color)
	end

	if size ~= nil then
		fontAttributes[`size`] = size
	end

	if transparency ~= nil then
		fontAttributes[`transparency`] = transparency
	end
	
	return if next(fontAttributes) ~= nil then fontAttributes else nil
end

function RichTextUtilities.font(text: string, font: Enum.Font?, weight: Enum.FontWeight?, color: Color3?, size: number?, transparency: number?, fontUsesFamily: boolean?, colorUsesHex: boolean?): string
	return RichTextUtilities.tag(text, `font`, generateFontAttributes(font, weight, color, size, transparency, fontUsesFamily, colorUsesHex))
end

function RichTextUtilities.fontFunction(font: Enum.Font?, weight: Enum.FontWeight?, color: Color3?, size: number?, transparency: number?, fontUsesFamily: boolean?, colorUsesHex: boolean?): (text: string) -> string
	local fontAttributes: {[string]: string | number}? = generateFontAttributes(font, weight, color, size, transparency, fontUsesFamily, colorUsesHex)
	
	return function(text: string): string
		return RichTextUtilities.tag(text, `font`, fontAttributes)
	end
end

function RichTextUtilities.fontFace(text: string, face: Enum.Font): string
	return RichTextUtilities.font(text, face, nil, nil, nil, nil, nil, nil)
end

function RichTextUtilities.fontFamily(text: string, family: Enum.Font): string
	return RichTextUtilities.font(text, family, nil, nil, nil, nil, true, nil)
end

function RichTextUtilities.fontWeight(text: string, weight: Enum.FontWeight): string
	return RichTextUtilities.font(text, nil, weight, nil, nil, nil, true, nil)
end

function RichTextUtilities.fontColor(text: string, color: Color3, colorUsesHex: boolean?): string
	return RichTextUtilities.font(text, nil, nil, color, nil, nil, nil, colorUsesHex)
end

function RichTextUtilities.fontSize(text: string, size: number): string
	return RichTextUtilities.font(text, nil, nil, nil, size, nil, nil, nil)
end

function RichTextUtilities.fontTransparency(text: string, transparency: number): string
	return RichTextUtilities.font(text, nil, nil, nil, nil, transparency, nil, nil)
end

local function generateStrokeAttributes(color: Color3?, thickness: number?, transparency: number?, joins: Enum.LineJoinMode?, colorUsesHex: boolean?): {[string]: string | number}?
	local strokeAttributes: {[string]: string | number} = {}

	if color ~= nil then
		strokeAttributes[`color`] = if colorUsesHex == true then RichTextUtilities.colorToHexFormat(color) else RichTextUtilities.colorToRgbFormat(color)
	end

	if thickness ~= nil then
		strokeAttributes[`thickness`] = thickness
	end

	if joins ~= nil then
		strokeAttributes[`joins`] = string.lower(joins.Name)
	end

	return if next(strokeAttributes) ~= nil then strokeAttributes else nil
end

function RichTextUtilities.stroke(text: string, color: Color3?, thickness: number?, transparency: number?, joins: Enum.LineJoinMode?, colorUsesHex: boolean?): string
	return RichTextUtilities.tag(text, `stroke`, generateStrokeAttributes(color, thickness, transparency, joins, colorUsesHex))
end

function RichTextUtilities.strokeFunction(color: Color3?, thickness: number?, transparency: number?, joins: Enum.LineJoinMode?, colorUsesHex: boolean?): (text: string) -> string
	local strokeAttributes: {[string]: string | number}? = generateStrokeAttributes(color, thickness, transparency, joins, colorUsesHex)
	
	return function(text: string): string
		return RichTextUtilities.tag(text, `stroke`, strokeAttributes)
	end
end

function RichTextUtilities.strokeColor(text: string, color: Color3, colorUsesHex: boolean?): string
	return RichTextUtilities.stroke(text, color, nil, nil, nil, colorUsesHex)
end

function RichTextUtilities.strokeThickness(text: string, thickness: number): string
	return RichTextUtilities.stroke(text, nil, thickness, nil, nil, nil)
end

function RichTextUtilities.strokeTransparency(text: string, transparency: number): string
	return RichTextUtilities.stroke(text, nil, nil, transparency, nil, nil)
end

function RichTextUtilities.strokeJoins(text: string, joins: Enum.LineJoinMode): string
	return RichTextUtilities.stroke(text, nil, nil, nil, joins, nil)
end

function RichTextUtilities.bold(text: string): string
	return RichTextUtilities.tag(text, `b`)
end

function RichTextUtilities.italic(text: string): string
	return RichTextUtilities.tag(text, `i`)
end

function RichTextUtilities.underline(text: string): string
	return RichTextUtilities.tag(text, `u`)
end

function RichTextUtilities.strikethrough(text: string): string
	return RichTextUtilities.tag(text, `s`)
end

function RichTextUtilities.uppercase(text: string, useLongFormat: boolean?): string
	return RichTextUtilities.tag(text, if useLongFormat == nil or useLongFormat == false then `uc` else `uppercase`)
end

function RichTextUtilities.smallcaps(text: string, useLongFormat: boolean?): string
	return RichTextUtilities.tag(text, if useLongFormat == nil or useLongFormat == false then `sc` else `smallcaps`)
end

function RichTextUtilities.comment(text: string): string
	return `<!--{text}-->`
end

function RichTextUtilities.linebreak(): string
	return `<br />`
end

return table.freeze(RichTextUtilities)
Usage and Examples
--!strict

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RichTextUtilities = require(ReplicatedStorage.RichTextUtilities)

local tag = RichTextUtilities.tag
local fontToFaceFormat = RichTextUtilities.fontToFaceFormat
local fontToFamilyFormat = RichTextUtilities.fontToFamilyFormat
local colorToRgbFormat = RichTextUtilities.colorToRgbFormat
local colorToHexFormat = RichTextUtilities.colorToHexFormat

local font = RichTextUtilities.font
local fontFunction = RichTextUtilities.fontFunction
local fontFace = RichTextUtilities.fontFace
local fontFamily = RichTextUtilities.fontFamily
local fontWeight = RichTextUtilities.fontWeight
local fontColor = RichTextUtilities.fontColor
local fontSize = RichTextUtilities.fontSize
local fontTransparency = RichTextUtilities.fontTransparency

local stroke = RichTextUtilities.stroke
local strokeFunction = RichTextUtilities.strokeFunction
local strokeColor = RichTextUtilities.strokeColor
local strokeThickness = RichTextUtilities.strokeThickness
local strokeTransparency = RichTextUtilities.strokeTransparency
local strokeJoins = RichTextUtilities.strokeJoins

local bold = RichTextUtilities.bold
local italic = RichTextUtilities.italic
local underline = RichTextUtilities.underline
local strikethrough = RichTextUtilities.strikethrough
local uppercase = RichTextUtilities.uppercase
local smallcaps = RichTextUtilities.smallcaps
local comment = RichTextUtilities.comment
local linebreak = RichTextUtilities.linebreak

--[=[ tag(text: string, tag: string, attributes: {[string]: string | number}?): string ]=]
print(tag(`Hello, World!`, `stroke`, {
	color = colorToRgbFormat(Color3.fromRGB(85, 255, 0)),
	thickness = 1,
	transparency = 0.5,
	joins = string.lower(Enum.LineJoinMode.Round.Name)
}))
-- <stroke thickness="1" transparency="0.5" joins="round">Hello, World!</stroke>

--[=[ fontToFaceFormat(font: Enum.Font): string ]=]
print(fontToFaceFormat(Enum.Font.Fantasy))
-- Fantasy

--[=[ fontToFaceFormat(font: Enum.Font): string ]=]
print(fontToFamilyFormat(Enum.Font.GothamBlack))
-- rbxasset://fonts/families/GothamSSm.json

--[=[ colorToRgbFormat(color: Color3): string ]=]
print(colorToRgbFormat(Color3.fromRGB(85, 255, 0)))
-- rgb(85, 255, 0)

--[=[ font(text: string, font: Enum.Font?, weight: Enum.FontWeight?, color: Color3?, size: number?, transparency: number?, fontUsesFamily: boolean?, colorUsesHex: boolean?): string ]=]
print(font(`Welcome traveller. Would you like to view my wares?`, Enum.Font.Fantasy, Enum.FontWeight.Thin, nil, nil, nil, true, true))
-- <font family="rbxasset://fonts/families/Balthazar.json" weight="100">Welcome traveller. Would you like to view my wares?</font>

--[=[ fontFunction(font: Enum.Font?, weight: Enum.FontWeight?, color: Color3?, size: number?, transparency: number?, fontUsesFamily: boolean?, colorUsesHex: boolean?): (text: string) -> string ]=]
local shoutFormat: (text: string) -> string = fontFunction(nil, Enum.FontWeight.Heavy, Color3.new(1, 0, 0))
print(shoutFormat(`You dare stumble upon my territory!?`))
-- <font color="rgb(255, 0, 0)" weight="900">You dare stumble upon my territory!?</font>

--[=[ fontFace(text: string, font: Enum.Font): string ]=]
print(fontFace(`Hello, World!`, Enum.Font.Code))
-- <font face="Code">Hello, World!</font>

--[=[ fontFamily(text: string, font: Enum.Font): string ]=]
print(fontFamily(`Hello, World!`, Enum.Font.Code))
-- <font family="rbxasset://fonts/families/Inconsolata.json">Hello, World!</font>

--[=[ fontWeight(text: string, weight: Enum.FontWeight): string ]=]
print(fontWeight(`Hello, World!`, Enum.FontWeight.Regular))
-- <font weight="400">Hello, World!</font>

--[=[ fontColor(text: string, color: Color3, colorUsesHex: boolean?): string ]=]
print(fontColor(`Hello, World!`, Color3.new(1, 0, 1), true))
-- <font color="#ff00ff">Hello, World!</font>

--[=[ fontSize(text: string, size: number): string ]=]
print(fontSize(`Hello, World!`, 24))
-- <font size="24">Hello, World!</font>

--[=[ fontTransparency(text: string, transparency: number): string ]=]
print(fontTransparency(`Hello, World!`, 0.2))
-- <font transparency="0.2">Hello, World!</font>

--[=[ stroke(text: string, color: Color3?, thickness: number?, transparency: number?, joins: Enum.LineJoinMode?, colorUsesHex: boolean?): string ]=]
print(stroke(`This sentence is purple outlined!`, Color3.fromRGB(170, 85, 255), 2, nil, Enum.LineJoinMode.Round))
-- <stroke thickness="2" joins="round" color="rgb(170, 85, 255)">This sentence is purple outlined!</stroke>

--[=[ strokeFunction(color: Color3?, thickness: number?, transparency: number?, joins: Enum.LineJoinMode?, colorUsesHex: boolean?): (text: string) -> string ]=]
local currencyStrokeFormat: (text: string) -> string = strokeFunction(Color3.fromRGB(255, 255, 0), 2, 0.5)
print(currencyStrokeFormat(`$900,000,000`))
--  <stroke color="rgb(255, 255, 0)" thickness="2">$900,000,000</stroke>

--[=[ strokeColor(text: string, color: Color3, colorUsesHex: boolean?): string ]=]
print(strokeColor(`Hello, World!`, Color3.new(0, 0, 0), true))
-- <stroke color="#000000">Hello, World!</stroke>

--[=[ strokeThickness(text: string, thickness: number): string ]=]
print(strokeThickness(`Hello, World!`, 1.5))
-- <stroke thickness="1.5">Hello, World!</stroke>

--[=[ strokeTransparency(text: string, transparency: number): string ]=]
print(strokeThickness(`Hello, World!`, 0.2))
-- <stroke transparency="0.2">Hello, World!</stroke>

--[=[ strokeJoins(text: string, joins: Enum.LineJoinMode): string ]=]
print(strokeJoins(`Hello, World!`, Enum.LineJoinMode.Bevel))
-- <stroke joins="bevel">Hello, World!</stroke>

--[=[ bold(text: string): string ]=]
print(bold(`Hello, World!`))
-- <b>Hello, World!</b>

--[=[ italic(text: string): string ]=]
print(italic(`Hello, World!`))
-- <i>Hello, World!</i>

--[=[ underline(text: string): string ]=]
print(underline(`Hello, World!`))
-- <u>Hello, World!</u>

--[=[ strikethrough(text: string): string ]=]
print(strikethrough(`Hello, World!`))
-- <s>Hello, World!</s>

--[=[ uppercase(text: string, useLongFormat: boolean?): string ]=]
print(uppercase(`Hello, World!`))
-- <uc>Hello, World!</uc>

--[=[ smallcaps(text: string, useLongFormat: boolean?): string ]=]
print(smallcaps(`Hello, World!`, true))
-- <smallcaps>Hello, World!</smallcaps>

--[=[ comment(text: string): string ]=]
print(comment(`This will not be visible in a TextLabel with RichText enabled.`))
-- <!--This will not be visible in a TextLabel with RichText enabled.-->

--[=[ linebreak(): string ]=]
print(linebreak())
-- <br />
4 Likes

I love it!

This text will be blurred