diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml
index 94d7456..c9c98a8 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,13 @@ 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/.github/workflows/pr.yml b/.github/workflows/pr.yml
index 7c01ef2..9dd27ad 100644
--- a/.github/workflows/pr.yml
+++ b/.github/workflows/pr.yml
@@ -1,20 +1,10 @@
-# 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]
jobs:
- build:
+ tests:
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/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
+```
+
[Check the documentation here](https://darckfast.com/docs/emotesjs)
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..5dad366
--- /dev/null
+++ b/mise.toml
@@ -0,0 +1,18 @@
+[tools]
+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"
+
+[tasks.publish]
+depends = ["prepare"]
+run = "pnpm publish --access public --no-git-checks"
diff --git a/package.json b/package.json
index 2e03c63..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"
@@ -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..1bcad8f
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,18 @@
+{
+ "compilerOptions": {
+ "ignoreDeprecations": "6.0",
+ "module": "nodenext",
+ "target": "esnext",
+ "sourceMap": true,
+ "declaration": true,
+ "declarationMap": true,
+ "noUncheckedIndexedAccess": true,
+ "exactOptionalPropertyTypes": true,
+ "strict": true,
+ "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..0fda359
--- /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: false,
+ clean: true,
+ minify: true,
+ format: ["esm"],
+})