├── .gitignore
├── .prettierrc.json
├── README.md
├── dist
├── index.d.ts
├── index.d.ts.map
├── index.js
└── src
│ └── utils
│ ├── makeStylesInline.d.ts
│ ├── makeStylesInline.d.ts.map
│ ├── makeStylesInline.js
│ ├── makeStylesInline.test.d.ts
│ ├── makeStylesInline.test.d.ts.map
│ ├── makeStylesInline.test.js
│ ├── rgbToHex.d.ts
│ ├── rgbToHex.d.ts.map
│ └── rgbToHex.js
├── eslint.config.mjs
├── index.ts
├── jest.config.js
├── package-lock.json
├── package.json
├── src
├── mocks
│ └── example-template.html
└── utils
│ ├── makeStylesInline.test.ts
│ ├── makeStylesInline.ts
│ └── rgbToHex.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
3 | .idea
4 |
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "semi": true,
3 | "singleQuote": true
4 | }
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tailwind to Inline styles converter
2 |
3 | ### 🚀 Problem Solved
4 | This package addresses a common challenge in email template creation: the need for inline styles. With tailwind-to-inline, you can:
5 |
6 | - Quickly craft your templates using Tailwind CSS
7 | - Automatically convert Tailwind classes to inline styles
8 | - Generate email-ready HTML templates effortlessly
9 |
10 | No more manual inline styling - save time and reduce errors in your email template workflow!
11 |
12 |
13 | ### 🔥 Top Features
14 |
15 | - Effortless Conversion: Transform Tailwind classes to inline styles with a single function call
16 | - Dynamic Content Support: Easily replace placeholders in your templates
17 | - Time-Saving: Eliminate the need for manual inline styling in email templates
18 |
19 |
20 | ### Installation
21 | `npm install tailwind-to-inline`
22 |
23 |
24 | ### Usage
25 |
26 | ```js
27 | import { makeStylesInline } from 'tailwind-to-inline';
28 | ...
29 | const htmlTemplate = await makeStylesInline('templates/welcome-email.html', {
30 | name: 'John',
31 | cta_text: 'Complete Profile'
32 | };
33 | ```
34 |
35 |
36 | ### Parameters
37 |
38 | `templatePath`
39 | Path to the template file.
40 |
41 | `placeholderValues` *(optional)*
42 | A key-value pair object to replace dynamic content in the template.
43 |
44 |
45 | ### Example
46 | #### Original template `welcome-email.html`:
47 |
48 | ```html
49 |
50 |
51 |
52 | Welcome, {{name}}
53 |
54 |
59 |
60 |
61 | ```
62 |
63 | #### Converted result:
64 |
65 | ```html
66 |
67 |
68 |
69 | Welcome, John
70 |
71 |
76 |
77 |
78 | ```
79 |
80 | ### 🤝 Contributing
81 |
82 | Contributions, issues, and feature requests are welcome!
83 |
84 | ### 📄 License
85 |
86 | This project is MIT licensed.
87 |
--------------------------------------------------------------------------------
/dist/index.d.ts:
--------------------------------------------------------------------------------
1 | import { makeStylesInline } from './src/utils/makeStylesInline';
2 | export { makeStylesInline };
3 | //# sourceMappingURL=index.d.ts.map
--------------------------------------------------------------------------------
/dist/index.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
--------------------------------------------------------------------------------
/dist/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.makeStylesInline = void 0;
4 | const makeStylesInline_1 = require("./src/utils/makeStylesInline");
5 | Object.defineProperty(exports, "makeStylesInline", { enumerable: true, get: function () { return makeStylesInline_1.makeStylesInline; } });
6 |
--------------------------------------------------------------------------------
/dist/src/utils/makeStylesInline.d.ts:
--------------------------------------------------------------------------------
1 | type TMakeStylesInline = (templatePath: string, placeholderValues?: {
2 | [key: string]: string;
3 | }) => Promise;
4 | export declare const makeStylesInline: TMakeStylesInline;
5 | export {};
6 | //# sourceMappingURL=makeStylesInline.d.ts.map
--------------------------------------------------------------------------------
/dist/src/utils/makeStylesInline.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"makeStylesInline.d.ts","sourceRoot":"","sources":["../../../src/utils/makeStylesInline.ts"],"names":[],"mappings":"AASA,KAAK,iBAAiB,GAAG,CACvB,YAAY,EAAE,MAAM,EACpB,iBAAiB,CAAC,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAE,KAC1C,OAAO,CAAC,MAAM,CAAC,CAAC;AA6DrB,eAAO,MAAM,gBAAgB,EAAE,iBAW9B,CAAC"}
--------------------------------------------------------------------------------
/dist/src/utils/makeStylesInline.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14 | Object.defineProperty(o, "default", { enumerable: true, value: v });
15 | }) : function(o, v) {
16 | o["default"] = v;
17 | });
18 | var __importStar = (this && this.__importStar) || function (mod) {
19 | if (mod && mod.__esModule) return mod;
20 | var result = {};
21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22 | __setModuleDefault(result, mod);
23 | return result;
24 | };
25 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
26 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
27 | return new (P || (P = Promise))(function (resolve, reject) {
28 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
29 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
30 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
31 | step((generator = generator.apply(thisArg, _arguments || [])).next());
32 | });
33 | };
34 | var __importDefault = (this && this.__importDefault) || function (mod) {
35 | return (mod && mod.__esModule) ? mod : { "default": mod };
36 | };
37 | Object.defineProperty(exports, "__esModule", { value: true });
38 | exports.makeStylesInline = void 0;
39 | const fs = __importStar(require("fs"));
40 | const juice_1 = __importDefault(require("juice"));
41 | const handlebars_1 = __importDefault(require("handlebars"));
42 | const postcss_1 = __importDefault(require("postcss"));
43 | const tailwindcss_1 = __importDefault(require("tailwindcss"));
44 | const autoprefixer_1 = __importDefault(require("autoprefixer"));
45 | const rgbToHex_1 = require("./rgbToHex");
46 | const processTailwindCSS = (html) => __awaiter(void 0, void 0, void 0, function* () {
47 | const tailwindConfig = {
48 | content: [{ raw: html, extension: 'html' }],
49 | corePlugins: {
50 | preflight: false,
51 | },
52 | };
53 | const result = yield (0, postcss_1.default)([
54 | (0, tailwindcss_1.default)(tailwindConfig),
55 | autoprefixer_1.default,
56 | ]).process('@tailwind components; @tailwind utilities;', {
57 | from: undefined,
58 | });
59 | return result.css;
60 | });
61 | const simplifyColors = (css) => {
62 | // Remove CSS variables coming from Tailwind (starting with "--tw-...")
63 | const generalSimplifications = css
64 | .replace(/rgb\(([^)]+)\) \/ var\(--tw-[^)]+\)/g, 'rgb($1)')
65 | .replace(/rgba\(([^,]+),([^,]+),([^,]+),var\(--tw-[^)]+\)\)/g, 'rgba($1,$2,$3,1)')
66 | .replace(/var\(--tw-[^)]+\)/g, '1')
67 | .replace(/--tw-[^:]+:[^;]+;/g, '');
68 | // Since email agents like Gmail don't allow using `rgb()` colors, we replace them with their `hex` counterparts
69 | const hexColorsInsteadOfRgb = generalSimplifications.replaceAll(/(rgba?\(\d+\s+\d+\s+\d+\s*\/.*\))/g, (match) => {
70 | return (0, rgbToHex_1.rgbToHex)(match);
71 | });
72 | return hexColorsInsteadOfRgb;
73 | };
74 | const removeCssClasses = (css) => {
75 | return css.replaceAll(/\s*class=["'][^"']*["']/g, '');
76 | };
77 | const inlineStyles = (html) => __awaiter(void 0, void 0, void 0, function* () {
78 | const tailwindCss = yield processTailwindCSS(html);
79 | const simplifiedCss = simplifyColors(tailwindCss);
80 | return (0, juice_1.default)(html, {
81 | extraCss: simplifiedCss,
82 | applyStyleTags: true,
83 | removeStyleTags: true,
84 | preserveMediaQueries: true,
85 | preserveFontFaces: true,
86 | preserveImportant: true,
87 | inlinePseudoElements: true,
88 | });
89 | });
90 | const makeStylesInline = (templatePath, data) => __awaiter(void 0, void 0, void 0, function* () {
91 | const templateSource = fs.readFileSync(templatePath, 'utf8');
92 | const template = handlebars_1.default.compile(templateSource);
93 | const html = template(data);
94 | const inlinedStyles = yield inlineStyles(html);
95 | return removeCssClasses(inlinedStyles);
96 | });
97 | exports.makeStylesInline = makeStylesInline;
98 |
--------------------------------------------------------------------------------
/dist/src/utils/makeStylesInline.test.d.ts:
--------------------------------------------------------------------------------
1 | export {};
2 | //# sourceMappingURL=makeStylesInline.test.d.ts.map
--------------------------------------------------------------------------------
/dist/src/utils/makeStylesInline.test.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"makeStylesInline.test.d.ts","sourceRoot":"","sources":["../../../src/utils/makeStylesInline.test.ts"],"names":[],"mappings":""}
--------------------------------------------------------------------------------
/dist/src/utils/makeStylesInline.test.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4 | return new (P || (P = Promise))(function (resolve, reject) {
5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8 | step((generator = generator.apply(thisArg, _arguments || [])).next());
9 | });
10 | };
11 | Object.defineProperty(exports, "__esModule", { value: true });
12 | const makeStylesInline_1 = require("./makeStylesInline");
13 | describe('renderEmailFromTemplate', () => {
14 | const templatePath = 'src/mocks/example-template.html';
15 | test('should render email from template', () => __awaiter(void 0, void 0, void 0, function* () {
16 | const placeholderValues = {
17 | name: 'John Doe',
18 | thank_you: 'Thank you for signing up!',
19 | cta_link: 'https://example.com',
20 | cta_text: 'See all features',
21 | };
22 | const inlinedHtml = yield (0, makeStylesInline_1.makeStylesInline)(templatePath, placeholderValues);
23 | expect(inlinedHtml).toEqual(`
24 |
25 | Test title
26 |
27 |
28 |
29 | Welcome, John Doe
30 |
31 |
34 |
35 |
36 | `);
37 | }));
38 | });
39 |
--------------------------------------------------------------------------------
/dist/src/utils/rgbToHex.d.ts:
--------------------------------------------------------------------------------
1 | export declare const rgbToHex: (rgb: string) => string;
2 | //# sourceMappingURL=rgbToHex.d.ts.map
--------------------------------------------------------------------------------
/dist/src/utils/rgbToHex.d.ts.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"rgbToHex.d.ts","sourceRoot":"","sources":["../../../src/utils/rgbToHex.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ,QAAS,MAAM,WAqBnC,CAAC"}
--------------------------------------------------------------------------------
/dist/src/utils/rgbToHex.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.rgbToHex = void 0;
4 | const rgbToHex = (rgb) => {
5 | // Regular expression to match RGB(A) values
6 | const rgbRegex = /rgba?\((\d+)\s*,?\s*(\d+)\s*,?\s*(\d+)\s*(?:,?\s*\/?\s*(?:\d*\.?\d+)?)?\)/i;
7 | const match = rgb.match(rgbRegex);
8 | if (!match) {
9 | throw new Error('Invalid RGB string format');
10 | }
11 | // Extract RGB values
12 | const [, r, g, b] = match.map(Number);
13 | // Ensure values are within 0-255 range
14 | const clamp = (value) => Math.max(0, Math.min(255, value));
15 | // Convert to hex
16 | const toHex = (value) => clamp(value).toString(16).padStart(2, '0');
17 | return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
18 | };
19 | exports.rgbToHex = rgbToHex;
20 | // Example usage:
21 | // console.log(rgbToHex('rgba(59 130 246 / 1)')); // Output: #3b82f6
22 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import globals from "globals";
2 | import tseslint from "typescript-eslint";
3 |
4 | export default [
5 | {
6 | files: ["**/*.ts"],
7 | languageOptions: {
8 | globals: globals.browser,
9 | parser: tseslint.parser,
10 | parserOptions: {
11 | project: "./tsconfig.json",
12 | },
13 | },
14 | ignores: ["dist/**/*"],
15 | plugins: {
16 | "@typescript-eslint": tseslint.plugin,
17 | },
18 | rules: {
19 | ...tseslint.configs.recommended.rules,
20 | "no-console": ["error"],
21 | "no-unused-vars": "off",
22 | "@typescript-eslint/no-unused-vars": ["error"]
23 | },
24 | }
25 | ];
26 |
--------------------------------------------------------------------------------
/index.ts:
--------------------------------------------------------------------------------
1 | import { makeStylesInline } from './src/utils/makeStylesInline';
2 |
3 | export { makeStylesInline };
4 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | const jestConfig = {
2 | preset: 'ts-jest',
3 | testMatch: ['**/?(*.)+(spec|test).ts'],
4 | };
5 |
6 | module.exports = jestConfig;
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tailwind-to-inline",
3 | "version": "1.0.5",
4 | "description": "Convert HTML templates with Tailwind CSS classes to inline styles. Ideal for email templates, making Tailwind-styled emails compatible with major email clients.",
5 | "repository": {
6 | "type": "git",
7 | "url": "https://github.com/vardan-arm/tailwind-to-inline"
8 | },
9 | "bugs": {
10 | "url": "https://github.com/vardan-arm/tailwind-to-inline/issues"
11 | },
12 | "homepage": "https://github.com/vardan-arm/tailwind-to-inline#readme",
13 | "main": "dist/index.js",
14 | "types": "dist/index.d.ts",
15 | "files": [
16 | "dist/**/*"
17 | ],
18 | "scripts": {
19 | "start": "ts-node index.ts",
20 | "build": "rm -rf dist && tsc --outDir dist --declaration --declarationDir dist",
21 | "test": "jest",
22 | "lint": "eslint . --fix --config eslint.config.mjs",
23 | "format": "prettier --ignore-path .gitignore dist --write \"**/*.+(js|ts|json|html)\""
24 | },
25 | "keywords": [
26 | "tailwind",
27 | "inline-styles",
28 | "email-template",
29 | "converter",
30 | "css-inliner",
31 | "tailwind-inliner",
32 | "tailwind-email",
33 | "utility-classes",
34 | "responsive-email",
35 | "dynamic-template"
36 | ],
37 | "author": "Vardan Hakobyan",
38 | "license": "ISC",
39 | "devDependencies": {
40 | "@eslint/js": "^9.9.1",
41 | "@types/jest": "^29.5.12",
42 | "eslint": "^9.9.1",
43 | "globals": "^15.9.0",
44 | "jest": "^29.7.0",
45 | "prettier": "^3.3.3",
46 | "ts-jest": "^29.2.5",
47 | "ts-node": "^10.9.2",
48 | "typescript": "^5.5.4",
49 | "typescript-eslint": "^8.4.0"
50 | },
51 | "dependencies": {
52 | "autoprefixer": "^10.4.20",
53 | "fs": "^0.0.1-security",
54 | "handlebars": "^4.7.8",
55 | "juice": "^11.0.0",
56 | "postcss": "^8.4.43",
57 | "tailwindcss": "^3.4.10"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/mocks/example-template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Test title
4 |
5 |
6 |
7 | Welcome, {{name}}
8 |
9 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/utils/makeStylesInline.test.ts:
--------------------------------------------------------------------------------
1 | import { makeStylesInline } from './makeStylesInline';
2 |
3 | describe('renderEmailFromTemplate', () => {
4 | const templatePath = 'src/mocks/example-template.html';
5 |
6 | test('should render email from template', async () => {
7 | const placeholderValues = {
8 | name: 'John Doe',
9 | thank_you: 'Thank you for signing up!',
10 | cta_link: 'https://example.com',
11 | cta_text: 'See all features',
12 | };
13 |
14 | const inlinedHtml = await makeStylesInline(templatePath, placeholderValues);
15 |
16 | expect(inlinedHtml).toEqual(`
17 |
18 | Test title
19 |
20 |
21 |
22 | Welcome, John Doe
23 |
24 |
28 |
29 |
30 | `);
31 | });
32 | });
33 |
--------------------------------------------------------------------------------
/src/utils/makeStylesInline.ts:
--------------------------------------------------------------------------------
1 | import * as fs from 'fs';
2 | import juice from 'juice';
3 | import Handlebars from 'handlebars';
4 | import postcss from 'postcss';
5 | import tailwindcss from 'tailwindcss';
6 | import autoprefixer from 'autoprefixer';
7 |
8 | import { rgbToHex } from './rgbToHex';
9 |
10 | type TMakeStylesInline = (
11 | templatePath: string,
12 | placeholderValues?: { [key: string]: string },
13 | ) => Promise;
14 |
15 | const processTailwindCSS = async (html: string): Promise => {
16 | const tailwindConfig = {
17 | content: [{ raw: html, extension: 'html' }],
18 | corePlugins: {
19 | preflight: false,
20 | },
21 | };
22 |
23 | const result = await postcss([
24 | tailwindcss(tailwindConfig),
25 | autoprefixer,
26 | ]).process('@tailwind components; @tailwind utilities;', {
27 | from: undefined,
28 | });
29 |
30 | return result.css;
31 | };
32 |
33 | const simplifyColors = (css: string): string => {
34 | // Remove CSS variables coming from Tailwind (starting with "--tw-...")
35 | const generalSimplifications = css
36 | .replace(/rgb\(([^)]+)\) \/ var\(--tw-[^)]+\)/g, 'rgb($1)')
37 | .replace(
38 | /rgba\(([^,]+),([^,]+),([^,]+),var\(--tw-[^)]+\)\)/g,
39 | 'rgba($1,$2,$3,1)',
40 | )
41 | .replace(/var\(--tw-[^)]+\)/g, '1')
42 | .replace(/--tw-[^:]+:[^;]+;/g, '');
43 |
44 | // Since email agents like Gmail don't allow using `rgb()` colors, we replace them with their `hex` counterparts
45 | const hexColorsInsteadOfRgb = generalSimplifications.replaceAll(
46 | /(rgba?\(\d+\s+\d+\s+\d+\s*\/.*\))/g,
47 | (match) => {
48 | return rgbToHex(match);
49 | },
50 | );
51 |
52 | return hexColorsInsteadOfRgb;
53 | };
54 |
55 | const removeCssClasses = (css: string) => {
56 | // https://claude.ai/chat/9475aaf1-207a-4921-8b7d-f7a2b14c265f
57 | const regex = /\s*class=(['"])(?:(?!\1)[^\\]|\\.)*\1/g;
58 |
59 | return css.replaceAll(regex, '');
60 | };
61 |
62 | const inlineStyles = async (html: string): Promise => {
63 | const tailwindCss = await processTailwindCSS(html);
64 | const simplifiedCss = simplifyColors(tailwindCss);
65 |
66 | return juice(html, {
67 | extraCss: simplifiedCss,
68 | applyStyleTags: true,
69 | removeStyleTags: true,
70 | preserveMediaQueries: true,
71 | preserveFontFaces: true,
72 | preserveImportant: true,
73 | inlinePseudoElements: true,
74 | });
75 | };
76 |
77 | export const makeStylesInline: TMakeStylesInline = async (
78 | templatePath,
79 | data,
80 | ) => {
81 | const templateSource = fs.readFileSync(templatePath, 'utf8');
82 | const template = Handlebars.compile(templateSource);
83 | const html = template(data);
84 |
85 | const inlinedStyles = await inlineStyles(html);
86 |
87 | return removeCssClasses(inlinedStyles);
88 | };
89 |
--------------------------------------------------------------------------------
/src/utils/rgbToHex.ts:
--------------------------------------------------------------------------------
1 | export const rgbToHex = (rgb: string) => {
2 | // Regular expression to match RGB(A) values
3 | const rgbRegex =
4 | /rgba?\((\d+)\s*,?\s*(\d+)\s*,?\s*(\d+)\s*(?:,?\s*\/?\s*(?:\d*\.?\d+)?)?\)/i;
5 |
6 | const match = rgb.match(rgbRegex);
7 |
8 | if (!match) {
9 | throw new Error('Invalid RGB string format');
10 | }
11 |
12 | // Extract RGB values
13 | const [, r, g, b] = match.map(Number);
14 |
15 | // Ensure values are within 0-255 range
16 | const clamp = (value: number) => Math.max(0, Math.min(255, value));
17 |
18 | // Convert to hex
19 | const toHex = (value: number) => clamp(value).toString(16).padStart(2, '0');
20 |
21 | return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
22 | };
23 |
24 | // Example usage:
25 | // console.log(rgbToHex('rgba(59 130 246 / 1)')); // Output: #3b82f6
26 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es6",
4 | "module": "commonjs",
5 | "outDir": "dist",
6 | "declaration": true,
7 | "declarationMap": true,
8 | "declarationDir": "dist",
9 | "strict": true,
10 | "esModuleInterop": true,
11 | "lib": ["DOM", "ES2021.String"]
12 | },
13 | "include": ["**/*.ts"],
14 | "exclude": ["dist", "node_modules"]
15 | }
16 |
--------------------------------------------------------------------------------