diff --git a/package-lock.json b/package-lock.json index 68bda38..9ef3708 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@eslint/js": "^9.25.1", "@rollup/plugin-node-resolve": "^16.0.1", "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^12.1.2", "@types/node": "^22.15.3", "@vitest/coverage-v8": "^3.1.2", "@vitest/ui": "^3.1.2", @@ -35,6 +36,8 @@ "prettier": "^3.5.3", "rollup": "^4.40.1", "rollup-plugin-cleaner": "^1.0.0", + "rollup-plugin-scss": "^4.0.1", + "sass": "^1.87.0", "tslib": "^2.8.1", "typescript": "^5.8.3", "typescript-eslint": "^8.31.1", @@ -1333,6 +1336,316 @@ "node": ">= 8" } }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -1399,6 +1712,33 @@ } } }, + "node_modules/@rollup/plugin-typescript": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.1.2.tgz", + "integrity": "sha512-cdtSp154H5sv637uMr1a8OTWB0L1SWDSm1rDGiyfcGcvQ6cuTs4MDk2BVEBGysUWago4OJN4EQZqOTl/QY3Jgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0||^4.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, "node_modules/@rollup/pluginutils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.0.tgz", @@ -2893,6 +3233,22 @@ "node": ">= 0.8.0" } }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ci-info": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", @@ -3356,6 +3712,20 @@ "node": ">=0.4.0" } }, + "node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/dunder-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", @@ -4916,6 +5286,13 @@ "node": ">= 4" } }, + "node_modules/immutable": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.1.tgz", + "integrity": "sha512-3jatXi9ObIsPGr3N5hGw/vWWcTkq6hUYhpQz4k0wLC+owqWi/LiugIw9x0EdNZ2yGedKN/HzePiBvaJRXa0Ujg==", + "dev": true, + "license": "MIT" + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", @@ -6036,6 +6413,14 @@ "dev": true, "license": "MIT" }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, "node_modules/node-releases": { "version": "2.0.19", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", @@ -6577,6 +6962,20 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/refa": { "version": "0.12.1", "resolved": "https://registry.npmjs.org/refa/-/refa-0.12.1.tgz", @@ -6799,6 +7198,33 @@ "rimraf": "bin.js" } }, + "node_modules/rollup-plugin-scss": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-scss/-/rollup-plugin-scss-4.0.1.tgz", + "integrity": "sha512-3W3+3OzR+shkDl3hJ1XTAuGkP4AfiLgIjie2GtcoZ9pHfRiNqeDbtCu1EUnkjZ98EPIM6nnMIXkKlc7Sx5bRvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "rollup-pluginutils": "^2.3.3" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/rollup-pluginutils/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true, + "license": "MIT" + }, "node_modules/rrweb-cssom": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", @@ -6905,6 +7331,27 @@ "dev": true, "license": "MIT" }, + "node_modules/sass": { + "version": "1.87.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.87.0.tgz", + "integrity": "sha512-d0NoFH4v6SjEK7BoX810Jsrhj7IQSYHAHLi/iSpgqKc7LaIDshFRlSg5LOymf9FqQhxEHs2W5ZQXlvy0KD45Uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", diff --git a/package.json b/package.json index d91dbb9..0d01b7d 100644 --- a/package.json +++ b/package.json @@ -16,8 +16,7 @@ "author": "Jeroen Akkerman", "repository": "github:Ionaru/easy-markdown-editor", "scripts": { - "clean": "npx rimraf dist", - "prebuild": "npm run clean", + "clean": "npx -y rimraf dist", "build": "rollup -c", "build:watch": "rollup -c -w", "build:types": "tsc --emitDeclarationOnly --declaration --outDir dist/types", @@ -43,6 +42,7 @@ "@eslint/js": "^9.25.1", "@rollup/plugin-node-resolve": "^16.0.1", "@rollup/plugin-terser": "^0.4.4", + "@rollup/plugin-typescript": "^12.1.2", "@types/node": "^22.15.3", "@vitest/coverage-v8": "^3.1.2", "@vitest/ui": "^3.1.2", @@ -56,6 +56,8 @@ "prettier": "^3.5.3", "rollup": "^4.40.1", "rollup-plugin-cleaner": "^1.0.0", + "rollup-plugin-scss": "^4.0.1", + "sass": "^1.87.0", "tslib": "^2.8.1", "typescript": "^5.8.3", "typescript-eslint": "^8.31.1", diff --git a/src/easymde.ts b/src/easymde.ts index e896f1c..b3ff309 100644 --- a/src/easymde.ts +++ b/src/easymde.ts @@ -17,15 +17,14 @@ import { InputOptions, Options } from "./options"; import "./styles.scss"; export class EasyMDE { - private readonly element: HTMLTextAreaElement; + readonly #element: HTMLTextAreaElement; #container?: HTMLDivElement; #codemirror?: EditorView; - // private rendered = false; readonly #options: Options; - private readonly plugins: IEasyMDEPlugin[] = []; + readonly #plugins: IEasyMDEPlugin[] = []; - public constructor(options: InputOptions) { + constructor(options: InputOptions) { this.#options = { ...options, blockStyles: { @@ -35,33 +34,31 @@ export class EasyMDE { code: "`", }, }; - this.element = EasyMDE.verifyAndReturnElement(options.element); + this.#element = EasyMDE.#verifyAndReturnElement(options.element); marked.parse("# EasyMDE", { async: false }); // eslint-disable-next-line sonarjs/no-async-constructor void this.construct(); } - public get container(): HTMLDivElement { + get container(): HTMLDivElement { if (!this.#container) { throw new NotConstructedError(); } return this.#container; } - public get codemirror(): EditorView { + get codemirror(): EditorView { if (!this.#codemirror) { throw new NotConstructedError(); } return this.#codemirror; } - public get options(): Readonly { + get options(): Readonly { return Object.freeze(this.#options); } - private static verifyAndReturnElement( - element?: HTMLElement, - ): HTMLTextAreaElement { + static #verifyAndReturnElement(element?: HTMLElement): HTMLTextAreaElement { if (!(element instanceof HTMLTextAreaElement)) { throw new TypeError( 'EasyMDE: Parameter "element" must be a TextArea.', @@ -71,11 +68,11 @@ export class EasyMDE { return element; } - public get isRendered(): boolean { + get isRendered(): boolean { return Boolean(this.container && this.codemirror); } - public async construct(): Promise { + async construct(): Promise { if (this.#container && this.#codemirror) { throw new AlreadyConstructedError(); } @@ -126,10 +123,10 @@ export class EasyMDE { }, ]); - this.element.hidden = true; + this.#element.hidden = true; this.#codemirror = new EditorView({ state: EditorState.create({ - doc: this.element.value, + doc: this.#element.value, extensions: [ syntaxHighlighting(highlightStyle), syntaxHighlighting(defaultHighlightStyle), @@ -140,35 +137,35 @@ export class EasyMDE { drawSelection(), ], selection: { - anchor: this.element.value.length, + anchor: this.#element.value.length, }, }), // parent: this.element.parentElement || document.body, }); - const easyMDEContainer = this.createContainer(); + const easyMDEContainer = this.#createContainer(); if (this.options.toolbar !== false) { - easyMDEContainer.append(await this.createToolbar()); + easyMDEContainer.append(await this.#createToolbar()); } easyMDEContainer.append(this.codemirror.dom); if (this.options.statusbar !== false) { - easyMDEContainer.append(await this.createStatusBar()); + easyMDEContainer.append(await this.#createStatusBar()); } - this.element.insertAdjacentElement("afterend", easyMDEContainer); + this.#element.insertAdjacentElement("afterend", easyMDEContainer); this.codemirror.focus(); this.#container = easyMDEContainer; } - public destruct(): void { - this.element.value = this.codemirror.state.doc.toString(); + destruct(): void { + this.#element.value = this.codemirror.state.doc.toString(); - for (const plugin of this.plugins) { + for (const plugin of this.#plugins) { void plugin.destroy(); } @@ -178,15 +175,15 @@ export class EasyMDE { this.#container = undefined; this.#codemirror = undefined; - this.element.hidden = false; + this.#element.hidden = false; } - public addPlugin(plugin: IEasyMDEPlugin): IEasyMDEPlugin { - this.plugins.push(plugin); + addPlugin(plugin: IEasyMDEPlugin): IEasyMDEPlugin { + this.#plugins.push(plugin); return plugin; } - private async createToolbar(): Promise { + async #createToolbar(): Promise { const [{ Toolbar }, { defaultToolbar }] = await Promise.all([ importToolbar(), importDefaultToolbar(), @@ -197,13 +194,13 @@ export class EasyMDE { return toolbar.element; } - private async createStatusBar(): Promise { + async #createStatusBar(): Promise { const { StatusBar } = await import("./status-bar/status-bar"); const statusBar = new StatusBar(this); return statusBar.element; } - private createContainer(): HTMLDivElement { + #createContainer(): HTMLDivElement { const container = document.createElement("div"); container.classList.add("easymde-container"); return container; diff --git a/src/errors/already-constructed-error.ts b/src/errors/already-constructed-error.ts index 3ebb956..c8a4ee7 100644 --- a/src/errors/already-constructed-error.ts +++ b/src/errors/already-constructed-error.ts @@ -1,5 +1,5 @@ export class AlreadyConstructedError extends Error { - public constructor() { + constructor() { super("EasyMDE is already initialized."); this.name = "AlreadyConstructedError"; } diff --git a/src/errors/not-constructed-error.ts b/src/errors/not-constructed-error.ts index 1ae4fa7..fac68b5 100644 --- a/src/errors/not-constructed-error.ts +++ b/src/errors/not-constructed-error.ts @@ -1,5 +1,5 @@ export class NotConstructedError extends Error { - public constructor() { + constructor() { super( 'EasyMDE is not initialized, run the "construct()" method to do so.', ); diff --git a/src/status-bar/status-bar.ts b/src/status-bar/status-bar.ts index f9ef701..0c75d1f 100644 --- a/src/status-bar/status-bar.ts +++ b/src/status-bar/status-bar.ts @@ -5,34 +5,34 @@ import { EasyMDE } from "../easymde"; import { countWords } from "../utils/count-words"; export class StatusBar { - public element: HTMLDivElement; + element: HTMLDivElement; - private characterCount = 0; - private wordCount = 0; - private lineCount = 1; - private cursorLine = 1; - private cursorColumn = 1; + #characterCount = 0; + #wordCount = 0; + #lineCount = 1; + #cursorLine = 1; + #cursorColumn = 1; - private selectionStart = 0; - private selectionEnd = 0; + #selectionStart = 0; + #selectionEnd = 0; - public constructor(private editor: EasyMDE) { + constructor(private editor: EasyMDE) { this.element = document.createElement("div"); this.element.className = "easymde-statusbar"; // Initial values - this.characterCount = this.editor.codemirror.state.doc.length; - this.wordCount = countWords(this.editor.codemirror.state.doc); - this.lineCount = this.editor.codemirror.state.doc.lines; + this.#characterCount = this.editor.codemirror.state.doc.length; + this.#wordCount = countWords(this.editor.codemirror.state.doc); + this.#lineCount = this.editor.codemirror.state.doc.lines; const line = this.editor.codemirror.state.doc.lineAt( this.editor.codemirror.state.selection.main.to, ); - this.cursorLine = line.number; - this.cursorColumn = + this.#cursorLine = line.number; + this.#cursorColumn = this.editor.codemirror.state.selection.main.to - line.from + 1; - this.selectionStart = this.editor.codemirror.state.selection.main.from; - this.selectionEnd = this.editor.codemirror.state.selection.main.to; + this.#selectionStart = this.editor.codemirror.state.selection.main.from; + this.#selectionEnd = this.editor.codemirror.state.selection.main.to; this.editor.codemirror.dispatch({ effects: StateEffect.appendConfig.of( @@ -41,11 +41,12 @@ export class StatusBar { const document = update.state.doc; const selection = update.state.selection.main; - this.characterCount = document.length; - this.wordCount = countWords(document); - this.lineCount = document.lines; + this.#characterCount = document.length; + this.#wordCount = countWords(document); + this.#lineCount = document.lines; - const direction = this.getSelectionDirection(selection); + const direction = + this.#getSelectionDirection(selection); const toLine = document.lineAt(selection.to); const fromLine = document.lineAt(selection.from); @@ -54,25 +55,25 @@ export class StatusBar { if (direction === "left") { // Cursor is at the start of the selection. cursorLine = fromLine; - this.cursorColumn = + this.#cursorColumn = selection.from - cursorLine.from; } else { // Cursor is at the end of the selection, or there is no selection. cursorLine = toLine; - this.cursorColumn = selection.to - cursorLine.from; + this.#cursorColumn = selection.to - cursorLine.from; - if (this.cursorColumn > toLine.length) { + if (this.#cursorColumn > toLine.length) { // Column is incorrect, can happen when Ctrl+A is used. We need to manually adjust it. - this.cursorColumn = toLine.length; + this.#cursorColumn = toLine.length; } } - this.cursorLine = cursorLine.number; - this.selectionStart = selection.from; - this.selectionEnd = selection.to; + this.#cursorLine = cursorLine.number; + this.#selectionStart = selection.from; + this.#selectionEnd = selection.to; // We start counting columns at 1. - this.cursorColumn++; + this.#cursorColumn++; this.render(); }, @@ -83,22 +84,22 @@ export class StatusBar { this.render(); } - public render() { + render() { this.element.innerHTML = ` - Lines: ${this.lineCount} - Words: ${this.wordCount} - Characters: ${this.characterCount} - Pos: ${this.cursorLine}:${this.cursorColumn} + Lines: ${this.#lineCount} + Words: ${this.#wordCount} + Characters: ${this.#characterCount} + Pos: ${this.#cursorLine}:${this.#cursorColumn} `; } - private getSelectionDirection( + #getSelectionDirection( selection: SelectionRange, ): "right" | "left" | undefined { - return selection.from === this.selectionStart + return selection.from === this.#selectionStart ? "right" : // eslint-disable-next-line sonarjs/no-nested-conditional - selection.to === this.selectionEnd + selection.to === this.#selectionEnd ? "left" : undefined; } diff --git a/src/styles.scss b/src/styles.scss index 34b3b12..380667d 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -1,10 +1,12 @@ +@use "sass:color"; + $light-border-color: #d1d1d1; :root { --easymde-border-color: #{$light-border-color}; - --easymde-enabled-color: #{lighten($light-border-color, 5%)}; + --easymde-enabled-color: #{color.adjust($light-border-color, $lightness: 5%)}; --easymde-hover-color: #{$light-border-color}; - --easymde-active-color: #{darken($light-border-color, 5%)}; + --easymde-active-color: #{color.adjust($light-border-color, $lightness: -5%)}; } // @media (prefers-color-scheme: dark) { diff --git a/src/toolbar/toolbar.ts b/src/toolbar/toolbar.ts index 891e55b..72a9ff9 100644 --- a/src/toolbar/toolbar.ts +++ b/src/toolbar/toolbar.ts @@ -6,11 +6,11 @@ import { EasyMDE, IEasyMDEPlugin } from "../easymde"; import { IToolbarButtonOptions } from "./default-toolbar"; export class Toolbar implements IEasyMDEPlugin { - private static readonly activeClass = "enabled"; + static readonly #activeClass = "enabled"; - public element: HTMLDivElement; + element: HTMLDivElement; - public constructor( + constructor( private editor: EasyMDE, toolbarLayout: IToolbarButtonOptions[][], ) { @@ -22,7 +22,7 @@ export class Toolbar implements IEasyMDEPlugin { for (const toolBarButtonOptions of toolBarButtonSection) { toolBarSection.push( - this.createToolBarButton(toolBarButtonOptions), + this.#createToolBarButton(toolBarButtonOptions), ); } @@ -31,7 +31,7 @@ export class Toolbar implements IEasyMDEPlugin { toolbarLayout.indexOf(toolBarButtonSection) !== toolbarLayout.length - 1 ) { - toolBarSection.push(this.createToolBarSeparator()); + toolBarSection.push(this.#createToolBarSeparator()); } for (const toolBarEntry of toolBarSection) { @@ -52,13 +52,13 @@ export class Toolbar implements IEasyMDEPlugin { } // eslint-disable-next-line @typescript-eslint/require-await - public async build(toolbarLayout: IToolbarButtonOptions[][]) { + async build(toolbarLayout: IToolbarButtonOptions[][]) { for (const toolBarButtonSection of toolbarLayout) { const toolBarSection: (HTMLButtonElement | HTMLSpanElement)[] = []; for (const toolBarButtonOptions of toolBarButtonSection) { toolBarSection.push( - this.createToolBarButton(toolBarButtonOptions), + this.#createToolBarButton(toolBarButtonOptions), ); } @@ -67,7 +67,7 @@ export class Toolbar implements IEasyMDEPlugin { toolbarLayout.indexOf(toolBarButtonSection) !== toolbarLayout.length - 1 ) { - toolBarSection.push(this.createToolBarSeparator()); + toolBarSection.push(this.#createToolBarSeparator()); } for (const toolBarEntry of toolBarSection) { @@ -76,18 +76,18 @@ export class Toolbar implements IEasyMDEPlugin { } } // eslint-disable-next-line @typescript-eslint/require-await - public async destroy() { + async destroy() { this.element.remove(); } - private createToolBarSeparator() { + #createToolBarSeparator() { const separatorElement = document.createElement("span"); separatorElement.className = "separator"; separatorElement.innerHTML = "|"; return separatorElement; } - private createToolBarButton( + #createToolBarButton( toolBarButtonOptions: IToolbarButtonOptions, ): HTMLButtonElement { const buttonElement: HTMLButtonElement = @@ -114,7 +114,7 @@ export class Toolbar implements IEasyMDEPlugin { if (typeof toolBarButtonOptions.active === "boolean") { buttonElement.classList.toggle( - Toolbar.activeClass, + Toolbar.#activeClass, toolBarButtonOptions.active, ); } else if (typeof toolBarButtonOptions.active === "function") { @@ -132,7 +132,7 @@ export class Toolbar implements IEasyMDEPlugin { update, ); buttonElement.classList.toggle( - Toolbar.activeClass, + Toolbar.#activeClass, result, ); }