--[[
    Used to build the rbxts version.
]]

--!strict
local fs = require("@lune/fs")

local SRC_PATH = "./src"
local OUT_PATH = "./rbxts/src"
local INCLUDE_PATH = `./rbxts/include`
local OTHER_INCLUDED_PATHS = {
    "LICENSE.md",
    "default.project.json"
}

if fs.isDir(OUT_PATH) then fs.removeDir(OUT_PATH) end
fs.writeDir(OUT_PATH)

local function CopyDirContentsRecursiveMain(cloneFromPath: string, cloneToPath: string)
    local cloneFromDir = fs.readDir(cloneFromPath)

    for _, entryPath in cloneFromDir do
        local fullEntryPath = `{cloneFromPath}/{entryPath}`
        local cloneToFullEntryPath = `{cloneToPath}/{entryPath}`

        if fs.isDir(fullEntryPath) then
            fs.writeDir(cloneToFullEntryPath)
            CopyDirContentsRecursiveMain(fullEntryPath, cloneToFullEntryPath)

        else
            fs.writeFile(cloneToFullEntryPath, fs.readFile(fullEntryPath))
        end
    end
end

-- this function exists because `fs.copy` overwrites everything instead of just the conflicts.
local function CopyDirContentsRecursive(cloneFromPath: string, cloneToPath: string)
    if not fs.isDir(cloneFromPath) then
        print(`Skipping "{cloneFromPath}": Not a valid directory!`)
        return
    end

    if not fs.isDir(cloneToPath) then fs.writeDir(cloneToPath) end

    return CopyDirContentsRecursiveMain(cloneFromPath, cloneToPath)
end

CopyDirContentsRecursive(SRC_PATH, OUT_PATH)
CopyDirContentsRecursive(INCLUDE_PATH, OUT_PATH)
for _, path in OTHER_INCLUDED_PATHS do
    fs.copy(path, `{OUT_PATH}/../{path}`, true)
end


--!strict
--!optimize 2

local LexRsml = require(script.Lexer)
local ParseRsml = require(script.Parser)
local ConvertRsml = require(script.Converter)

local DefaultStyles = require(script.DefaultStyles)

local function Rsml(content: string, derives: { StyleSheet }?)
    -- If the content is a `TemplateStringsArray`.
    if type(content) == "table" then content = content[1] :: string end

    return ConvertRsml(ParseRsml(LexRsml(content)), derives, DefaultStyles)
end

return {
    rsml = Rsml,
    parseRsml = ParseRsml,
    lexRsml = LexRsml
}


return {
	["bc:white"] = Color3.fromRGB(242, 243, 243),
	["bc:grey"] = Color3.fromRGB(161, 165, 162),
	["bc:lightyellow"] = Color3.fromRGB(249, 233, 153),
	["bc:brickyellow"] = Color3.fromRGB(215, 197, 154),
	["bc:lightgreen"] = Color3.fromRGB(194, 218, 184),
	["bc:lightreddishviolet"] = Color3.fromRGB(232, 186, 200),
	["bc:pastelblue"] = Color3.fromRGB(128, 187, 219),
	["bc:lightorangebrown"] = Color3.fromRGB(203, 132, 66),
	["bc:nougat"] = Color3.fromRGB(204, 142, 105),
	["bc:brightred"] = Color3.fromRGB(196, 40, 28),
	["bc:medreddishviolet"] = Color3.fromRGB(196, 112, 160),
	["bc:brightblue"] = Color3.fromRGB(13, 105, 172),
	["bc:brightyellow"] = Color3.fromRGB(245, 205, 48),
	["bc:earthorange"] = Color3.fromRGB(98, 71, 50),
	["bc:black"] = Color3.fromRGB(27, 42, 53),
	["bc:darkgrey"] = Color3.fromRGB(109, 110, 108),
	["bc:darkgreen"] = Color3.fromRGB(40, 127, 71),
	["bc:mediumgreen"] = Color3.fromRGB(161, 196, 140),
	["bc:ligyellowichorange"] = Color3.fromRGB(243, 207, 155),
	["bc:brightgreen"] = Color3.fromRGB(75, 151, 75),
	["bc:darkorange"] = Color3.fromRGB(160, 95, 53),
	["bc:lightbluishviolet"] = Color3.fromRGB(193, 202, 222),
	["bc:transparent"] = Color3.fromRGB(236, 236, 236),
	["bc:trred"] = Color3.fromRGB(205, 84, 75),
	["bc:trlgblue"] = Color3.fromRGB(193, 223, 240),
	["bc:trblue"] = Color3.fromRGB(123, 182, 232),
	["bc:tryellow"] = Color3.fromRGB(247, 241, 141),
	["bc:lightblue"] = Color3.fromRGB(180, 210, 228),
	["bc:trflureddishorange"] = Color3.fromRGB(217, 133, 108),
	["bc:trgreen"] = Color3.fromRGB(132, 182, 141),
	["bc:trflugreen"] = Color3.fromRGB(248, 241, 132),
	["bc:phosphwhite"] = Color3.fromRGB(236, 232, 222),
	["bc:lightred"] = Color3.fromRGB(238, 196, 182),
	["bc:mediumred"] = Color3.fromRGB(218, 134, 122),
	["bc:mediumblue"] = Color3.fromRGB(110, 153, 202),
	["bc:lightgrey"] = Color3.fromRGB(199, 193, 183),
	["bc:brightviolet"] = Color3.fromRGB(107, 50, 124),
	["bc:bryellowishorange"] = Color3.fromRGB(226, 155, 64),
	["bc:brightorange"] = Color3.fromRGB(218, 133, 65),
	["bc:brightbluishgreen"] = Color3.fromRGB(0, 143, 156),
	["bc:earthyellow"] = Color3.fromRGB(104, 92, 67),
	["bc:brightbluishviolet"] = Color3.fromRGB(67, 84, 147),
	["bc:trbrown"] = Color3.fromRGB(191, 183, 177),
	["bc:mediumbluishviolet"] = Color3.fromRGB(104, 116, 172),
	["bc:trmedireddishviolet"] = Color3.fromRGB(229, 173, 200),
	["bc:medyellowishgreen"] = Color3.fromRGB(199, 210, 60),
	["bc:medbluishgreen"] = Color3.fromRGB(85, 165, 175),
	["bc:lightbluishgreen"] = Color3.fromRGB(183, 215, 213),
	["bc:bryellowishgreen"] = Color3.fromRGB(164, 189, 71),
	["bc:ligyellowishgreen"] = Color3.fromRGB(217, 228, 167),
	["bc:medyellowishorange"] = Color3.fromRGB(231, 172, 88),
	["bc:brreddishorange"] = Color3.fromRGB(211, 111, 76),
	["bc:brightreddishviolet"] = Color3.fromRGB(146, 57, 120),
	["bc:lightorange"] = Color3.fromRGB(234, 184, 146),
	["bc:trbrightbluishviolet"] = Color3.fromRGB(165, 165, 203),
	["bc:darknougat"] = Color3.fromRGB(174, 122, 89),
	["bc:silver"] = Color3.fromRGB(156, 163, 168),
	["bc:neonorange"] = Color3.fromRGB(213, 115, 61),
	["bc:neongreen"] = Color3.fromRGB(216, 221, 86),
	["bc:sandblue"] = Color3.fromRGB(116, 134, 157),
	["bc:sandviolet"] = Color3.fromRGB(135, 124, 144),
	["bc:mediumorange"] = Color3.fromRGB(224, 152, 100),
	["bc:sandyellow"] = Color3.fromRGB(149, 138, 115),
	["bc:earthblue"] = Color3.fromRGB(32, 58, 86),
	["bc:earthgreen"] = Color3.fromRGB(39, 70, 45),
	["bc:trflublue"] = Color3.fromRGB(207, 226, 247),
	["bc:sandbluemetallic"] = Color3.fromRGB(121, 136, 161),
	["bc:sandvioletmetallic"] = Color3.fromRGB(149, 142, 163),
	["bc:sandyellowmetallic"] = Color3.fromRGB(147, 135, 103),
	["bc:darkgreymetallic"] = Color3.fromRGB(87, 88, 87),
	["bc:blackmetallic"] = Color3.fromRGB(22, 29, 50),
	["bc:lightgreymetallic"] = Color3.fromRGB(171, 173, 172),
	["bc:sandgreen"] = Color3.fromRGB(120, 144, 130),
	["bc:sandred"] = Color3.fromRGB(149, 121, 119),
	["bc:darkred"] = Color3.fromRGB(123, 46, 47),
	["bc:trfluyellow"] = Color3.fromRGB(255, 246, 123),
	["bc:trflured"] = Color3.fromRGB(225, 164, 194),
	["bc:gunmetallic"] = Color3.fromRGB(117, 108, 98),
	["bc:redflipflop"] = Color3.fromRGB(151, 105, 91),
	["bc:yellowflipflop"] = Color3.fromRGB(180, 132, 85),
	["bc:silverflipflop"] = Color3.fromRGB(137, 135, 136),
	["bc:curry"] = Color3.fromRGB(215, 169, 75),
	["bc:fireyellow"] = Color3.fromRGB(249, 214, 46),
	["bc:flameyellowishorange"] = Color3.fromRGB(232, 171, 45),
	["bc:reddishbrown"] = Color3.fromRGB(105, 64, 40),
	["bc:flamereddishorange"] = Color3.fromRGB(207, 96, 36),
	["bc:mediumstonegrey"] = Color3.fromRGB(163, 162, 165),
	["bc:royalblue"] = Color3.fromRGB(70, 103, 164),
	["bc:darkroyalblue"] = Color3.fromRGB(35, 71, 139),
	["bc:brightreddishlilac"] = Color3.fromRGB(142, 66, 133),
	["bc:darkstonegrey"] = Color3.fromRGB(99, 95, 98),
	["bc:lemonmetalic"] = Color3.fromRGB(130, 138, 93),
	["bc:lightstonegrey"] = Color3.fromRGB(229, 228, 223),
	["bc:darkcurry"] = Color3.fromRGB(176, 142, 68),
	["bc:fadedgreen"] = Color3.fromRGB(112, 149, 120),
	["bc:turquoise"] = Color3.fromRGB(121, 181, 181),
	["bc:lightroyalblue"] = Color3.fromRGB(159, 195, 233),
	["bc:mediumroyalblue"] = Color3.fromRGB(108, 129, 183),
	["bc:brown"] = Color3.fromRGB(124, 92, 70),
	["bc:reddishlilac"] = Color3.fromRGB(150, 112, 159),
	["bc:lightlilac"] = Color3.fromRGB(167, 169, 206),
	["bc:brightpurple"] = Color3.fromRGB(205, 98, 152),
	["bc:lightpurple"] = Color3.fromRGB(228, 173, 200),
	["bc:lightpink"] = Color3.fromRGB(220, 144, 149),
	["bc:lightbrickyellow"] = Color3.fromRGB(240, 213, 160),
	["bc:warmyellowishorange"] = Color3.fromRGB(235, 184, 127),
	["bc:coolyellow"] = Color3.fromRGB(253, 234, 141),
	["bc:doveblue"] = Color3.fromRGB(125, 187, 221),
	["bc:mediumlilac"] = Color3.fromRGB(52, 43, 117),
	["bc:slimegreen"] = Color3.fromRGB(80, 109, 84),
	["bc:smokygrey"] = Color3.fromRGB(91, 93, 105),
	["bc:darkblue"] = Color3.fromRGB(0, 16, 176),
	["bc:parsleygreen"] = Color3.fromRGB(44, 101, 29),
	["bc:steelblue"] = Color3.fromRGB(82, 124, 174),
	["bc:stormblue"] = Color3.fromRGB(51, 88, 130),
	["bc:lapis"] = Color3.fromRGB(16, 42, 220),
	["bc:darkindigo"] = Color3.fromRGB(61, 21, 133),
	["bc:seagreen"] = Color3.fromRGB(52, 142, 64),
	["bc:shamrock"] = Color3.fromRGB(91, 154, 76),
	["bc:fossil"] = Color3.fromRGB(159, 161, 172),
	["bc:mulberry"] = Color3.fromRGB(89, 34, 89),
	["bc:forestgreen"] = Color3.fromRGB(31, 128, 29),
	["bc:cadetblue"] = Color3.fromRGB(159, 173, 192),
	["bc:electricblue"] = Color3.fromRGB(9, 137, 207),
	["bc:eggplant"] = Color3.fromRGB(123, 0, 123),
	["bc:moss"] = Color3.fromRGB(124, 156, 107),
	["bc:artichoke"] = Color3.fromRGB(138, 171, 133),
	["bc:sagegreen"] = Color3.fromRGB(185, 196, 177),
	["bc:ghostgrey"] = Color3.fromRGB(202, 203, 209),
	["bc:lilac"] = Color3.fromRGB(167, 94, 155),
	["bc:plum"] = Color3.fromRGB(123, 47, 123),
	["bc:olivine"] = Color3.fromRGB(148, 190, 129),
	["bc:laurelgreen"] = Color3.fromRGB(168, 189, 153),
	["bc:quillgrey"] = Color3.fromRGB(223, 223, 222),
	["bc:crimson"] = Color3.fromRGB(151, 0, 0),
	["bc:mint"] = Color3.fromRGB(177, 229, 166),
	["bc:babyblue"] = Color3.fromRGB(152, 194, 219),
	["bc:carnationpink"] = Color3.fromRGB(255, 152, 220),
	["bc:persimmon"] = Color3.fromRGB(255, 89, 89),
	["bc:maroon"] = Color3.fromRGB(117, 0, 0),
	["bc:gold"] = Color3.fromRGB(239, 184, 56),
	["bc:daisyorange"] = Color3.fromRGB(248, 217, 109),
	["bc:pearl"] = Color3.fromRGB(231, 231, 236),
	["bc:fog"] = Color3.fromRGB(199, 212, 228),
	["bc:salmon"] = Color3.fromRGB(255, 148, 148),
	["bc:terracotta"] = Color3.fromRGB(190, 104, 98),
	["bc:cocoa"] = Color3.fromRGB(86, 36, 36),
	["bc:wheat"] = Color3.fromRGB(241, 231, 199),
	["bc:buttermilk"] = Color3.fromRGB(254, 243, 187),
	["bc:mauve"] = Color3.fromRGB(224, 178, 208),
	["bc:sunrise"] = Color3.fromRGB(212, 144, 189),
	["bc:tawny"] = Color3.fromRGB(150, 85, 85),
	["bc:rust"] = Color3.fromRGB(143, 76, 42),
	["bc:cashmere"] = Color3.fromRGB(211, 190, 150),
	["bc:khaki"] = Color3.fromRGB(226, 220, 188),
	["bc:lilywhite"] = Color3.fromRGB(237, 234, 234),
	["bc:seashell"] = Color3.fromRGB(233, 218, 218),
	["bc:burgundy"] = Color3.fromRGB(136, 62, 62),
	["bc:cork"] = Color3.fromRGB(188, 155, 93),
	["bc:burlap"] = Color3.fromRGB(199, 172, 120),
	["bc:beige"] = Color3.fromRGB(202, 191, 163),
	["bc:oyster"] = Color3.fromRGB(187, 179, 178),
	["bc:pinecone"] = Color3.fromRGB(108, 88, 75),
	["bc:fawnbrown"] = Color3.fromRGB(160, 132, 79),
	["bc:hurricanegrey"] = Color3.fromRGB(149, 137, 136),
	["bc:cloudygrey"] = Color3.fromRGB(171, 168, 158),
	["bc:linen"] = Color3.fromRGB(175, 148, 131),
	["bc:copper"] = Color3.fromRGB(150, 103, 102),
	["bc:mediumbrown"] = Color3.fromRGB(86, 66, 54),
	["bc:bronze"] = Color3.fromRGB(126, 104, 63),
	["bc:flint"] = Color3.fromRGB(105, 102, 92),
	["bc:darktaupe"] = Color3.fromRGB(90, 76, 66),
	["bc:burntsienna"] = Color3.fromRGB(106, 57, 9),
	["bc:institutionalwhite"] = Color3.fromRGB(248, 248, 248),
	["bc:midgray"] = Color3.fromRGB(205, 205, 205),
	["bc:reallyblack"] = Color3.fromRGB(17, 17, 17),
	["bc:reallyred"] = Color3.fromRGB(255, 0, 0),
	["bc:deeporange"] = Color3.fromRGB(255, 176, 0),
	["bc:alder"] = Color3.fromRGB(180, 128, 255),
	["bc:dustyrose"] = Color3.fromRGB(163, 75, 75),
	["bc:olive"] = Color3.fromRGB(193, 190, 66),
	["bc:newyeller"] = Color3.fromRGB(255, 255, 0),
	["bc:reallyblue"] = Color3.fromRGB(0, 0, 255),
	["bc:navyblue"] = Color3.fromRGB(0, 32, 96),
	["bc:deepblue"] = Color3.fromRGB(33, 84, 185),
	["bc:cyan"] = Color3.fromRGB(4, 175, 236),
	["bc:cgabrown"] = Color3.fromRGB(170, 85, 0),
	["bc:magenta"] = Color3.fromRGB(170, 0, 170),
	["bc:pink"] = Color3.fromRGB(255, 102, 204),
	["bc:teal"] = Color3.fromRGB(18, 238, 212),
	["bc:toothpaste"] = Color3.fromRGB(0, 255, 255),
	["bc:limegreen"] = Color3.fromRGB(0, 255, 0),
	["bc:camo"] = Color3.fromRGB(58, 125, 21),
	["bc:grime"] = Color3.fromRGB(127, 142, 100),
	["bc:lavender"] = Color3.fromRGB(140, 91, 159),
	["bc:pastellightblue"] = Color3.fromRGB(175, 221, 255),
	["bc:pastelorange"] = Color3.fromRGB(255, 201, 201),
	["bc:pastelviolet"] = Color3.fromRGB(177, 167, 255),
	["bc:pastelbluegreen"] = Color3.fromRGB(159, 243, 233),
	["bc:pastelgreen"] = Color3.fromRGB(204, 255, 204),
	["bc:pastelyellow"] = Color3.fromRGB(255, 255, 204),
	["bc:pastelbrown"] = Color3.fromRGB(255, 204, 153),
	["bc:royalpurple"] = Color3.fromRGB(98, 37, 209),
	["bc:hotpink"] = Color3.fromRGB(255, 0, 191)
}


return {
    ["css:aliceblue"] = Color3.fromRGB(240, 248, 255),
    ["css:antiquewhite"] = Color3.fromRGB(250, 235, 215),
    ["css:aqua"] = Color3.fromRGB(0, 255, 255),
    ["css:aquamarine"] = Color3.fromRGB(127, 255, 212),
    ["css:azure"] = Color3.fromRGB(240, 255, 255),
    ["css:beige"] = Color3.fromRGB(245, 245, 220),
    ["css:bisque"] = Color3.fromRGB(255, 228, 196),
    ["css:black"] = Color3.fromRGB(0, 0, 0),
    ["css:blanchedalmond"] = Color3.fromRGB(255, 235, 205),
    ["css:blue"] = Color3.fromRGB(0, 0, 255),
    ["css:blueviolet"] = Color3.fromRGB(138, 43, 226),
    ["css:brown"] = Color3.fromRGB(165, 42, 42),
    ["css:burlywood"] = Color3.fromRGB(222, 184, 135),
    ["css:cadetblue"] = Color3.fromRGB(95, 158, 160),
    ["css:chartreuse"] = Color3.fromRGB(127, 255, 0),
    ["css:chocolate"] = Color3.fromRGB(210, 105, 30),
    ["css:coral"] = Color3.fromRGB(255, 127, 80),
    ["css:cornflowerblue"] = Color3.fromRGB(100, 149, 237),
    ["css:cornsilk"] = Color3.fromRGB(255, 248, 220),
    ["css:crimson"] = Color3.fromRGB(220, 20, 60),
    ["css:cyan"] = Color3.fromRGB(0, 255, 255),
    ["css:darkblue"] = Color3.fromRGB(0, 0, 139),
    ["css:darkcyan"] = Color3.fromRGB(0, 139, 139),
    ["css:darkgoldenrod"] = Color3.fromRGB(184, 134, 11),
    ["css:darkgray"] = Color3.fromRGB(169, 169, 169),
    ["css:darkgreen"] = Color3.fromRGB(0, 100, 0),
    ["css:darkgrey"] = Color3.fromRGB(169, 169, 169),
    ["css:darkkhaki"] = Color3.fromRGB(189, 183, 107),
    ["css:darkmagenta"] = Color3.fromRGB(139, 0, 139),
    ["css:darkolivegreen"] = Color3.fromRGB(85, 107, 47),
    ["css:darkorange"] = Color3.fromRGB(255, 140, 0),
    ["css:darkorchid"] = Color3.fromRGB(153, 50, 204),
    ["css:darkred"] = Color3.fromRGB(139, 0, 0),
    ["css:darksalmon"] = Color3.fromRGB(233, 150, 122),
    ["css:darkseagreen"] = Color3.fromRGB(143, 188, 143),
    ["css:darkslateblue"] = Color3.fromRGB(72, 61, 139),
    ["css:darkslategray"] = Color3.fromRGB(47, 79, 79),
    ["css:darkslategrey"] = Color3.fromRGB(47, 79, 79),
    ["css:darkturquoise"] = Color3.fromRGB(0, 206, 209),
    ["css:darkviolet"] = Color3.fromRGB(148, 0, 211),
    ["css:deeppink"] = Color3.fromRGB(255, 20, 147),
    ["css:deepskyblue"] = Color3.fromRGB(0, 191, 255),
    ["css:dimgray"] = Color3.fromRGB(105, 105, 105),
    ["css:dimgrey"] = Color3.fromRGB(105, 105, 105),
    ["css:dodgerblue"] = Color3.fromRGB(30, 144, 255),
    ["css:firebrick"] = Color3.fromRGB(178, 34, 34),
    ["css:floralwhite"] = Color3.fromRGB(255, 250, 240),
    ["css:forestgreen"] = Color3.fromRGB(34, 139, 34),
    ["css:fuchsia"] = Color3.fromRGB(255, 0, 255),
    ["css:gainsboro"] = Color3.fromRGB(220, 220, 220),
    ["css:ghostwhite"] = Color3.fromRGB(248, 248, 255),
    ["css:goldenrod"] = Color3.fromRGB(218, 165, 32),
    ["css:gold"] = Color3.fromRGB(255, 215, 0),
    ["css:gray"] = Color3.fromRGB(128, 128, 128),
    ["css:green"] = Color3.fromRGB(0, 128, 0),
    ["css:greenyellow"] = Color3.fromRGB(173, 255, 47),
    ["css:grey"] = Color3.fromRGB(128, 128, 128),
    ["css:honeydew"] = Color3.fromRGB(240, 255, 240),
    ["css:hotpink"] = Color3.fromRGB(255, 105, 180),
    ["css:indianred"] = Color3.fromRGB(205, 92, 92),
    ["css:indigo"] = Color3.fromRGB(75, 0, 130),
    ["css:ivory"] = Color3.fromRGB(255, 255, 240),
    ["css:khaki"] = Color3.fromRGB(240, 230, 140),
    ["css:lavenderblush"] = Color3.fromRGB(255, 240, 245),
    ["css:lavender"] = Color3.fromRGB(230, 230, 250),
    ["css:lawngreen"] = Color3.fromRGB(124, 252, 0),
    ["css:lemonchiffon"] = Color3.fromRGB(255, 250, 205),
    ["css:lightblue"] = Color3.fromRGB(173, 216, 230),
    ["css:lightcoral"] = Color3.fromRGB(240, 128, 128),
    ["css:lightcyan"] = Color3.fromRGB(224, 255, 255),
    ["css:lightgoldenrodyellow"] = Color3.fromRGB(250, 250, 210),
    ["css:lightgray"] = Color3.fromRGB(211, 211, 211),
    ["css:lightgreen"] = Color3.fromRGB(144, 238, 144),
    ["css:lightgrey"] = Color3.fromRGB(211, 211, 211),
    ["css:lightpink"] = Color3.fromRGB(255, 182, 193),
    ["css:lightsalmon"] = Color3.fromRGB(255, 160, 122),
    ["css:lightseagreen"] = Color3.fromRGB(32, 178, 170),
    ["css:lightskyblue"] = Color3.fromRGB(135, 206, 250),
    ["css:lightslategray"] = Color3.fromRGB(119, 136, 153),
    ["css:lightslategrey"] = Color3.fromRGB(119, 136, 153),
    ["css:lightsteelblue"] = Color3.fromRGB(176, 196, 222),
    ["css:lightyellow"] = Color3.fromRGB(255, 255, 224),
    ["css:lime"] = Color3.fromRGB(0, 255, 0),
    ["css:limegreen"] = Color3.fromRGB(50, 205, 50),
    ["css:linen"] = Color3.fromRGB(250, 240, 230),
    ["css:magenta"] = Color3.fromRGB(255, 0, 255),
    ["css:maroon"] = Color3.fromRGB(128, 0, 0),
    ["css:mediumaquamarine"] = Color3.fromRGB(102, 205, 170),
    ["css:mediumblue"] = Color3.fromRGB(0, 0, 205),
    ["css:mediumorchid"] = Color3.fromRGB(186, 85, 211),
    ["css:mediumpurple"] = Color3.fromRGB(147, 112, 219),
    ["css:mediumseagreen"] = Color3.fromRGB(60, 179, 113),
    ["css:mediumslateblue"] = Color3.fromRGB(123, 104, 238),
    ["css:mediumspringgreen"] = Color3.fromRGB(0, 250, 154),
    ["css:mediumturquoise"] = Color3.fromRGB(72, 209, 204),
    ["css:mediumvioletred"] = Color3.fromRGB(199, 21, 133),
    ["css:midnightblue"] = Color3.fromRGB(25, 25, 112),
    ["css:mintcream"] = Color3.fromRGB(245, 255, 250),
    ["css:mistyrose"] = Color3.fromRGB(255, 228, 225),
    ["css:moccasin"] = Color3.fromRGB(255, 228, 181),
    ["css:navajowhite"] = Color3.fromRGB(255, 222, 173),
    ["css:navy"] = Color3.fromRGB(0, 0, 128),
    ["css:oldlace"] = Color3.fromRGB(253, 245, 230),
    ["css:olive"] = Color3.fromRGB(128, 128, 0),
    ["css:olivedrab"] = Color3.fromRGB(107, 142, 35),
    ["css:orange"] = Color3.fromRGB(255, 165, 0),
    ["css:orangered"] = Color3.fromRGB(255, 69, 0),
    ["css:orchid"] = Color3.fromRGB(218, 112, 214),
    ["css:palegoldenrod"] = Color3.fromRGB(238, 232, 170),
    ["css:palegreen"] = Color3.fromRGB(152, 251, 152),
    ["css:paleturquoise"] = Color3.fromRGB(175, 238, 238),
    ["css:palevioletred"] = Color3.fromRGB(219, 112, 147),
    ["css:papayawhip"] = Color3.fromRGB(255, 239, 213),
    ["css:peachpuff"] = Color3.fromRGB(255, 218, 185),
    ["css:peru"] = Color3.fromRGB(205, 133, 63),
    ["css:pink"] = Color3.fromRGB(255, 192, 203),
    ["css:plum"] = Color3.fromRGB(221, 160, 221),
    ["css:powderblue"] = Color3.fromRGB(176, 224, 230),
    ["css:purple"] = Color3.fromRGB(128, 0, 128),
    ["css:rebeccapurple"] = Color3.fromRGB(102, 51, 153),
    ["css:red"] = Color3.fromRGB(255, 0, 0),
    ["css:rosybrown"] = Color3.fromRGB(188, 143, 143),
    ["css:royalblue"] = Color3.fromRGB(65, 105, 225),
    ["css:saddlebrown"] = Color3.fromRGB(139, 69, 19),
    ["css:salmon"] = Color3.fromRGB(250, 128, 114),
    ["css:sandybrown"] = Color3.fromRGB(244, 164, 96),
    ["css:seagreen"] = Color3.fromRGB(46, 139, 87),
    ["css:seashell"] = Color3.fromRGB(255, 245, 238),
    ["css:sienna"] = Color3.fromRGB(160, 82, 45),
    ["css:silver"] = Color3.fromRGB(192, 192, 192),
    ["css:skyblue"] = Color3.fromRGB(135, 206, 235),
    ["css:slateblue"] = Color3.fromRGB(106, 90, 205),
    ["css:slategray"] = Color3.fromRGB(112, 128, 144),
    ["css:slategrey"] = Color3.fromRGB(112, 128, 144),
    ["css:snow"] = Color3.fromRGB(255, 250, 250),
    ["css:springgreen"] = Color3.fromRGB(0, 255, 127),
    ["css:steelblue"] = Color3.fromRGB(70, 130, 180),
    ["css:tan"] = Color3.fromRGB(210, 180, 140),
    ["css:teal"] = Color3.fromRGB(0, 128, 128),
    ["css:thistle"] = Color3.fromRGB(216, 191, 216),
    ["css:tomato"] = Color3.fromRGB(255, 99, 71),
    ["css:turquoise"] = Color3.fromRGB(64, 224, 208),
    ["css:violet"] = Color3.fromRGB(238, 130, 238),
    ["css:wheat"] = Color3.fromRGB(245, 222, 179),
    ["css:white"] = Color3.fromRGB(255, 255, 255),
    ["css:whitesmoke"] = Color3.fromRGB(245, 245, 245),
    ["css:yellow"] = Color3.fromRGB(255, 255, 0),
    ["css:yellowgreen"] = Color3.fromRGB(154, 205, 50)
  }


--!strict
--!optimize 2
--!native

local Parser = require(script.Parent.Parser)

type StyleParent = StyleSheet | StyleRule

local function ResolvePath(path: string, inst: Instance): Instance?
    if string.match(path, "%.rsml$") then
        path = string.sub(path, 1, #path - 5)
    end

    local sections = string.split(path, "/")

    for _, section in sections do
        if section == ".." then
            local parentInst = inst.Parent
            if parentInst then inst = parentInst end

            if not parentInst then
                warn(`[RSML Error]: Instance could not be resolved for the path: \`{path}\``)
                return nil
            end

        elseif section ~= "." then
            inst = inst:WaitForChild(section)
        end
    end

    return inst
end

local function GetRoot()
    local idx = 1
    local root = debug.info(idx, "s")

    while true do
        idx += 1
        local newRoot = debug.info(idx, "s")
        if newRoot then
            root = newRoot
        else
            return root
        end
    end

    return root
end

local function InstanceFromString(instString: string): Instance
    local inst = game

    local segments = string.split(instString, ".")
    local segmentsLength = #segments

    local idx = 0
    while idx < segmentsLength do
        idx += 1
        local segment = segments[idx]

        repeat
            local ok, updatedInst = pcall(function()
                return (inst :: any)[segment]
            end)

            if not ok then
                idx += 1
                segment = `{segment}.{segments[idx]}`

            else
                inst = updatedInst
                continue
            end
        until updatedInst or idx == segmentsLength
    end

    return inst
end

local function ApplyDerive(styleSheet: StyleSheet, parent: StyleSheet)
    if typeof(styleSheet) ~= "Instance" and styleSheet.ClassName ~= "StyleSheet" then return end
    if styleSheet == parent then return end

    local derive = Instance.new("StyleDerive")
    derive.StyleSheet = styleSheet :: StyleSheet
    derive.Name = styleSheet.Name
    derive.Parent = parent
end

local function ApplyAttributes(attributes: { [string]: Parser.Datatype }, parent: StyleParent)
    for attributeName, datatype in attributes do
        -- Attribute's can't start with RBX or be more than 100 characters.
        -- If this is the case then we return that parsing was successful -
        -- but we don't apply the attribute as that would cause an error.
        if string.match(attributeName, "^RBX") then continue end
        if #attributeName > 100 then continue end

        parent:SetAttribute(attributeName, datatype)
    end
end

local function ApplyRules(rules: { Parser.TreeNode }, parent: StyleParent)
    for _, node in rules do
        local selector = node.Selector :: string
        local priority = node.Priority
        local name = node.Name

        local styleRule = Instance.new("StyleRule")
        styleRule.Selector = selector
        styleRule.Name = name or selector

        styleRule:SetProperties(node.Properties)
        ApplyAttributes(node.Attributes, styleRule)

        ApplyRules(node.Rules, styleRule)

        styleRule.Parent = parent

        if priority then styleRule.Priority = priority end
    end
end

local function ConvertRsml(rootTreeNode: Parser.TreeNode, derivesTble: { StyleSheet }?, defaultStyles: StyleSheet?): StyleSheet
    local styleSheet = Instance.new("StyleSheet")
    local styleSheetParent = InstanceFromString(GetRoot())

    local name = rootTreeNode.Name
    if name then styleSheet.Name = name end

    local attributes = rootTreeNode.Attributes
    if attributes then ApplyAttributes(attributes, styleSheet) end

    ApplyRules(rootTreeNode.Rules, styleSheet)

    local derivesFromNode = rootTreeNode.Derives
    if derivesFromNode then
        for sheetToDerivePath in derivesFromNode do
            if defaultStyles and sheetToDerivePath == "@defaults" then
                ApplyDerive(defaultStyles, styleSheet)

            else
                -- Spawns thread as `ResolvePath` may yield.
                task.spawn(function()
                    local sheetToDerive = ResolvePath(sheetToDerivePath, styleSheetParent)
                    if sheetToDerive and sheetToDerive.ClassName == "StyleSheet" then
                        -- Ensures the derived StyleSheet doesn't exist in the derives table.
                        if derivesTble then
                            local foundInDerivesTble = table.find(derivesTble, sheetToDerive :: StyleSheet)
                            if foundInDerivesTble then table.remove(derivesTble, foundInDerivesTble) end
                        end

                        ApplyDerive(sheetToDerive :: StyleSheet, styleSheet)
                    end
                end)
            end
        end
    end

    if derivesTble then
        for _, sheetToDerive in derivesTble do
            ApplyDerive(sheetToDerive, styleSheet)
        end
    end

    styleSheet.Parent = styleSheetParent

    return styleSheet
end

return ConvertRsml


local LexRsml = require(script.Parent.Lexer)
local ParseRsml = require(script.Parent.Parser)
local ConvertRsml = require(script.Parent.Converter)

-- We have to create an identical Rsml function from
-- init.luau to prevent circular dependency issues.
local function Rsml(content: string, derives: { StyleSheet }?)
    return ConvertRsml(ParseRsml(LexRsml(content)), derives)
end

--[[
The defaults below were taken from Fusion's source code. License here:
    MIT License

    Copyright (c) 2024 Daniel P H Fox

    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
]]

return Rsml [[!rsml
    @name "DefaultStyles";

    ScreenGui {
        @priority -1;
		ResetOnSpawn = false;
		ZIndexBehavior = Enum.ZIndexBehavior.Sibling
	}

	BillboardGui {
        @priority -1;
		ResetOnSpawn = false;
		ZIndexBehavior = Enum.ZIndexBehavior.Sibling;
		Active = true
	}

	SurfaceGui {
        @priority -1;
		ResetOnSpawn = false;
		ZIndexBehavior = Enum.ZIndexBehavior.Sibling;

		SizingMode = Enum.SurfaceGuiSizingMode.PixelsPerStud;
		PixelsPerStud = 50
	}

	Frame {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0
	}

	ScrollingFrame {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0;

		ScrollBarImageColor3 = color3 (0, 0, 0)
	}

	TextLabel {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0;

		FontFace = font ("SourceSansPro");
		Text = "";
		TextColor3 = color3 (0, 0, 0);
		TextSize = 14
	}

	TextButton {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0;

		AutoButtonColor = false;

		FontFace = font ("SourceSansPro");
		Text = "";
		TextColor3 = color3 (0, 0, 0);
		TextSize = 14
	}

	TextBox {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0;

		ClearTextOnFocus = false;

		FontFace = font ("SourceSansPro");
		Text = "";
		TextColor3 = color3 (0, 0, 0);
		TextSize = 14
	}

	ImageLabel {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0
	}

	ImageButton {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0;

		AutoButtonColor = false
	}

	ViewportFrame {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0
	}

	VideoFrame {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0
	}

	CanvasGroup {
        @priority -1;
		BackgroundColor3 = color3 (1, 1, 1);
		BorderColor3 = color3 (0, 0, 0);
		BorderSizePixel = 0
	}

	SpawnLocation {
        @priority -1;
		Duration = 0
	}

	BoxHandleAdornment {
        @priority -1;
		ZIndex = 0
	}
	ConeHandleAdornment {
        @priority -1;
		ZIndex = 0
	}
	CylinderHandleAdornment {
        @priority -1;
		ZIndex = 0
	}
	ImageHandleAdornment {
        @priority -1;
		ZIndex = 0
	}
	LineHandleAdornment {
        @priority -1;
		ZIndex = 0
	}
	SphereHandleAdornment {
        @priority -1;
		ZIndex = 0
	}
	WireframeHandleAdornment {
        @priority -1;
		ZIndex = 0
	}

	Part {
        @priority -1;
		Anchored = true;
		Size = vec3 (1);
		FrontSurface = Enum.SurfaceType.Smooth;
		BackSurface = Enum.SurfaceType.Smooth;
		LeftSurface = Enum.SurfaceType.Smooth;
		RightSurface = Enum.SurfaceType.Smooth;
		TopSurface = Enum.SurfaceType.Smooth;
		BottomSurface = Enum.SurfaceType.Smooth;
	}

	TrussPart {
        @priority -1;
		Anchored = true;
		Size = vec3 (2);
		FrontSurface = Enum.SurfaceType.Smooth;
		BackSurface = Enum.SurfaceType.Smooth;
		LeftSurface = Enum.SurfaceType.Smooth;
		RightSurface = Enum.SurfaceType.Smooth;
		TopSurface = Enum.SurfaceType.Smooth;
		BottomSurface = Enum.SurfaceType.Smooth;
	}

	MeshPart {
        @priority -1;
		Anchored = true;
		Size = vec3 (1);
		FrontSurface = Enum.SurfaceType.Smooth;
		BackSurface = Enum.SurfaceType.Smooth;
		LeftSurface = Enum.SurfaceType.Smooth;
		RightSurface = Enum.SurfaceType.Smooth;
		TopSurface = Enum.SurfaceType.Smooth;
		BottomSurface = Enum.SurfaceType.Smooth;
	}

	CornerWedgePart {
        @priority -1;
		Anchored = true;
		Size = vec3 (1);
		FrontSurface = Enum.SurfaceType.Smooth;
		BackSurface = Enum.SurfaceType.Smooth;
		LeftSurface = Enum.SurfaceType.Smooth;
		RightSurface = Enum.SurfaceType.Smooth;
		TopSurface = Enum.SurfaceType.Smooth;
		BottomSurface = Enum.SurfaceType.Smooth;
	}

	VehicleSeat {
        @priority -1;
		Anchored = true;
		Size = vec3 (1);
		FrontSurface = Enum.SurfaceType.Smooth;
		BackSurface = Enum.SurfaceType.Smooth;
		LeftSurface = Enum.SurfaceType.Smooth;
		RightSurface = Enum.SurfaceType.Smooth;
		TopSurface = Enum.SurfaceType.Smooth;
		BottomSurface = Enum.SurfaceType.Smooth;
	}
]]


--!strict
--!optimize 2
--!native
--!nolint LocalShadow

export type TokenDefinition = {
    Kind: TokenKind,
    Pattern: string
}

export type Token = {
    Kind: TokenKind,
    Value: string
}

export type TokenKind =
    "CommentMultiStart" |
    "StringMultiStart" | "StringMultiEnd" |
    "CommentSingle" |
    "ScopeOpen" | "ScopeClose" |
    "ParensOpen" | "ParensClose" |
    "Comma" | "SemiColon" |
    "Equals" |
    "AttributeIdentifier" | "NameIdentifier" | "PsuedoIdentifier" | "StateOrEnumIdentifier" |
    "ScopeToDescendants" | "ScopeToChildren" |
    "PriorityDeclaration" | "DeriveDeclaration" | "NameDeclaration" |
    "OpAdd" | "OpSub" | "OpMult" | "OpDiv" | "OpFloorDiv" | "OpPow" | "OpMod" |
    "BoolTrue" | "BoolFalse" |
    "Nil" |
    "EnumKeyword" |
    "ColorTailwind" | "ColorBrick" | "ColorCss" | "ColorHex" |
    "Number" | "Offset" | "ScaleOrOpMod" |
    "TagOrEnumIdentifier" |
    "StringSingle" |
    "RobloxAsset" |
    "Text" | "Error"

export type Lexer = () -> Token?

local TokenDefinitions: { TokenDefinition } = {
    {
        Kind = "CommentMultiStart",
        Pattern = "%-%-%[=*%["
    },

    {
        Kind = "StringMultiStart",
        Pattern = "%[=*%["
    },
    {
        Kind = "StringMultiEnd",
        Pattern = "%]=*%]"
    },

    {
        Kind = "CommentSingle",
        Pattern = "%-%- *[^%[\n\f\r]*"
    },

    {
        Kind = "ScopeOpen",
        Pattern = "{"
    },
    {
        Kind = "ScopeClose",
        Pattern = "}"
    },

    {
        Kind = "ParensOpen",
        Pattern = "%("
    },
    {
        Kind = "ParensClose",
        Pattern = "%)"
    },

    {
        Kind = "Comma",
        Pattern = ","
    },
    {
        Kind = "SemiColon",
        Pattern = ";"
    },

    {
        Kind = "Equals",
        Pattern = "="
    },

    {
        Kind = "AttributeIdentifier",
        Pattern = "%$"
    },
    {
        Kind = "NameIdentifier",
        Pattern = "#"
    },
    {
        Kind = "PsuedoIdentifier",
        Pattern = "::"
    },
    {
        Kind = "StateOrEnumIdentifier",
        Pattern = ":"
    },

    {
        Kind = "ScopeToDescendants",
        Pattern = ">>"
    },
    {
        Kind = "ScopeToChildren",
        Pattern = ">"
    },

    {
        Kind = "PriorityDeclaration",
        Pattern = "@priority"
    },
    {
        Kind = "DeriveDeclaration",
        Pattern = "@derive"
    },
    {
        Kind = "NameDeclaration",
        Pattern = "@name"
    },

    {
        Kind = "OpAdd",
        Pattern = "%+"
    },
    {
        Kind = "OpSub",
        Pattern = "%-"
    },
    {
        Kind = "OpMult",
        Pattern = "%*"
    },
    {
        Kind = "OpFloorDiv",
        Pattern = "//"
    },
    {
        Kind = "OpDiv",
        Pattern = "/"
    },
    {
        Kind = "OpPow",
        Pattern = "%^"
    },
    {
        Kind = "OpMod",
        Pattern = "[\n\f\t\r ]+(%%)"
    },

    {
        Kind = "BoolTrue",
        Pattern = "true"
    },
    {
        Kind = "BoolFalse",
        Pattern = "false"
    },

    {
        Kind = "Nil",
        Pattern = "nil"
    },

    {
        Kind = "EnumKeyword",
        Pattern = "Enum"
    },

    {
        Kind = "ColorTailwind",
        Pattern = "[Tt][Ww]:[A-Za-z]+:%d+"
    },
    {
        Kind = "ColorTailwind",
        Pattern = "[Tt][Ww]:[A-Za-z]+"
    },
    {
        Kind = "ColorBrick",
        Pattern = "[Bb][Cc]:[A-Za-z]+"
    },
    {
        Kind = "ColorCss",
        Pattern = "[Cc][Ss][Ss]:[A-Za-z]+"
    },
    {
        Kind = "ColorHex",
        Pattern = "#[0-9a-fA-F]+"
    },

    {
        Kind = "Number",
        Pattern = "%d*%.?%d+"
    },
    {
        Kind = "Offset",
        Pattern = "px"
    },
    {
        Kind = "ScaleOrOpMod",
        Pattern = "%%"
    },

    {
        Kind = "TagOrEnumIdentifier",
        Pattern = "%."
    },

    {
        Kind = "StringSingle",
        Pattern = '"[^"\n\t]+"'
    },
    {
        Kind = "StringSingle",
        Pattern = '""'
    },
    {
        Kind = "StringSingle",
        Pattern = "'[^'\n\t]+'"
    },
    {
        Kind = "StringSingle",
        Pattern = "''"
    },

    {
        Kind = "RobloxAsset",
        Pattern = "rbxassetid://%d+"
    },
    {
        Kind = "RobloxAsset",
        Pattern = "rbxasset://[^) ]+"
    },
    {
        Kind = "RobloxAsset",
        Pattern = "rbxthumb://[^) ]+"
    },
    {
        Kind = "RobloxAsset",
        Pattern = "rbxgameasset://[^) ]+"
    },
    {
        Kind = "RobloxAsset",
        Pattern = "rbxhttp://[^) ]+"
    },
    {
        Kind = "RobloxAsset",
        Pattern = "rbxtemp://[^) ]+"
    },
    {
        Kind = "RobloxAsset",
        Pattern = "https?://[^) ]+"
    },

    {
        Kind = "Text",
        Pattern = "[_a-zA-Z][_A-Za-z0-9]*"
    },
}

for _, token in TokenDefinitions do
    local tokenPattern = token.Pattern
    if string.match(tokenPattern, "^%^") then continue end
    token.Pattern = `^{tokenPattern}`
end

local function LexRsml(content: string)
    local cursorIdx = 0

    return function(): Token?
        for _, token in TokenDefinitions do
            local start, finish = string.find(content, token.Pattern, cursorIdx)
            if not start then continue end

            cursorIdx = (finish :: number) + 1

            return {
                Kind = token.Kind,
                Value = string.sub(content, start, finish)
            }
        end

        local start, finish = string.find(content, "[ \n\f\t\r]+", cursorIdx)
        if not start then return nil end
        cursorIdx = (finish :: number) + 1

        return {
            Kind = "Error",
            Value = string.sub(content, start, finish)
        }
    end
end

return LexRsml


export type DatatypeNone = { Kind: "None" }
local DATATYPE_NONE: DatatypeNone = { Kind = "None" }

return DATATYPE_NONE


--!strict
--!optimize 2
--!native

local DATATYPE_NONE = require(script.Parent.Parent.DatatypeNone)

type CeilFunction<T> = (from: T) -> T

type CeilFunctions = {
    number: CeilFunction<number>,
    UDim: CeilFunction<UDim>,
    UDim2: CeilFunction<UDim2>,
    Rect: CeilFunction<Rect>,
    Vector2: CeilFunction<Vector2>,
    Vector2int16: CeilFunction<Vector2int16>,
    Vector3: CeilFunction<Vector3>,
    Vector3int16: CeilFunction<Vector3int16>,
    CFrame: CeilFunction<CFrame>,
    Color3: CeilFunction<Color3>,
}

local CeilFunctions: CeilFunctions = {
    number = math.ceil,

    UDim = function(from)
        return UDim.new(
            math.ceil(from.Scale),
            math.ceil(from.Offset)
        )
    end,

    UDim2 = function(from)
        local fromX, fromY = from.X, from.Y

        return UDim2.new(
            math.ceil(fromX.Scale),
            math.ceil(fromX.Offset),
            math.ceil(fromY.Scale),
            math.ceil(fromY.Offset)
        )
    end,

    Rect = function(from)
        local fromMin, fromMax = from.Min, from.Max

        return Rect.new(
            math.ceil(fromMin.X),
            math.ceil(fromMin.Y),
            math.ceil(fromMax.X),
            math.ceil(fromMax.Y)
        )
    end,

    Vector2 = function(from)
        return Vector2.new(
            math.ceil(from.X),
            math.ceil(from.Y)
        )
    end,

    Vector2int16 = function(from)
        return Vector2int16.new(
            math.ceil(from.X),
            math.ceil(from.Y)
        )
    end,

    Vector3 = function(from)
        return Vector3.new(
            math.ceil(from.X),
            math.ceil(from.Y),
            math.ceil(from.Z)
        )
    end,

    Vector3int16 = function(from)
        return Vector3int16.new(
            math.ceil(from.X),
            math.ceil(from.Y),
            math.ceil(from.Z)
        )
    end,

    CFrame = function(from)
        local fromXVector, fromYVector, fromZVector = from.XVector, from.YVector, from.ZVector

        return CFrame.new(
            math.ceil(from.X),
            math.ceil(from.Y),
            math.ceil(from.Z),

            math.ceil(fromXVector.X),
            math.ceil(fromXVector.Y),
            math.ceil(fromXVector.Z),

            math.ceil(fromYVector.X),
            math.ceil(fromYVector.Y),
            math.ceil(fromYVector.Z),

            math.ceil(fromZVector.X),
            math.ceil(fromZVector.Y),
            math.ceil(fromZVector.Z)
        )
    end,

    Color3 = function(from)
        return Color3.new(
            math.ceil(from.R),
            math.ceil(from.G),
            math.ceil(from.B)
        )
    end,
}

local function Ceil(datatypes: { any })
    local datatype = datatypes[1]
    if not datatype then return DATATYPE_NONE end

    local func: CeilFunction<any>? = CeilFunctions[typeof(datatype)]
    if not func then return datatype end

    return func(datatype)
end

return Ceil


--!strict
--!optimize 2
--!native
--!nolint LocalShadow
--!nolint DuplicateLocal

local function DefaultIfNotType<T>(target: T, expectedType: string, default: T): T
    return if type(target) ~= expectedType then default else target
end

local function DefaultIfNotTypeOf<T>(target: T, expectedType: string, default: T): T
    return if typeof(target) ~= expectedType then default else target
end

local function ColorSeqGetColorAndTime(item: any): (Color3, number?)
    local color, colorTime

    local typeofItem = typeof(item)

    if typeofItem == "table" then
        colorTime = DefaultIfNotType((item :: any)[1], "number", nil)
        color = DefaultIfNotTypeOf((item :: any)[2], "Color3", Color3.new())

    elseif typeofItem == "Color3" then
        color = item

    else
        color = Color3.new()
    end

    return color, if colorTime then math.clamp(colorTime, 0, 1) else nil
end

local function ColorSeqGetStartValue(
    currIdx: number, colors: { ColorSequenceKeypoint | Color3 }
): (number, number)
    for idx = currIdx - 1, 1, -1 do
        local color = colors[idx]
        if typeof(color) ~= "ColorSequenceKeypoint" then continue end

        return idx, color.Time :: number
    end

    return 1, 0
end

local function ColorSeqGetEndValue(
    currIdx: number, colors: { ColorSequenceKeypoint | Color3 }, colorsLength: number
): (number, number)
    for idx = currIdx + 1, colorsLength do
        local color = colors[idx]
        if typeof(color) ~= "ColorSequenceKeypoint" then continue end

        return idx, color.Time :: number
    end

    return colorsLength, 1
end

local function ColorSeq(data)
    -- If the data only contains one color then we only
    -- need to return a color sequence with that color.
    if #data == 1 then
        local color = ColorSeqGetColorAndTime(data[1])
        return ColorSequence.new(color)
    end

    local timedColors: { ColorSequenceKeypoint }, untimedColors: { Color3 } = {}, {}

    -- Separates the colors based on if their time is explicitly stated.
    for idx, item in data do
        local color, colorTime = ColorSeqGetColorAndTime(item)

        if colorTime then
            table.insert(timedColors, ColorSequenceKeypoint.new(colorTime, color))

        else
            untimedColors[idx] = color
        end
    end

    table.sort(timedColors, function(a, b) return a.Time < b.Time end)

    local colors = timedColors :: { ColorSequenceKeypoint | Color3 }

    -- We need to insert the colors now to ensure color
    -- times are calculated properly in the next step.
    for idx, color in untimedColors do
        table.insert(colors, idx, color)
    end

    local colorsLength = #colors
    for idx, color in untimedColors do
        local startIdx, startValue = ColorSeqGetStartValue(idx, colors)
        local endIdx, endValue = ColorSeqGetEndValue(idx, colors, colorsLength)

        local colorTime = math.lerp(startValue, endValue, (idx - startIdx) / (endIdx - startIdx))

        colors[idx] = ColorSequenceKeypoint.new(colorTime, color)
    end

    local colors = timedColors :: { ColorSequenceKeypoint }

    -- Ensures that the first keypoint's time is 0.
    local firstColorKeypoint = colors[1]
    if firstColorKeypoint.Time ~= 0 then
        table.insert(colors, ColorSequenceKeypoint.new(0, firstColorKeypoint.Value))
        colorsLength += 1
    end

    -- Ensures that the last keypoint's time is 1.
    local lastColorKeypoint = colors[colorsLength]
    if lastColorKeypoint.Time ~= 1 then
        table.insert(colors, ColorSequenceKeypoint.new(1, lastColorKeypoint.Value))
    end

    return ColorSequence.new(colors :: { ColorSequenceKeypoint })
end

return ColorSeq


--!strict
--!optimize 2
--!native

local DATATYPE_NONE = require(script.Parent.Parent.DatatypeNone)

type FloorFunction<T> = (from: T) -> T

type FloorFunctions = {
    number: FloorFunction<number>,
    UDim: FloorFunction<UDim>,
    UDim2: FloorFunction<UDim2>,
    Rect: FloorFunction<Rect>,
    Vector2: FloorFunction<Vector2>,
    Vector2int16: FloorFunction<Vector2int16>,
    Vector3: FloorFunction<Vector3>,
    Vector3int16: FloorFunction<Vector3int16>,
    CFrame: FloorFunction<CFrame>,
    Color3: FloorFunction<Color3>,
}

local FloorFunctions: FloorFunctions = {
    number = math.floor,

    UDim = function(from)
        return UDim.new(
            math.floor(from.Scale),
            math.floor(from.Offset)
        )
    end,

    UDim2 = function(from)
        local fromX, fromY = from.X, from.Y

        return UDim2.new(
            math.floor(fromX.Scale),
            math.floor(fromX.Offset),
            math.floor(fromY.Scale),
            math.floor(fromY.Offset)
        )
    end,

    Rect = function(from)
        local fromMin, fromMax = from.Min, from.Max

        return Rect.new(
            math.floor(fromMin.X),
            math.floor(fromMin.Y),
            math.floor(fromMax.X),
            math.floor(fromMax.Y)
        )
    end,

    Vector2 = function(from)
        return Vector2.new(
            math.floor(from.X),
            math.floor(from.Y)
        )
    end,

    Vector2int16 = function(from)
        return Vector2int16.new(
            math.floor(from.X),
            math.floor(from.Y)
        )
    end,

    Vector3 = function(from)
        return Vector3.new(
            math.floor(from.X),
            math.floor(from.Y),
            math.floor(from.Z)
        )
    end,

    Vector3int16 = function(from)
        return Vector3int16.new(
            math.floor(from.X),
            math.floor(from.Y),
            math.floor(from.Z)
        )
    end,

    CFrame = function(from)
        local fromXVector, fromYVector, fromZVector = from.XVector, from.YVector, from.ZVector

        return CFrame.new(
            math.floor(from.X),
            math.floor(from.Y),
            math.floor(from.Z),

            math.floor(fromXVector.X),
            math.floor(fromXVector.Y),
            math.floor(fromXVector.Z),

            math.floor(fromYVector.X),
            math.floor(fromYVector.Y),
            math.floor(fromYVector.Z),

            math.floor(fromZVector.X),
            math.floor(fromZVector.Y),
            math.floor(fromZVector.Z)
        )
    end,

    Color3 = function(from)
        return Color3.new(
            math.floor(from.R),
            math.floor(from.G),
            math.floor(from.B)
        )
    end,
}

local function floor(datatypes: { any })
    local datatype = datatypes[1]
    if not datatype then return DATATYPE_NONE end

    local func: FloorFunction<any>? = FloorFunctions[typeof(datatype)]
    if not func then return datatype end

    return func(datatype)
end

return floor


--!strict
--!optimize 2
--!native

local DATATYPE_NONE = require(script.Parent.Parent.DatatypeNone)

type LerpFunction<T> = (from: T, to: T, time: number) -> T

type LerpFunctions = {
    number: LerpFunction<number>,
    UDim: LerpFunction<UDim>,
    UDim2: LerpFunction<UDim2>,
    Rect: LerpFunction<Rect>,
    Vector2: LerpFunction<Vector2>,
    Vector2int16: LerpFunction<Vector2int16>,
    Vector3: LerpFunction<Vector3>,
    Vector3int16: LerpFunction<Vector3int16>,
    CFrame: LerpFunction<CFrame>,
    Color3: LerpFunction<Color3>,
}

local LerpFunctions: LerpFunctions = {
    number = math.lerp,

    UDim = function(from, to, time)
        return UDim.new(
            math.lerp(from.Scale, to.Scale, time),
            math.lerp(from.Offset, to.Offset, time)
        )
    end,

    UDim2 = function(from, to, time)
        local fromX, fromY = from.X, from.Y
        local toX, toY = to.X, to.Y

        return UDim2.new(
            math.lerp(fromX.Scale, toX.Scale, time),
            math.lerp(fromX.Offset, toX.Offset, time),
            math.lerp(fromY.Scale, toY.Scale, time),
            math.lerp(fromY.Offset, toY.Offset, time)
        )
    end,

    Rect = function(from, to, time)
        local fromMin, fromMax = from.Min, from.Max
        local toMin, toMax = to.Min, to.Max

        return Rect.new(
            math.lerp(fromMin.X, toMin.X, time),
            math.lerp(fromMin.Y, toMin.Y, time),
            math.lerp(fromMax.X, toMax.X, time),
            math.lerp(fromMax.Y, toMax.Y, time)
        )
    end,

    Vector2 = function(from, to, time)
        return Vector2.new(
            math.lerp(from.X, to.X, time),
            math.lerp(from.Y, to.Y, time)
        )
    end,

    Vector2int16 = function(from, to, time)
        return Vector2int16.new(
            math.lerp(from.X, to.X, time),
            math.lerp(from.Y, to.Y, time)
        )
    end,

    Vector3 = function(from, to, time)
        return Vector3.new(
            math.lerp(from.X, to.X, time),
            math.lerp(from.Y, to.Y, time),
            math.lerp(from.Z, to.Z, time)
        )
    end,

    Vector3int16 = function(from, to, time)
        return Vector3int16.new(
            math.lerp(from.X, to.X, time),
            math.lerp(from.Y, to.Y, time),
            math.lerp(from.Z, to.Z, time)
        )
    end,

    CFrame = function(from, to, time)
        local fromXVector, fromYVector, fromZVector = from.XVector, from.YVector, from.ZVector
        local toXVector, toYVector, toZVector = to.XVector, to.YVector, to.ZVector

        return CFrame.new(
            math.lerp(from.X, to.X, time),
            math.lerp(from.Y, to.Y, time),
            math.lerp(from.Z, to.Z, time),

            math.lerp(fromXVector.X, toXVector.X, time),
            math.lerp(fromXVector.Y, toXVector.Y, time),
            math.lerp(fromXVector.Z, toXVector.Z, time),

            math.lerp(fromYVector.X, toYVector.X, time),
            math.lerp(fromYVector.Y, toYVector.Y, time),
            math.lerp(fromYVector.Z, toYVector.Z, time),

            math.lerp(fromZVector.X, toZVector.X, time),
            math.lerp(fromZVector.Y, toZVector.Y, time),
            math.lerp(fromZVector.Z, toZVector.Z, time)
        )
    end,

    Color3 = function(from, to, time)
        return Color3.new(
            math.lerp(from.R, to.R, time),
            math.lerp(from.G, to.G, time),
            math.lerp(from.B, to.B, time)
        )
    end,
}

local function DefaultIfNotType<T>(target: T, expectedType: string, default: T): T
    return if type(target) ~= expectedType then default else target
end

local function Lerp(datatypes: { any })
    local datatypeA = datatypes[1]
    if not datatypeA then return DATATYPE_NONE end

    local datatypeB = datatypes[2]
    if not datatypeB then return datatypeA end

    local time = DefaultIfNotType(datatypes[3], "number", .5)

    local typeofDatatypeA, typeofDatatypeB = typeof(datatypeA), typeof(datatypeB)

    if typeofDatatypeA ~= typeofDatatypeB then return datatypeA end

    local func: LerpFunction<any>? = LerpFunctions[typeofDatatypeA]
    if not func then return datatypeA end

    return func(datatypeA, datatypeB, time)
end

return Lerp


--!strict
--!optimize 2
--!native
--!nolint LocalShadow
--!nolint DuplicateLocal

local function DefaultIfNotType<T>(target: T, expectedType: string, default: T): T
    return if type(target) ~= expectedType then default else target
end

local function DefaultIfNotTypeOf<T>(target: T, expectedType: string, default: T): T
    return if typeof(target) ~= expectedType then default else target
end

local function NumSeqGetNumberTimeAndEnvelope(item: any): (number, number?, number)
    local number, numberTime, envelope

    local typeofItem = type(item)

    if typeofItem == "table" then
        numberTime = DefaultIfNotType((item :: any)[1], "number", nil)
        number = DefaultIfNotTypeOf((item :: any)[2], "number", 0)
        envelope = DefaultIfNotType((item :: any)[3], "number", 0)

    elseif typeofItem == "number" then
        number = item

    else
        number = 0
    end

    return number, if numberTime then math.clamp(numberTime, 0, 1) else nil, envelope or 0
end

local function NumSeqGetStartValue(
    currIdx: number, numbers: { NumberSequenceKeypoint | { number } }
): (number, number)
    for idx = currIdx - 1, 1, -1 do
        local number = numbers[idx]
        if typeof(number) ~= "NumberSequenceKeypoint" then continue end

        return idx, number.Time :: number
    end

    return 1, 0
end

local function NumSeqGetEndValue(
    currIdx: number, numbers: { NumberSequenceKeypoint | { number } }, numbersLength: number
): (number, number)
    for idx = currIdx + 1, numbersLength do
        local number = numbers[idx]
        if typeof(number) ~= "NumberSequenceKeypoint" then continue end

        return idx, number.Time :: number
    end

    return numbersLength, 1
end

local function NumSeq(data)
    -- If the data only contains one number then we only
    -- need to return a number sequence with that number.
    if #data == 1 then
        local number = NumSeqGetNumberTimeAndEnvelope(data[1])
        return NumberSequence.new(number)
    end

    local timedNumbers: { NumberSequenceKeypoint }, untimedNumbers: {{ number }} = {}, {}

    -- Separates the numbers based on if their time is explicitly stated.
    for idx, item in data do
        local number, numberTime, envelope = NumSeqGetNumberTimeAndEnvelope(item)

        if numberTime then
            table.insert(timedNumbers, NumberSequenceKeypoint.new(numberTime, number, envelope))

        else
            untimedNumbers[idx] = { number, envelope }
        end
    end

    table.sort(timedNumbers, function(a, b) return a.Time < b.Time end)

    local numbers = timedNumbers :: { NumberSequenceKeypoint | { number } }

    -- We need to insert the numbers now to ensure number
    -- times are calculated properly in the next step.
    for idx, number in untimedNumbers do
        table.insert(numbers, idx, number)
    end

    local numbersLength = #numbers
    for idx, number in untimedNumbers do
        local startIdx, startValue = NumSeqGetStartValue(idx, numbers)
        local endIdx, endValue = NumSeqGetEndValue(idx, numbers, numbersLength)

        local numberTime = math.lerp(startValue, endValue, (idx - startIdx) / (endIdx - startIdx))

        numbers[idx] = NumberSequenceKeypoint.new(numberTime, number[1], number[2])
    end

    local numbers = timedNumbers :: { NumberSequenceKeypoint }

    -- Ensures that the first keypoint's time is 0.
    local firstNumberKeypoint = numbers[1]
    if firstNumberKeypoint.Time ~= 0 then
        table.insert(numbers, NumberSequenceKeypoint.new(0, firstNumberKeypoint.Value))
        numbersLength += 1
    end

    -- Ensures that the last keypoint's time is 1.
    local lastNumberKeypoint = numbers[numbersLength]
    if lastNumberKeypoint.Time ~= 1 then
        table.insert(numbers, NumberSequenceKeypoint.new(1, lastNumberKeypoint.Value))
    end

    return NumberSequence.new(numbers :: { NumberSequenceKeypoint })
end

return NumSeq


--!strict
--!optimize 2
--!native

local DATATYPE_NONE = require(script.Parent.Parent.DatatypeNone)

type RoundFunction<T> = (from: T) -> T

type RoundFunctions = {
    number: RoundFunction<number>,
    UDim: RoundFunction<UDim>,
    UDim2: RoundFunction<UDim2>,
    Rect: RoundFunction<Rect>,
    Vector2: RoundFunction<Vector2>,
    Vector2int16: RoundFunction<Vector2int16>,
    Vector3: RoundFunction<Vector3>,
    Vector3int16: RoundFunction<Vector3int16>,
    CFrame: RoundFunction<CFrame>,
    Color3: RoundFunction<Color3>,
}

local RoundFunctions: RoundFunctions = {
    number = math.round,

    UDim = function(from)
        return UDim.new(
            math.round(from.Scale),
            math.round(from.Offset)
        )
    end,

    UDim2 = function(from)
        local fromX, fromY = from.X, from.Y

        return UDim2.new(
            math.round(fromX.Scale),
            math.round(fromX.Offset),
            math.round(fromY.Scale),
            math.round(fromY.Offset)
        )
    end,

    Rect = function(from)
        local fromMin, fromMax = from.Min, from.Max

        return Rect.new(
            math.round(fromMin.X),
            math.round(fromMin.Y),
            math.round(fromMax.X),
            math.round(fromMax.Y)
        )
    end,

    Vector2 = function(from)
        return Vector2.new(
            math.round(from.X),
            math.round(from.Y)
        )
    end,

    Vector2int16 = function(from)
        return Vector2int16.new(
            math.round(from.X),
            math.round(from.Y)
        )
    end,

    Vector3 = function(from)
        return Vector3.new(
            math.round(from.X),
            math.round(from.Y),
            math.round(from.Z)
        )
    end,

    Vector3int16 = function(from)
        return Vector3int16.new(
            math.round(from.X),
            math.round(from.Y),
            math.round(from.Z)
        )
    end,

    CFrame = function(from)
        local fromXVector, fromYVector, fromZVector = from.XVector, from.YVector, from.ZVector

        return CFrame.new(
            math.round(from.X),
            math.round(from.Y),
            math.round(from.Z),

            math.round(fromXVector.X),
            math.round(fromXVector.Y),
            math.round(fromXVector.Z),

            math.round(fromYVector.X),
            math.round(fromYVector.Y),
            math.round(fromYVector.Z),

            math.round(fromZVector.X),
            math.round(fromZVector.Y),
            math.round(fromZVector.Z)
        )
    end,

    Color3 = function(from)
        return Color3.new(
            math.round(from.R),
            math.round(from.G),
            math.round(from.B)
        )
    end,
}

local function round(datatypes: { any })
    local datatype = datatypes[1]
    if not datatype then return DATATYPE_NONE end

    local func: RoundFunction<any>? = RoundFunctions[typeof(datatype)]
    if not func then return datatype end

    return func(datatype)
end

return round