From 990cc98e75f5854e30306050f911e057bd928e70 Mon Sep 17 00:00:00 2001 From: darckfast <21337578+Darckfast@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:52:36 -0300 Subject: [PATCH 1/8] feat: add typescript support --- index.test.js => index.test.ts | 2 +- index.js => index.ts | 202 +++++++++++++++++++++++---------- mise.toml | 10 ++ package.json | 18 ++- tsconfig.json | 40 +++++++ tsup.config.ts | 11 ++ 6 files changed, 222 insertions(+), 61 deletions(-) rename index.test.js => index.test.ts (99%) rename index.js => index.ts (57%) create mode 100644 mise.toml create mode 100644 tsconfig.json create mode 100644 tsup.config.ts diff --git a/index.test.js b/index.test.ts similarity index 99% rename from index.test.js rename to index.test.ts index f60a3de..c57c8bb 100644 --- a/index.test.js +++ b/index.test.ts @@ -2,7 +2,7 @@ import { beforeAll, describe, expect, test } from 'vitest' import { EmotesJS } from './index' describe('EmotesJS: parse', () => { - let emotes + let emotes: EmotesJS beforeAll(async () => { emotes = new EmotesJS({ channelId: 38746172, colon: true }) diff --git a/index.js b/index.ts similarity index 57% rename from index.js rename to index.ts index 9025a86..dbb4f16 100644 --- a/index.js +++ b/index.ts @@ -1,35 +1,144 @@ -class EmotesJS { - /** @default Map */ - #cachedEmotes = new Map(); - /** @default true */ +export interface SevenTVChannelEmotes { + id: string + platform: string + username: string + display_name: string + linked_at: number + emote_capacity: number + emote_set_id: string + emote_set: EmoteSet + user: User +} + +export interface EmoteSet { + id: string + name: string + flags: number + tags: any[] + immutable: boolean + privileged: boolean + emotes: Emote[] + emote_count: number + capacity: number + owner: any +} + +export interface Emote { + id: string + name: string + flags: number + timestamp: number + actor_id?: string + data: Data + origin_id: any +} + +export interface Data { + id: string + name: string + flags: number + lifecycle: number + state: string[] + listed: boolean + animated: boolean + owner?: Owner + host: Host + tags?: string[] +} + +export interface Owner { + id: string + username: string + display_name: string + avatar_url?: string + style: Style + role_ids: string[] + connections: Connection[] +} + +export interface Style { + color?: number + paint_id?: string + badge_id?: string +} + + + +export interface Connection { + id: string + platform: string + username: string + display_name: string + linked_at: number + emote_capacity: number + emote_set_id: string + emote_set: any +} + +export interface Host { + url: string + files: File[] +} + +export interface File { + name: string + static_name: string + width: number + height: number + frame_count: number + size: number + format: string +} + +export interface User { + id: string + username: string + display_name: string + created_at: number + avatar_url: string + style: Style + emote_sets: EmoteSet[] + editors: Editor[] + roles: string[] + connections: Connection[] +} + +export interface Editor { + id: string + permissions: number + visible: boolean + added_at: number +} + + + +interface Opts { + channelId?: number + only?: Array + usePixelDensity?: boolean + colon?: boolean + height?: string + format?: string + cache?: string + proxy?: string +} + +export class EmotesJS { + #cachedEmotes = new Map(); #colon = true; - /** @default "1.65rem" */ #height = "1.65rem"; - /** @default "WEBP" */ #format = "WEBP"; - /** @default "https://cdn.7tv.app" */ #allowedOrigins = "https://cdn.7tv.app"; - /** @default false */ #isReady = false; - /** @default false */ #usePixelDensity = false; - /** @default 0 */ total = 0; - /** @default 0 */ channelId = 0; - /** @default Promise */ isLoading = Promise.resolve(); - /** @default "" */ proxy = "" - /** - * @static - */ - static instance; - /** - * @param {Opts} opts - */ - constructor(opts) { + static instance: EmotesJS; + + constructor(opts: Opts) { if (EmotesJS.instance && EmotesJS.instance.channelId !== 0) { return EmotesJS.instance; } @@ -47,37 +156,28 @@ class EmotesJS { this.#isReady = true; } - this.proxy = opts.proxy + this.proxy = opts.proxy || "" } this.isLoading = this.load(only); EmotesJS.instance = this; } - /** - * @static - * @param {string} cache - * @returns {EmotesJS} - */ - static fromCache(cache) { + + static fromCache(cache: string) { return new EmotesJS({ cache }); } - /** - * @returns {string} - */ + cache() { return JSON.stringify(Object.fromEntries(this.#cachedEmotes.entries())); } - /** - * @param {string[]} [only=[]] - * @returns {Promise} - */ - async load(only = []) { - let globalProm = fetch("https://7tv.io/v3/emote-sets/global").then(r => { + + async load(only: Array = []) { + let globalProm: Promise = fetch("https://7tv.io/v3/emote-sets/global").then(r => { if (r.ok) { return r.json(); } throw new Error("fetch unsuccessful"); }); - let chProm = fetch("https://7tv.io/v3/users/twitch/" + this.channelId).then(r => { + let chProm: Promise = fetch("https://7tv.io/v3/users/twitch/" + this.channelId).then(r => { if (r.ok) { return r.json(); } @@ -110,7 +210,8 @@ class EmotesJS { let srcset = files.reduce((acc, curr) => { let w = `${curr.width}w`; if (this.#usePixelDensity) { - [w] = curr.name.split('.'); + //@ts-ignore + [w] = curr.name.split('.') || ''; } return `${url}/${curr.name} ${w}, ${acc}`; }, ""); @@ -120,11 +221,8 @@ class EmotesJS { this.total = this.#cachedEmotes.size; this.#isReady = true; } - /** - * @param {string | undefined} text - * @returns {string} - */ - parse(text) { + + parse(text: string) { if (!text) { console.log("no text to parse emotes"); return ""; @@ -141,11 +239,11 @@ class EmotesJS { let fullText = ""; for (let i = 0; i < words.length; i++) { let word = words[i]; - if (this.#colon && !word.startsWith(":")) { + if (this.#colon && !word?.startsWith(":")) { fullText += word + " "; continue; } - let wordKey = word.replaceAll(":", ""); + let wordKey = word?.replaceAll(":", "") || ''; let emote = this.#cachedEmotes.get(wordKey); if (emote) { fullText += emote + " "; @@ -156,14 +254,4 @@ class EmotesJS { return fullText.trim(); } } -module.exports = { EmotesJS }; -/** - * @typedef {Object} Opts - * @property {number} [channelId] - * @property {string[]} [only] - * @property {boolean} [colon] - * @property {string} [height] - * @property {"WEBP" | "AVIF"} [format] - * @property {boolean} [usePixelDensity] - * @property {string} [cache] - */ + diff --git a/mise.toml b/mise.toml new file mode 100644 index 0000000..4b5061a --- /dev/null +++ b/mise.toml @@ -0,0 +1,10 @@ +[tools] +node = "26" +pnpm = "10.33" + +[tasks.build] +run = "pnpx tsup && pnpx terser ./dist/index.js -o ./dist/index.js" + +[tasks.test] +run = "pnpm run test" + diff --git a/package.json b/package.json index 2e03c63..551935b 100644 --- a/package.json +++ b/package.json @@ -10,9 +10,19 @@ "node": ">=22" }, "files": [ - "index.js" + "dist" ], - "main": "index.js", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "type": "module", + "exports": { + ".": { + "import": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + } + }, "repository": { "type": "git", "url": "git://github.com/darckfast/emotesjs.git" @@ -25,9 +35,11 @@ ], "scripts": { "test": "vitest run", - "prepublishOnly": "pnpx terser index.js -o index.js" + "prepublishOnly": "pnpx tsup && pnpx terser ./dist/index.js -o ./dist/index.js" }, "devDependencies": { + "tsup": "^8.5.1", + "typescript": "^6.0.3", "vitest": "^3.2.4" } } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a8108a4 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,40 @@ +{ + // Visit https://aka.ms/tsconfig to read more about this file + "compilerOptions": { + // File Layout + // "rootDir": "./src", + // "outDir": "./dist", + "ignoreDeprecations": "6.0", + // Environment Settings + // See also https://aka.ms/tsconfig/module + "module": "nodenext", + "target": "esnext", + "types": [], + // For nodejs: + // "lib": ["esnext"], + // "types": ["node"], + // and npm install -D @types/node + // Other Outputs + "sourceMap": true, + "declaration": true, + "declarationMap": true, + // Stricter Typechecking Options + "noUncheckedIndexedAccess": true, + "exactOptionalPropertyTypes": true, + // Style Options + // "noImplicitReturns": true, + // "noImplicitOverride": true, + // "noUnusedLocals": true, + // "noUnusedParameters": true, + // "noFallthroughCasesInSwitch": true, + // "noPropertyAccessFromIndexSignature": true, + // Recommended Options + "strict": true, + "jsx": "react-jsx", + "verbatimModuleSyntax": true, + "isolatedModules": true, + "noUncheckedSideEffectImports": true, + "moduleDetection": "force", + "skipLibCheck": true, + } +} diff --git a/tsup.config.ts b/tsup.config.ts new file mode 100644 index 0000000..702e3cc --- /dev/null +++ b/tsup.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + entry: ['index.ts'], + dts: true, + splitting: false, + sourcemap: true, + clean: true, + minify: true, + format: ["esm"], +}) From 1af57b0d0f871ea8430b32d5f2b3b953d1749c0b Mon Sep 17 00:00:00 2001 From: darckfast <21337578+Darckfast@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:56:35 -0300 Subject: [PATCH 2/8] feat: updated CI to use mise --- .github/workflows/pr.yml | 16 +++------------- mise.toml | 5 +++++ tsup.config.ts | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7c01ef2..b2fd247 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -1,6 +1,3 @@ -# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created -# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages - name: PR on: [pull_request] @@ -8,13 +5,6 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - name: Install pnpm - with: - version: 10 - - uses: actions/setup-node@v4 - with: - node-version: 22 - - run: pnpm i - - run: pnpm test + - uses: actions/checkout@v6 + - uses: jdx/mise-action@v4 + - run: mise test diff --git a/mise.toml b/mise.toml index 4b5061a..84a8bf3 100644 --- a/mise.toml +++ b/mise.toml @@ -2,9 +2,14 @@ node = "26" pnpm = "10.33" +[tasks.prepare] +run = "pnpm install" + [tasks.build] +depends = ["prepare"] run = "pnpx tsup && pnpx terser ./dist/index.js -o ./dist/index.js" [tasks.test] +depends = ["prepare"] run = "pnpm run test" diff --git a/tsup.config.ts b/tsup.config.ts index 702e3cc..0fda359 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -4,7 +4,7 @@ export default defineConfig({ entry: ['index.ts'], dts: true, splitting: false, - sourcemap: true, + sourcemap: false, clean: true, minify: true, format: ["esm"], From 6ad04edc78a7befcd3b0e6f0ffdcc31446918e80 Mon Sep 17 00:00:00 2001 From: darckfast <21337578+Darckfast@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:58:46 -0300 Subject: [PATCH 3/8] chore: renamed job --- .github/workflows/pr.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index b2fd247..9dd27ad 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -2,7 +2,7 @@ name: PR on: [pull_request] jobs: - build: + tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 From 2bae86a582547b1d7a78a4462ea8e669d5c0b059 Mon Sep 17 00:00:00 2001 From: darckfast <21337578+Darckfast@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:58:55 -0300 Subject: [PATCH 4/8] feat: moved publish into mise tasks --- .github/workflows/npm-publish.yml | 30 +++--------------------------- mise.toml | 3 +++ 2 files changed, 6 insertions(+), 27 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 94d7456..9df4c87 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -1,6 +1,3 @@ -# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created -# For more information see: https://docs.github.com/en/actions/publishing-packages/publishing-nodejs-packages - name: Node.js Package on: @@ -8,35 +5,14 @@ on: types: [created] jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - name: Install pnpm - with: - version: 10 - - uses: actions/setup-node@v4 - with: - node-version: 22 - - run: pnpm i - - run: pnpm test - publish-npm: needs: build runs-on: ubuntu-latest permissions: id-token: write steps: - - uses: actions/checkout@v4 - - uses: pnpm/action-setup@v4 - name: Install pnpm - with: - version: 10 - - uses: actions/setup-node@v4 - with: - node-version: 22 - registry-url: https://registry.npmjs.org/ - - run: pnpm publish --access public --no-git-checks + - uses: actions/checkout@v6 + - uses: jdx/mise-action@v4 + - run: mise publish env: NODE_AUTH_TOKEN: ${{secrets.npm_token}} diff --git a/mise.toml b/mise.toml index 84a8bf3..5dad366 100644 --- a/mise.toml +++ b/mise.toml @@ -13,3 +13,6 @@ run = "pnpx tsup && pnpx terser ./dist/index.js -o ./dist/index.js" depends = ["prepare"] run = "pnpm run test" +[tasks.publish] +depends = ["prepare"] +run = "pnpm publish --access public --no-git-checks" From 902c4ccacf8c2df017732b9c517fcddc04ff5077 Mon Sep 17 00:00:00 2001 From: darckfast <21337578+Darckfast@users.noreply.github.com> Date: Wed, 17 Jun 2026 10:59:11 -0300 Subject: [PATCH 5/8] 1.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 551935b..7234e48 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "emotesjs", "description": "Fast, dependency free, and responsive 7TV inline emotes parse", - "version": "0.0.27", + "version": "1.0.0", "license": "MIT", "author": { "name": "darckfast" From 6f0c3e0e4a783ababc1e3f57bd4cebfe33d6b043 Mon Sep 17 00:00:00 2001 From: darckfast <21337578+Darckfast@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:00:18 -0300 Subject: [PATCH 6/8] chore: cleanup tsconfig file --- tsconfig.json | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index a8108a4..1bcad8f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,40 +1,18 @@ { - // Visit https://aka.ms/tsconfig to read more about this file "compilerOptions": { - // File Layout - // "rootDir": "./src", - // "outDir": "./dist", "ignoreDeprecations": "6.0", - // Environment Settings - // See also https://aka.ms/tsconfig/module "module": "nodenext", "target": "esnext", - "types": [], - // For nodejs: - // "lib": ["esnext"], - // "types": ["node"], - // and npm install -D @types/node - // Other Outputs "sourceMap": true, "declaration": true, "declarationMap": true, - // Stricter Typechecking Options "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, - // Style Options - // "noImplicitReturns": true, - // "noImplicitOverride": true, - // "noUnusedLocals": true, - // "noUnusedParameters": true, - // "noFallthroughCasesInSwitch": true, - // "noPropertyAccessFromIndexSignature": true, - // Recommended Options "strict": true, - "jsx": "react-jsx", "verbatimModuleSyntax": true, "isolatedModules": true, "noUncheckedSideEffectImports": true, "moduleDetection": "force", - "skipLibCheck": true, + "skipLibCheck": true } } From ddcd81ab02f0b61a6947aec2e591297ced36fe73 Mon Sep 17 00:00:00 2001 From: darckfast <21337578+Darckfast@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:04:04 -0300 Subject: [PATCH 7/8] feat: add basic usage on readme --- README.md | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/README.md b/README.md index 053ab47..8fcb794 100644 --- a/README.md +++ b/README.md @@ -6,4 +6,26 @@ Fast, dependency free, and responsive 7TV inline emotes parse +## Basic usage + +```sh +npm i emotesjs +``` + +```ts +import { EmotesJS } from 'emotesjs' + +let emotes = new EmotesJS({ channelId: 123456 }) + +let html = emotes.parse('this is pretty Pog') + +console.log(html) +// this is pretty Pog +``` + [Check the documentation here](https://darckfast.com/docs/emotesjs) From f62c91a524ee8125674eebd1c323442b1363160f Mon Sep 17 00:00:00 2001 From: darckfast <21337578+Darckfast@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:04:55 -0300 Subject: [PATCH 8/8] fix: fixed publish workflow --- .github/workflows/npm-publish.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 9df4c87..c9c98a8 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -6,7 +6,6 @@ on: jobs: publish-npm: - needs: build runs-on: ubuntu-latest permissions: id-token: write