diff --git a/package.json b/package.json index da6deeed..074e1ae4 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "@builder.io/partytown": "^0.10.2", "@builder.io/qwik": "1.5.7", "@builder.io/qwik-city": "1.5.7", - "@luminescent/ui": "0.18.1", + "@luminescent/ui": "0.18.2", "@modular-forms/qwik": "^0.25.0", "@types/eslint": "8.56.10", "@types/node": "latest", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c90b462d..bb3b3e40 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,8 +21,8 @@ importers: specifier: 1.5.7 version: 1.5.7(@types/node@20.13.0)(rollup@4.18.0) '@luminescent/ui': - specifier: 0.18.1 - version: 0.18.1 + specifier: 0.18.2 + version: 0.18.2 '@modular-forms/qwik': specifier: ^0.25.0 version: 0.25.0(@builder.io/qwik-city@1.5.7(@types/node@20.13.0)(rollup@4.18.0))(@builder.io/qwik@1.5.7(@types/node@20.13.0)(undici@6.18.2)) @@ -606,8 +606,8 @@ packages: '@kurkle/color@0.3.2': resolution: {integrity: sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==} - '@luminescent/ui@0.18.1': - resolution: {integrity: sha512-DqdaCQ7uuc/AfimNnmqjBnlV2+d8l6WQJXKZ5wafIQTSeXGX1fxESDP76W+A0NOURhkh3FuwIcoHOM4c4eT+Zw==} + '@luminescent/ui@0.18.2': + resolution: {integrity: sha512-hMt7dRJyTbLdaMTNinn/bV338jHIn7Y2D7gjigKxolzkcPFVk2dyvMQYsQC7OsaXLuGgx6l1zWW0oP/i0j1CGQ==} engines: {node: '>=15.0.0'} '@mdx-js/mdx@3.0.1': @@ -2776,7 +2776,7 @@ snapshots: '@kurkle/color@0.3.2': {} - '@luminescent/ui@0.18.1': {} + '@luminescent/ui@0.18.2': {} '@mdx-js/mdx@3.0.1': dependencies: diff --git a/src/components/util/PresetUtils.ts b/src/components/util/PresetUtils.ts index b22543ea..48078013 100644 --- a/src/components/util/PresetUtils.ts +++ b/src/components/util/PresetUtils.ts @@ -223,7 +223,7 @@ export function loadPreset(p: string) { } if (version === 1) { newPreset.version = defaults.version; - newPreset.colors = preset.colors.map((color: string, i: number) => ({ hex: color, pos: i / preset.colors.length * 100 })); + newPreset.colors = preset.colors.map((color: string, i: number) => ({ hex: color, pos: (100 / (preset.colors.length - 1)) * i })); newPreset.name = preset.name; newPreset.text = preset.text; newPreset.speed = preset.speed; @@ -242,7 +242,7 @@ export function loadPreset(p: string) { } if (version === 2) { newPreset.version = defaults.version; - newPreset.colors = preset.colors.map((color: string, i: number) => ({ hex: color, pos: i / preset.colors.length * 100 })); + newPreset.colors = preset.colors.map((color: string, i: number) => ({ hex: color, pos: (100 / (preset.colors.length - 1)) * i })); newPreset.name = preset.name; newPreset.text = preset.text; newPreset.speed = preset.speed; diff --git a/src/routes/api/gradient/index.tsx b/src/routes/api/gradient/index.tsx index 0914fd50..c6bd3936 100755 --- a/src/routes/api/gradient/index.tsx +++ b/src/routes/api/gradient/index.tsx @@ -49,13 +49,11 @@ export const onGet: RequestHandler = async ({ json, query }) => { }; throw json(200, { - WARNING: 'This endpoint is deprecated. Please use /api/v3/rgb instead.', - output: generateOutput(text, colors?.split(',').map((color: string, index: number) => { - return { - hex: color, - pos: index / colors.length, - }; - }), { color: format, char: formatchar }, `${prefix}$t`, true, bold == 'true', italic == 'true', underline == 'true', strikethrough == 'true'), + WARNING: 'This endpoint is deprecated. Please use /api/v2/rgb instead.', + output: generateOutput(text, colors?.split(',').map((color: string, i: number) => ({ + hex: color, + pos: (100 / (colors.length - 1)) * i, + })), { color: format, char: formatchar }, `${prefix}$t`, true, bold == 'true', italic == 'true', underline == 'true', strikethrough == 'true'), ...options, }); }; \ No newline at end of file diff --git a/src/routes/api/index.tsx b/src/routes/api/index.tsx index 94fcf0c2..d1c8fdd4 100755 --- a/src/routes/api/index.tsx +++ b/src/routes/api/index.tsx @@ -9,10 +9,6 @@ export const onGet: RequestHandler = async ({ json }) => { }, '/api/v2': { GET: 'View the v2 API endpoints.', - WARNING: '/api/v2 is deprecated. Please use /api/v3 instead.', - }, - '/api/v3': { - GET: 'View the v3 API endpoints.', }, }, }); diff --git a/src/routes/api/v2/docs/index.tsx b/src/routes/api/v2/docs/index.tsx index 93530722..6f8760b5 100644 --- a/src/routes/api/v2/docs/index.tsx +++ b/src/routes/api/v2/docs/index.tsx @@ -26,9 +26,6 @@ export default component$(() => {

RGBirdflop API Docs

-

- The /api/gradient and /api/v2 endpoints are deprecated and will be removed in the future in favor of /api/v3. Please update your code to use the new API. -

Get Started

@@ -70,7 +67,7 @@ export default component$(() => {
- Format Object + Format

color

@@ -110,6 +107,25 @@ export default component$(() => {

example: {v3formats.find(format => format.color == 'MiniMessage')?.strikethrough}

+ +
+ Color +
+
+

hex

+

required

+

type: string

+

The color in hex format.

+

example: "#00ffe0"

+
+
+

pos

+

required

+

type: number

+

The position of the color in the gradient as a percentage

+

example: 50

+
+
; diff --git a/src/routes/api/v2/index.tsx b/src/routes/api/v2/index.tsx index fc22173b..bdbf0739 100644 --- a/src/routes/api/v2/index.tsx +++ b/src/routes/api/v2/index.tsx @@ -6,9 +6,7 @@ export const onGet: RequestHandler = async ({ json }) => { '/api/v2/rgb': { POST: 'Generate a gradient.', GET: 'Equivalent to POST, but with query parameters.', - WARNING: '/api/v2/rgb is deprecated. Please use /api/v3/rgb instead.', }, }, - WARNING: '/api/v2 is deprecated. Please use /api/v3 instead.', }); }; \ No newline at end of file diff --git a/src/routes/api/v2/rgb/index.tsx b/src/routes/api/v2/rgb/index.tsx index 4591eed4..c91330ef 100644 --- a/src/routes/api/v2/rgb/index.tsx +++ b/src/routes/api/v2/rgb/index.tsx @@ -3,30 +3,19 @@ import { v3formats } from '~/components/util/PresetUtils'; import { generateOutput } from '~/components/util/RGBUtils'; import { rgbDefaults } from '~/routes/resources/rgb'; -const v2rgbDefaults = { - rgbDefaults, - colors: rgbDefaults.colors.map(color => color.hex), -}; - export const onGet: RequestHandler = async ({ json, query }) => { let output = {}; try { const queryjson: any = Object.fromEntries(query); + const keys = Object.keys(queryjson); for (const key of keys) { - if (key == 'colors') { - queryjson.colors = queryjson.colors.split(','); - queryjson.colors = queryjson.colors.map((color: string, index: number) => { - return { - hex: color, - pos: index / queryjson.colors.length, - }; - }); - } + if (key == 'colors') queryjson.colors = queryjson.colors.split(','); else if (queryjson[key] == 'true') queryjson[key] = true; else if (queryjson[key] == 'false') queryjson[key] = false; else if (queryjson[key].startsWith('{') && queryjson[key].endsWith('}')) queryjson[key] = JSON.parse(queryjson[key]); } + output = await getOutput(queryjson); } catch (e: any) { @@ -39,13 +28,7 @@ export const onGet: RequestHandler = async ({ json, query }) => { export const onPost: RequestHandler = async ({ json, parseBody }) => { let output = {}; try { - const body = await parseBody() as any; - if (body?.colors) body.colors = body.colors.map((color: string, index: number) => { - return { - hex: color, - pos: index / body.colors.length * 100, - }; - }); + const body = await parseBody(); output = await getOutput(body); } catch (e: any) { @@ -69,12 +52,12 @@ async function getOutput(body: any) { default: rgbDefaults.text, }, colors: { - type: 'array of (string)', + type: 'array of (Color object - see data models in docs) or array of (string)', description: 'The colors to use for the gradient. Must be in hex format.', - default: v2rgbDefaults.colors, + default: rgbDefaults.colors, }, format: { - type: 'format object - see data models in docs', + type: 'Format object - see data models in docs', description: 'The format to use for the color and format codes. For MiniMessage, { color: "MiniMessage" } can be used.', default: rgbDefaults.format, }, @@ -116,17 +99,23 @@ async function getOutput(body: any) { }, }; - // in case stupid - // mostly just so people can just send { color: "MiniMessage" } + /* in case stupid */ + + // make { color: "MiniMessage" } a valid format let format = body?.format; if (format && !format.char && (!format.bold || !format.italic || !format.underline || !format.strikethrough)) { format = v3formats.find(f => f.color == format.color) ?? { ...format, char: '&' }; } - const { text, colors, prefixsuffix, trimspaces, bold, italic, underline, strikethrough } = body ?? {}; + // make string[] a valid color array + let colors = body?.colors; + if (colors && colors.length && typeof colors[0] == 'string') { + if (typeof colors[0] == 'string') colors = colors.map((color: string, i: number) => ({ hex: color, pos: (100 / (colors.length - 1)) * i })); + } + + const { text, prefixsuffix, trimspaces, bold, italic, underline, strikethrough } = body ?? {}; const output = generateOutput(text, colors, format, prefixsuffix, trimspaces, bold, italic, underline, strikethrough); return { - WARNING: 'This endpoint is deprecated. Please use /api/v3/rgb instead.', output, ...options, }; diff --git a/src/routes/api/v3/docs/index.tsx b/src/routes/api/v3/docs/index.tsx deleted file mode 100644 index bd8f55ff..00000000 --- a/src/routes/api/v3/docs/index.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import { component$ } from '@builder.io/qwik'; -import { routeLoader$, type DocumentHead } from '@builder.io/qwik-city'; -import { Card, Header } from '@luminescent/ui'; - -import { DocumentOutline } from 'qwik-ionicons'; -import { defaults, v3formats } from '~/components/util/PresetUtils'; - -export const useEndpoints = routeLoader$(async ({ url }) => { - const data = await fetch(url.origin + '/api/v2'); - const json = await data.json(); - const paths = Object.keys(json.endpoints); - for (const path of paths) { - const endpointData = await fetch(url.origin + path); - const endpointJson = await endpointData.json(); - json.endpoints[path] = { methods: json.endpoints[path], options: endpointJson.options }; - } - return json; -}); - -export default component$(() => { - const { endpoints } = useEndpoints().value; - - return <> -
-
-

- RGBirdflop API Docs -

-

- Get Started -

-

- This API is used to generate RGB gradient text for Minecraft and is based on JSON. Useful for creating gradient text in your own code for anything Minecraft-related. - The API has default values that are the same as the RGBirdflop website, which are also shown in the docs below. - To generate a gradient, make a GET request to /api/v2/rgb. The API will return a JSON object with the gradient output. -

-

- Endpoints -

-
- {Object.keys(endpoints).map((path) =>
-

- {path} -

- {Object.entries(endpoints[path].methods).map(([method, description]: any) => -

- {method}: {description} -

, - )} -

- Options -

- - {Object.keys(endpoints[path].options).map(option => { - return
-

{option}

-

type: {endpoints[path].options[option].type}

-

{endpoints[path].options[option].description}

-

default: {JSON.stringify(endpoints[path].options[option].default, null, 1)}

-
; - })} -
-
)} -
-

- Data Models -

- -
- Format -
-
-

color

-

required

-

type: string

-

The format to use for the color codes. $1 = #(r)rggbb, $2 = #r(r)ggbb, $3 = #rr(g)gbb, $4 = #rrg(g)bb, $5 = #rrgg(b)b, $6 = #rrggb(b), $f = format tags, $c = the character

-

example: "{defaults.format.color}" or "MiniMessage"

-
-
-

char

-

type: string

-

The character to use for the format tags. (such as &l, &o, &n, &m)

-

example: "{defaults.format.char}"

-
-
-

bold

-

type: string

-

The code to use for making the text bold. $t is where the output text will go. If $t is not included, the output will not show.

-

example: {v3formats.find(format => format.color == 'MiniMessage')?.bold}

-
-
-

italic

-

type: string

-

The code to use for making the text italic. $t is where the output text will go. If $t is not included, the output will not show.

-

example: {v3formats.find(format => format.color == 'MiniMessage')?.italic}

-
-
-

underline

-

type: string

-

The code to use for making the text underline. $t is where the output text will go. If $t is not included, the output will not show.

-

example: {v3formats.find(format => format.color == 'MiniMessage')?.underline}

-
-
-

strikethrough

-

type: string

-

The code to use for making the text strikethrough. $t is where the output text will go. If $t is not included, the output will not show.

-

example: {v3formats.find(format => format.color == 'MiniMessage')?.strikethrough}

-
-
- -
- Color -
-
-

hex

-

required

-

type: string

-

The color in hex format.

-

example: "#00ffe0"

-
-
-

pos

-

type: number

-

The position of the color in the gradient as a percentage

-

example: 50

-
-
-
-
- ; -}); - -export const head: DocumentHead = { - title: 'RGBirdflop API Docs', - meta: [ - { - name: 'description', - content: 'This API is used to generate RGB gradient text for Minecraft', - }, - { - name: 'og:description', - content: 'This API is used to generate RGB gradient text for Minecraft', - }, - { - name: 'og:image', - content: '/branding/icon.png', - }, - ], -}; \ No newline at end of file diff --git a/src/routes/api/v3/index.tsx b/src/routes/api/v3/index.tsx deleted file mode 100644 index d0e239fa..00000000 --- a/src/routes/api/v3/index.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import type { RequestHandler } from '@builder.io/qwik-city'; - -export const onGet: RequestHandler = async ({ json }) => { - throw json(200, { - endpoints: { - '/api/v3/rgb': { - POST: 'Generate a gradient.', - GET: 'Equivalent to POST, but with query parameters.', - }, - }, - }); -}; \ No newline at end of file diff --git a/src/routes/api/v3/rgb/index.tsx b/src/routes/api/v3/rgb/index.tsx deleted file mode 100644 index 41567650..00000000 --- a/src/routes/api/v3/rgb/index.tsx +++ /dev/null @@ -1,115 +0,0 @@ -import type { RequestHandler } from '@builder.io/qwik-city'; -import { v3formats } from '~/components/util/PresetUtils'; -import { generateOutput } from '~/components/util/RGBUtils'; -import { rgbDefaults } from '~/routes/resources/rgb'; - -export const onGet: RequestHandler = async ({ json, query }) => { - let output = {}; - try { - const queryjson: any = Object.fromEntries(query); - - const keys = Object.keys(queryjson); - for (const key of keys) { - if (key == 'colors') queryjson.colors = queryjson.colors.split(','); - else if (queryjson[key] == 'true') queryjson[key] = true; - else if (queryjson[key] == 'false') queryjson[key] = false; - else if (queryjson[key].startsWith('{') && queryjson[key].endsWith('}')) queryjson[key] = JSON.parse(queryjson[key]); - } - - output = await getOutput(queryjson); - } - catch (e: any) { - console.error(e); - throw json(400, { error: e.message }); - } - throw json(200, output); -}; - -export const onPost: RequestHandler = async ({ json, parseBody }) => { - let output = {}; - try { - const body = await parseBody(); - output = await getOutput(body); - } - catch (e: any) { - console.error(e); - throw json(400, { error: e.message }); - } - - throw json(200, output); -}; - -async function getOutput(body: any) { - const options = body?.silent ? {} : { - input: { - ...rgbDefaults, - ...body, - }, - options: { - text: { - type: 'string', - description: 'The text to use for the gradient.', - default: rgbDefaults.text, - }, - colors: { - type: 'array of (Color object) - see data models in docs', - description: 'The colors to use for the gradient.', - default: rgbDefaults.colors, - }, - format: { - type: 'Format object - see data models in docs', - description: 'The format to use for the color and format codes. For MiniMessage, { color: "MiniMessage" } can be used.', - default: rgbDefaults.format, - }, - prefixsuffix: { - type: 'string', - description: 'The prefix or suffix to use for the text. Usually used for commands and stuff. $t will be replaced with the output text, if $t is not included, the output will not show.', - default: rgbDefaults.prefixsuffix, - }, - trimspaces: { - type: 'boolean', - description: 'Whether or not to trim color codes from spaces. Turn this off if you\'re using empty underlines or strikethroughs.', - default: rgbDefaults.trimspaces, - }, - bold: { - type: 'boolean', - description: 'Whether or not to bold the text.', - default: rgbDefaults.bold, - }, - italic: { - type: 'boolean', - description: 'Whether or not to italicize the text.', - default: rgbDefaults.italic, - }, - underline: { - type: 'boolean', - description: 'Whether or not to underline the text.', - default: rgbDefaults.underline, - }, - strikethrough: { - type: 'boolean', - description: 'Whether or not to strikethrough the text.', - default: rgbDefaults.strikethrough, - }, - silent: { - type: 'boolean', - description: 'Set this to true to hide the options and input.', - default: false, - }, - }, - }; - - // in case stupid - // mostly just so people can just send { color: "MiniMessage" } - let format = body?.format; - if (format && !format.char && (!format.bold || !format.italic || !format.underline || !format.strikethrough)) { - format = v3formats.find(f => f.color == format.color) ?? { ...format, char: '&' }; - } - - const { text, colors, prefixsuffix, trimspaces, bold, italic, underline, strikethrough } = body ?? {}; - const output = generateOutput(text, colors, format, prefixsuffix, trimspaces, bold, italic, underline, strikethrough); - return { - output, - ...options, - }; -} \ No newline at end of file