├── apps ├── .gitkeep ├── demo-pro │ ├── src │ │ ├── config.js │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── test-setup.ts │ │ ├── styles.scss │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── favicon.ico │ │ ├── app │ │ │ ├── app.component.scss │ │ │ ├── app.component.ts │ │ │ └── app.component.html │ │ ├── index.html │ │ ├── main.ts │ │ └── polyfills.ts │ ├── tsconfig.editor.json │ ├── tsconfig.spec.json │ ├── tsconfig.app.json │ ├── .browserslistrc │ ├── jest.config.js │ ├── tsconfig.json │ ├── .eslintrc.json │ └── project.json ├── demo │ ├── src │ │ ├── styles.scss │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── test-setup.ts │ │ ├── favicon.ico │ │ ├── environments │ │ │ ├── environment.prod.ts │ │ │ └── environment.ts │ │ ├── app │ │ │ ├── app.component.scss │ │ │ ├── app.component.ts │ │ │ └── app.component.html │ │ ├── index.html │ │ ├── main.ts │ │ └── polyfills.ts │ ├── tsconfig.editor.json │ ├── tsconfig.spec.json │ ├── tsconfig.app.json │ ├── jest.config.ts │ ├── tsconfig.json │ ├── .eslintrc.json │ └── project.json ├── demo-e2e │ ├── src │ │ ├── support │ │ │ ├── app.po.ts │ │ │ ├── index.ts │ │ │ └── commands.ts │ │ ├── fixtures │ │ │ └── example.json │ │ └── integration │ │ │ └── app.spec.ts │ ├── .eslintrc.json │ ├── cypress.json │ ├── tsconfig.json │ └── project.json └── demo-pro-e2e │ ├── src │ ├── support │ │ ├── app.po.ts │ │ ├── index.ts │ │ └── commands.ts │ ├── fixtures │ │ └── example.json │ └── integration │ │ └── app.spec.ts │ ├── .eslintrc.json │ ├── cypress.json │ ├── tsconfig.json │ └── project.json ├── libs ├── .gitkeep ├── ngx-jodit │ ├── src │ │ ├── lib │ │ │ ├── ngx-jodit.component.scss │ │ │ ├── ngx-jodit.component.html │ │ │ ├── types.ts │ │ │ └── ngx-jodit.component.ts │ │ ├── index.ts │ │ └── test-setup.ts │ ├── ng-package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── jest.config.ts │ ├── tsconfig.json │ ├── .eslintrc.json │ ├── package.json │ ├── LICENSE │ ├── project.json │ ├── CHANGELOG.md │ └── README.md └── ngx-jodit-pro │ ├── src │ ├── lib │ │ ├── ngx-jodit-pro.component.scss │ │ ├── ngx-jodit-pro.component.html │ │ └── ngx-jodit-pro.component.ts │ ├── index.ts │ └── test-setup.ts │ ├── ng-package.json │ ├── tsconfig.lib.prod.json │ ├── tsconfig.spec.json │ ├── tsconfig.lib.json │ ├── .browserslistrc │ ├── jest.config.js │ ├── tsconfig.json │ ├── package.json │ ├── .eslintrc.json │ ├── project.json │ ├── CHANGELOG.md │ └── README.md ├── .eslintignore ├── .prettierrc ├── .husky └── commit-msg ├── .prettierignore ├── jest.config.ts ├── .vscode └── extensions.json ├── .editorconfig ├── tools └── tsconfig.tools.json ├── .commitlintrc.json ├── .github └── ISSUE_TEMPLATE │ ├── general-issue.md │ ├── ngx-jodit-related-issue.md │ └── ngx-jodit-pro-related-issue.md ├── jest.preset.js ├── tsconfig.base.json ├── .gitignore ├── .eslintrc.json ├── docs ├── runtime.c73397b5506956dd.js ├── index.html ├── 3rdpartylicenses.txt └── polyfills.e8c516cd4b0b98b5.js ├── decorate-angular-cli.js ├── package.json ├── nx.json ├── README.md └── migrations.json /apps/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /libs/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/demo-pro/src/config.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/demo/src/styles.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /apps/demo-pro/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/demo/src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /libs/ngx-jodit/src/lib/ngx-jodit.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true 3 | } 4 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/src/lib/ngx-jodit-pro.component.scss: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /apps/demo/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /apps/demo-pro/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | import 'jest-preset-angular/setup-jest'; 2 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/ngx-jodit-pro.component'; 2 | -------------------------------------------------------------------------------- /apps/demo-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/demo-pro-e2e/src/support/app.po.ts: -------------------------------------------------------------------------------- 1 | export const getGreeting = () => cy.get('h1'); 2 | -------------------------------------------------------------------------------- /apps/demo/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julianpoemp/ngx-jodit/HEAD/apps/demo/src/favicon.ico -------------------------------------------------------------------------------- /libs/ngx-jodit/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './lib/ngx-jodit.component'; 2 | export * from './lib/types'; 3 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit $1 5 | -------------------------------------------------------------------------------- /apps/demo-pro/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /apps/demo/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/demo-pro/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | }; 4 | -------------------------------------------------------------------------------- /apps/demo-pro/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/julianpoemp/ngx-jodit/HEAD/apps/demo-pro/src/favicon.ico -------------------------------------------------------------------------------- /libs/ngx-jodit/src/lib/ngx-jodit.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/src/lib/ngx-jodit-pro.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /apps/demo-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /apps/demo-pro-e2e/src/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io" 4 | } 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Add files here to ignore them from prettier formatting 2 | 3 | /dist 4 | /coverage 5 | 6 | .angular 7 | 8 | /.nx/cache 9 | /.nx/workspace-data -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | const { getJestProjectsAsync } = require('@nx/jest'); 2 | 3 | export default async () => ({ 4 | projects: await getJestProjectsAsync(), 5 | }); 6 | -------------------------------------------------------------------------------- /apps/demo/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/demo-pro/tsconfig.editor.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "include": ["**/*.ts"], 4 | "compilerOptions": { 5 | "types": ["jest", "node"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /apps/demo/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | textarea { 2 | width: 100%; 3 | min-height: 300px; 4 | } 5 | 6 | h2 { 7 | margin-top: 40px; 8 | } 9 | 10 | h3 { 11 | margin-top: 20px; 12 | } 13 | -------------------------------------------------------------------------------- /apps/demo-pro/src/app/app.component.scss: -------------------------------------------------------------------------------- 1 | textarea { 2 | width: 100%; 3 | min-height: 300px; 4 | } 5 | 6 | h2 { 7 | margin-top: 40px; 8 | } 9 | 10 | h3 { 11 | margin-top: 20px; 12 | } 13 | -------------------------------------------------------------------------------- /libs/ngx-jodit/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/ngx-jodit", 4 | "lib": { 5 | "entryFile": "src/index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/ng-package.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json", 3 | "dest": "../../dist/libs/ngx-jodit-pro", 4 | "lib": { 5 | "entryFile": "src/index.ts" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "angular.ng-template", 4 | "nrwl.angular-console", 5 | "esbenp.prettier-vscode", 6 | "firsttris.vscode-jest-runner", 7 | "dbaeumer.vscode-eslint" 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /libs/ngx-jodit/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false, 5 | "moduleResolution": "bundler" 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/demo-pro-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/tsconfig.lib.prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.lib.json", 3 | "compilerOptions": { 4 | "declarationMap": false, 5 | "moduleResolution": "bundler" 6 | }, 7 | "angularCompilerOptions": { 8 | "compilationMode": "partial" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/demo-pro/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ngx-jodit-demo pro 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /apps/demo/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ngx-jodit-demo 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /apps/demo-pro/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/ngx-jodit/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment 2 | globalThis.ngJest = { 3 | testEnvironmentOptions: { 4 | errorOnUnknownElements: true, 5 | errorOnUnknownProperties: true, 6 | }, 7 | }; 8 | import 'jest-preset-angular/setup-jest'; 9 | -------------------------------------------------------------------------------- /tools/tsconfig.tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "../dist/out-tsc/tools", 5 | "rootDir": ".", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": ["node"], 9 | "importHelpers": false 10 | }, 11 | "include": ["**/*.ts"] 12 | } 13 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/src/test-setup.ts: -------------------------------------------------------------------------------- 1 | // @ts-expect-error https://thymikee.github.io/jest-preset-angular/docs/getting-started/test-environment 2 | globalThis.ngJest = { 3 | testEnvironmentOptions: { 4 | errorOnUnknownElements: true, 5 | errorOnUnknownProperties: true, 6 | }, 7 | }; 8 | import 'jest-preset-angular/setup-jest'; 9 | -------------------------------------------------------------------------------- /apps/demo/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /libs/ngx-jodit/src/lib/types.ts: -------------------------------------------------------------------------------- 1 | import type {IViewOptions} from 'jodit/types/types'; 2 | import * as JoditESMConfig from 'jodit/config'; 3 | import * as JoditCoreConfig from 'jodit/types/config'; 4 | 5 | export type JoditConfig = Partial< 6 | Record & 7 | IViewOptions & 8 | JoditCoreConfig.Config & 9 | JoditESMConfig.Config 10 | >; 11 | -------------------------------------------------------------------------------- /.commitlintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "@commitlint/config-angular" 4 | ], 5 | "rules": { 6 | "type-enum": [1, "always", [ 7 | "build", 8 | "chore", 9 | "ci", 10 | "docs", 11 | "feat", 12 | "fix", 13 | "perf", 14 | "refactor", 15 | "revert", 16 | "style", 17 | "test" 18 | ]] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "types": ["jest", "node"] 7 | }, 8 | "files": ["src/test-setup.ts"], 9 | "include": [ 10 | "jest.config.ts", 11 | "src/**/*.test.ts", 12 | "src/**/*.spec.ts", 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /apps/demo-pro/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [], 6 | "target": "ES2022", 7 | "useDefineForClassFields": false, 8 | "moduleResolution": "bundler" 9 | }, 10 | "files": ["src/main.ts", "src/polyfills.ts"], 11 | "include": ["src/**/*.d.ts"], 12 | "exclude": ["**/*.test.ts", "**/*.spec.ts"] 13 | } 14 | -------------------------------------------------------------------------------- /libs/ngx-jodit/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "module": "commonjs", 6 | "target": "es2016", 7 | "types": ["jest", "node"] 8 | }, 9 | "files": ["src/test-setup.ts"], 10 | "include": [ 11 | "jest.config.ts", 12 | "src/**/*.test.ts", 13 | "src/**/*.spec.ts", 14 | "src/**/*.d.ts" 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /apps/demo/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "types": [], 6 | "target": "ES2022", 7 | "useDefineForClassFields": false, 8 | "moduleResolution": "bundler" 9 | }, 10 | "files": ["src/main.ts", "src/polyfills.ts"], 11 | "include": ["src/**/*.d.ts"], 12 | "exclude": ["**/*.test.ts", "**/*.spec.ts", "jest.config.ts"] 13 | } 14 | -------------------------------------------------------------------------------- /apps/demo-e2e/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 7 | "rules": {} 8 | }, 9 | { 10 | "files": ["src/plugins/index.js"], 11 | "rules": { 12 | "@typescript-eslint/no-var-requires": "off", 13 | "no-undef": "off" 14 | } 15 | } 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /apps/demo-e2e/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileServerFolder": ".", 3 | "fixturesFolder": "./src/fixtures", 4 | "integrationFolder": "./src/integration", 5 | "modifyObstructiveCode": false, 6 | "supportFile": "./src/support/index.ts", 7 | "pluginsFile": false, 8 | "video": true, 9 | "videosFolder": "../../dist/cypress/apps/demo-e2e/videos", 10 | "screenshotsFolder": "../../dist/cypress/apps/demo-e2e/screenshots", 11 | "chromeWebSecurity": false 12 | } 13 | -------------------------------------------------------------------------------- /apps/demo-pro-e2e/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "fileServerFolder": ".", 3 | "fixturesFolder": "./src/fixtures", 4 | "integrationFolder": "./src/integration", 5 | "modifyObstructiveCode": false, 6 | "supportFile": "./src/support/index.ts", 7 | "pluginsFile": false, 8 | "video": true, 9 | "videosFolder": "../../dist/cypress/apps/demo-pro-e2e/videos", 10 | "screenshotsFolder": "../../dist/cypress/apps/demo-pro-e2e/screenshots", 11 | "chromeWebSecurity": false 12 | } 13 | -------------------------------------------------------------------------------- /libs/ngx-jodit/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [], 9 | "moduleResolution": "bundler" 10 | }, 11 | "exclude": [ 12 | "src/**/*.spec.ts", 13 | "src/test-setup.ts", 14 | "jest.config.ts", 15 | "src/**/*.test.ts" 16 | ], 17 | "include": ["src/**/*.ts"] 18 | } 19 | -------------------------------------------------------------------------------- /apps/demo-e2e/src/integration/app.spec.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('demo', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome demo'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/tsconfig.lib.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../../dist/out-tsc", 5 | "declaration": true, 6 | "declarationMap": true, 7 | "inlineSources": true, 8 | "types": [], 9 | "moduleResolution": "bundler" 10 | }, 11 | "exclude": [ 12 | "src/**/*.spec.ts", 13 | "src/test-setup.ts", 14 | "jest.config.ts", 15 | "src/**/*.test.ts" 16 | ], 17 | "include": ["src/**/*.ts"] 18 | } 19 | -------------------------------------------------------------------------------- /apps/demo-pro-e2e/src/integration/app.spec.ts: -------------------------------------------------------------------------------- 1 | import { getGreeting } from '../support/app.po'; 2 | 3 | describe('demo-pro', () => { 4 | beforeEach(() => cy.visit('/')); 5 | 6 | it('should display welcome message', () => { 7 | // Custom command example, see `../support/commands.ts` file 8 | cy.login('my-email@something.com', 'myPassword'); 9 | 10 | // Function helper example, see `../support/app.po.ts` file 11 | getGreeting().contains('Welcome demo-pro'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/general-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: General issue 3 | about: Describe your issue related to this wrapper. Issues related to Jodit package 4 | should be created on the Jodit repository. 5 | title: '' 6 | labels: '' 7 | assignees: '' 8 | 9 | --- 10 | 11 | Describe the issue as detailed as possible, in a way I can reproduce it easily. 12 | 13 | Please answer additionally: 14 | 15 | - Is this issue related to ngx-jodit or ngx-jodit-pro? 16 | - What version of the package? 17 | - What Angular version are you using? 18 | -------------------------------------------------------------------------------- /apps/demo/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode, importProvidersFrom } from '@angular/core'; 2 | 3 | import { environment } from './environments/environment'; 4 | import { BrowserModule, bootstrapApplication } from '@angular/platform-browser'; 5 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 6 | import { AppComponent } from './app/app.component'; 7 | 8 | if (environment.production) { 9 | enableProdMode(); 10 | } 11 | 12 | bootstrapApplication(AppComponent, { 13 | providers: [ 14 | importProvidersFrom(BrowserModule, FormsModule, ReactiveFormsModule), 15 | ], 16 | }).catch((err) => console.error(err)); 17 | -------------------------------------------------------------------------------- /apps/demo-pro/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | -------------------------------------------------------------------------------- /apps/demo-e2e/src/support/index.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/demo-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true 14 | }, 15 | "include": ["src/**/*.ts", "src/**/*.js"], 16 | "angularCompilerOptions": { 17 | "strictInjectionParameters": true, 18 | "strictInputAccessModifiers": true, 19 | "strictTemplates": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/demo-pro-e2e/src/support/index.ts: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands'; 18 | -------------------------------------------------------------------------------- /apps/demo-pro-e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "compilerOptions": { 4 | "sourceMap": false, 5 | "outDir": "../../dist/out-tsc", 6 | "allowJs": true, 7 | "types": ["cypress", "node"], 8 | "forceConsistentCasingInFileNames": true, 9 | "strict": true, 10 | "noImplicitOverride": true, 11 | "noPropertyAccessFromIndexSignature": true, 12 | "noImplicitReturns": true, 13 | "noFallthroughCasesInSwitch": true 14 | }, 15 | "include": ["src/**/*.ts", "src/**/*.js"], 16 | "angularCompilerOptions": { 17 | "strictInjectionParameters": true, 18 | "strictInputAccessModifiers": true, 19 | "strictTemplates": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /apps/demo-pro/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode, importProvidersFrom } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | 5 | import { environment } from './environments/environment'; 6 | import { BrowserModule, bootstrapApplication } from '@angular/platform-browser'; 7 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 8 | import { AppComponent } from './app/app.component'; 9 | 10 | if (environment.production) { 11 | enableProdMode(); 12 | } 13 | 14 | bootstrapApplication(AppComponent, { 15 | providers: [importProvidersFrom(BrowserModule, FormsModule, ReactiveFormsModule)] 16 | }) 17 | .catch((err) => console.error(err)); 18 | -------------------------------------------------------------------------------- /jest.preset.js: -------------------------------------------------------------------------------- 1 | const nxPreset = require('@nx/jest/preset').default; 2 | 3 | module.exports = { 4 | ...nxPreset, 5 | /* TODO: Update to latest Jest snapshotFormat 6 | * By default Nx has kept the older style of Jest Snapshot formats 7 | * to prevent breaking of any existing tests with snapshots. 8 | * It's recommend you update to the latest format. 9 | * You can do this by removing snapshotFormat property 10 | * and running tests with --update-snapshot flag. 11 | * Example: "nx affected --targets=test --update-snapshot" 12 | * More info: https://jestjs.io/docs/upgrading-to-jest29#snapshot-format 13 | */ 14 | snapshotFormat: { escapeString: true, printBasicPrototype: true }, 15 | }; 16 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "rootDir": ".", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "importHelpers": true, 11 | "target": "es2015", 12 | "module": "esnext", 13 | "lib": ["es2017", "dom"], 14 | "skipLibCheck": true, 15 | "skipDefaultLibCheck": true, 16 | "allowSyntheticDefaultImports": true, 17 | "baseUrl": ".", 18 | "paths": { 19 | "ngx-jodit": ["libs/ngx-jodit/src/index.ts"], 20 | "ngx-jodit-pro": ["libs/ngx-jodit-pro/src/index.ts"] 21 | } 22 | }, 23 | "exclude": ["node_modules", "tmp"] 24 | } 25 | -------------------------------------------------------------------------------- /apps/demo-e2e/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-e2e", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/demo-e2e/src", 5 | "projectType": "application", 6 | "tags": [], 7 | "implicitDependencies": [ 8 | "demo" 9 | ], 10 | "targets": { 11 | "e2e": { 12 | "executor": "@nx/cypress:cypress", 13 | "options": { 14 | "cypressConfig": "apps/demo-e2e/cypress.json", 15 | "devServerTarget": "demo:serve:development" 16 | }, 17 | "configurations": { 18 | "production": { 19 | "devServerTarget": "demo:serve:production" 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nx/eslint:lint" 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /apps/demo/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/demo-pro/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /apps/demo-pro/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'demo-pro', 3 | preset: '../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsconfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | }, 10 | }, 11 | coverageDirectory: '../../coverage/apps/demo-pro', 12 | transform: { 13 | '^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular', 14 | }, 15 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 16 | snapshotSerializers: [ 17 | 'jest-preset-angular/build/serializers/no-ng-attributes', 18 | 'jest-preset-angular/build/serializers/ng-snapshot', 19 | 'jest-preset-angular/build/serializers/html-comment', 20 | ], 21 | }; 22 | -------------------------------------------------------------------------------- /libs/ngx-jodit/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'ngx-jodit', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | coverageDirectory: '../../coverage/libs/ngx-jodit', 7 | transform: { 8 | '^.+\\.(ts|mjs|js|html)$': [ 9 | 'jest-preset-angular', 10 | { 11 | tsconfig: '/tsconfig.spec.json', 12 | stringifyContentPathRegex: '\\.(html|svg)$', 13 | }, 14 | ], 15 | }, 16 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 17 | snapshotSerializers: [ 18 | 'jest-preset-angular/build/serializers/no-ng-attributes', 19 | 'jest-preset-angular/build/serializers/ng-snapshot', 20 | 'jest-preset-angular/build/serializers/html-comment', 21 | ], 22 | }; 23 | -------------------------------------------------------------------------------- /apps/demo/jest.config.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | export default { 3 | displayName: 'demo', 4 | preset: '../../jest.preset.js', 5 | setupFilesAfterEnv: ['/src/test-setup.ts'], 6 | globals: {}, 7 | coverageDirectory: '../../coverage/apps/demo', 8 | transform: { 9 | '^.+\\.(ts|mjs|js|html)$': [ 10 | 'jest-preset-angular', 11 | { 12 | tsconfig: '/tsconfig.spec.json', 13 | stringifyContentPathRegex: '\\.(html|svg)$', 14 | }, 15 | ], 16 | }, 17 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 18 | snapshotSerializers: [ 19 | 'jest-preset-angular/build/serializers/no-ng-attributes', 20 | 'jest-preset-angular/build/serializers/ng-snapshot', 21 | 'jest-preset-angular/build/serializers/html-comment', 22 | ], 23 | }; 24 | -------------------------------------------------------------------------------- /apps/demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "forceConsistentCasingInFileNames": true, 18 | "strict": true, 19 | "noImplicitOverride": true, 20 | "noPropertyAccessFromIndexSignature": true, 21 | "noImplicitReturns": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "target": "es2020" 24 | }, 25 | "angularCompilerOptions": { 26 | "strictInjectionParameters": true, 27 | "strictInputAccessModifiers": true, 28 | "strictTemplates": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | displayName: 'libs-ngx-jodit-pro', 3 | preset: '../../../jest.preset.js', 4 | setupFilesAfterEnv: ['/src/test-setup.ts'], 5 | globals: { 6 | 'ts-jest': { 7 | tsconfig: '/tsconfig.spec.json', 8 | stringifyContentPathRegex: '\\.(html|svg)$', 9 | }, 10 | }, 11 | coverageDirectory: '../../../coverage/libs/ngx-jodit-pro', 12 | transform: { 13 | '^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular', 14 | }, 15 | transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'], 16 | snapshotSerializers: [ 17 | 'jest-preset-angular/build/serializers/no-ng-attributes', 18 | 'jest-preset-angular/build/serializers/ng-snapshot', 19 | 'jest-preset-angular/build/serializers/html-comment', 20 | ], 21 | }; 22 | -------------------------------------------------------------------------------- /apps/demo-pro/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../../tsconfig.base.json", 3 | "files": [], 4 | "include": [], 5 | "references": [ 6 | { 7 | "path": "./tsconfig.app.json" 8 | }, 9 | { 10 | "path": "./tsconfig.spec.json" 11 | }, 12 | { 13 | "path": "./tsconfig.editor.json" 14 | } 15 | ], 16 | "compilerOptions": { 17 | "forceConsistentCasingInFileNames": true, 18 | "strict": true, 19 | "noImplicitOverride": true, 20 | "noPropertyAccessFromIndexSignature": true, 21 | "noImplicitReturns": true, 22 | "noFallthroughCasesInSwitch": true, 23 | "target": "es2020" 24 | }, 25 | "angularCompilerOptions": { 26 | "strictInjectionParameters": true, 27 | "strictInputAccessModifiers": true, 28 | "strictTemplates": true 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | 8 | # dependencies 9 | node_modules 10 | 11 | # IDEs and editors 12 | /.idea 13 | .project 14 | .classpath 15 | .c9/ 16 | *.launch 17 | .settings/ 18 | *.sublime-workspace 19 | 20 | # IDE - VSCode 21 | .vscode/* 22 | !.vscode/settings.json 23 | !.vscode/tasks.json 24 | !.vscode/launch.json 25 | !.vscode/extensions.json 26 | 27 | # misc 28 | /.sass-cache 29 | /connect.lock 30 | /coverage 31 | /libpeerconnection.log 32 | npm-debug.log 33 | yarn-error.log 34 | testem.log 35 | /typings 36 | 37 | # System Files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | .angular 42 | 43 | .nx/cache 44 | .nx/workspace-data 45 | .cursor/rules/nx-rules.mdc 46 | .github/instructions/nx.instructions.md 47 | -------------------------------------------------------------------------------- /libs/ngx-jodit/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.lib.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | } 21 | ], 22 | "extends": "../../tsconfig.base.json", 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2022", 4 | "useDefineForClassFields": false, 5 | "forceConsistentCasingInFileNames": true, 6 | "strict": true, 7 | "noImplicitOverride": true, 8 | "noPropertyAccessFromIndexSignature": true, 9 | "noImplicitReturns": true, 10 | "noFallthroughCasesInSwitch": true 11 | }, 12 | "files": [], 13 | "include": [], 14 | "references": [ 15 | { 16 | "path": "./tsconfig.lib.json" 17 | }, 18 | { 19 | "path": "./tsconfig.spec.json" 20 | } 21 | ], 22 | "extends": "../../tsconfig.base.json", 23 | "angularCompilerOptions": { 24 | "enableI18nLegacyMessageIdFormat": false, 25 | "strictInjectionParameters": true, 26 | "strictInputAccessModifiers": true, 27 | "strictTemplates": true 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /apps/demo-pro-e2e/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-pro-e2e", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "apps/demo-pro-e2e/src", 5 | "projectType": "application", 6 | "tags": [], 7 | "implicitDependencies": [ 8 | "demo-pro" 9 | ], 10 | "targets": { 11 | "e2e": { 12 | "executor": "@nrwl/cypress:cypress", 13 | "options": { 14 | "cypressConfig": "apps/demo-pro-e2e/cypress.json", 15 | "devServerTarget": "demo-pro:serve:development" 16 | }, 17 | "configurations": { 18 | "production": { 19 | "devServerTarget": "demo-pro:serve:production" 20 | } 21 | } 22 | }, 23 | "lint": { 24 | "executor": "@nrwl/linter:eslint", 25 | "outputs": ["{options.outputFile}"], 26 | "options": { 27 | "lintFilePatterns": ["apps/demo-pro-e2e/**/*.{js,ts}"] 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ngx-jodit-related-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ngx-jodit related issue 3 | about: Issue related to ngx-jodit (not Pro) 4 | title: 'ngx-jodit:' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 20 | 21 | ### Package versions 22 | 23 | | package | version | 24 | |---------------|---------| 25 | | Angular | | 26 | | ngx-jodit | | 27 | | jodit | | 28 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-jodit-pro", 3 | "description": "Angular wrapper for Jodit Pro WYSIWYG editor", 4 | "version": "3.0.1", 5 | "peerDependencies": { 6 | "@angular/common": ">=16.0.0", 7 | "@angular/core": ">=16.0.0", 8 | "jodit-pro": "^4.2.35", 9 | "jodit": "^4.2.38" 10 | }, 11 | "author": { 12 | "name": "Julian Poemp" 13 | }, 14 | "private": false, 15 | "keywords": [ 16 | "angular", 17 | "jodit", 18 | "html", 19 | "text", 20 | "editor", 21 | "wysisyg", 22 | "rich editor", 23 | "rich text editor", 24 | "rte", 25 | "typescript" 26 | ], 27 | "bugs": { 28 | "url": "https://github.com/julianpoemp/ngx-jodit/issues" 29 | }, 30 | "homepage": "https://julianpoemp.github.io/ngx-jodit/", 31 | "dependencies": { 32 | "tslib": "^2.3.0" 33 | }, 34 | "repository": { 35 | "type": "git", 36 | "url": "git+https://github.com/julianpoemp/ngx-jodit.git" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /apps/demo/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "jodit", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "jodit", 25 | "style": "kebab-case" 26 | } 27 | ], 28 | "@angular-eslint/prefer-standalone": "off" 29 | } 30 | }, 31 | { 32 | "files": ["*.html"], 33 | "extends": ["plugin:@nx/angular-template"], 34 | "rules": {} 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /apps/demo-pro/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "jodit", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "jodit", 25 | "style": "kebab-case" 26 | } 27 | ], 28 | "@angular-eslint/prefer-standalone": "off" 29 | } 30 | }, 31 | { 32 | "files": ["*.html"], 33 | "extends": ["plugin:@nx/angular-template"], 34 | "rules": {} 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /libs/ngx-jodit/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "rules": { 8 | "@angular-eslint/directive-selector": [ 9 | "error", 10 | { 11 | "type": "attribute", 12 | "prefix": "ngx", 13 | "style": "camelCase" 14 | } 15 | ], 16 | "@angular-eslint/component-selector": [ 17 | "error", 18 | { 19 | "type": "element", 20 | "prefix": "ngx", 21 | "style": "kebab-case" 22 | } 23 | ], 24 | "@angular-eslint/prefer-standalone": "off" 25 | }, 26 | "extends": [ 27 | "plugin:@nx/angular", 28 | "plugin:@angular-eslint/template/process-inline-templates" 29 | ] 30 | }, 31 | { 32 | "files": ["*.html"], 33 | "extends": ["plugin:@nx/angular-template"], 34 | "rules": {} 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /libs/ngx-jodit/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-jodit", 3 | "description": "Angular wrapper for jodit WYSIWYG editor", 4 | "version": "3.2.2", 5 | "peerDependencies": { 6 | "@angular/common": ">=16.0.0", 7 | "@angular/core": ">=16.0.0", 8 | "@angular/forms": ">=16.0.0", 9 | "jodit": "^4.5.0" 10 | }, 11 | "author": { 12 | "name": "Julian Poemp" 13 | }, 14 | "license": "MIT", 15 | "private": false, 16 | "keywords": [ 17 | "angular", 18 | "jodit", 19 | "html", 20 | "text", 21 | "editor", 22 | "wysisyg", 23 | "rich editor", 24 | "rich text editor", 25 | "rte", 26 | "typescript" 27 | ], 28 | "bugs": { 29 | "url": "https://github.com/julianpoemp/ngx-jodit/issues" 30 | }, 31 | "homepage": "https://julianpoemp.github.io/ngx-jodit/", 32 | "dependencies": { 33 | "tslib": "^2.3.0" 34 | }, 35 | "repository": { 36 | "type": "git", 37 | "url": "git+https://github.com/julianpoemp/ngx-jodit.git" 38 | }, 39 | "sideEffects": false 40 | } 41 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["../../../.eslintrc.json"], 3 | "ignorePatterns": ["!**/*"], 4 | "overrides": [ 5 | { 6 | "files": ["*.ts"], 7 | "extends": [ 8 | "plugin:@nrwl/nx/angular", 9 | "plugin:@angular-eslint/template/process-inline-templates" 10 | ], 11 | "rules": { 12 | "@angular-eslint/directive-selector": [ 13 | "error", 14 | { 15 | "type": "attribute", 16 | "prefix": "julianpoemp", 17 | "style": "camelCase" 18 | } 19 | ], 20 | "@angular-eslint/component-selector": [ 21 | "error", 22 | { 23 | "type": "element", 24 | "prefix": "julianpoemp", 25 | "style": "kebab-case" 26 | } 27 | ], 28 | "@angular-eslint/prefer-standalone": "off" 29 | } 30 | }, 31 | { 32 | "files": ["*.html"], 33 | "extends": ["plugin:@nrwl/nx/angular-template"], 34 | "rules": {} 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "ignorePatterns": ["**/*"], 4 | "plugins": ["@nx"], 5 | "overrides": [ 6 | { 7 | "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], 8 | "rules": { 9 | "@nx/enforce-module-boundaries": [ 10 | "error", 11 | { 12 | "enforceBuildableLibDependency": true, 13 | "allow": [], 14 | "depConstraints": [ 15 | { 16 | "sourceTag": "*", 17 | "onlyDependOnLibsWithTags": ["*"] 18 | } 19 | ] 20 | } 21 | ] 22 | } 23 | }, 24 | { 25 | "files": ["*.ts", "*.tsx"], 26 | "extends": ["plugin:@nx/typescript"], 27 | "rules": { 28 | "@typescript-eslint/no-extra-semi": "error", 29 | "no-extra-semi": "off" 30 | } 31 | }, 32 | { 33 | "files": ["*.js", "*.jsx"], 34 | "extends": ["plugin:@nx/javascript"], 35 | "rules": { 36 | "@typescript-eslint/no-extra-semi": "error", 37 | "no-extra-semi": "off" 38 | } 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /libs/ngx-jodit/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Julian Pömp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/ngx-jodit-pro-related-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: ngx-jodit-pro related issue 3 | about: Issue related to ngx-jodit-pro. Please checkout the demo on https://xdsoft.net/jodit/pro/ 4 | if this issue exists. If yes, it's not related to this package. 5 | title: 'ngx-jodit-pro:' 6 | labels: '' 7 | assignees: '' 8 | 9 | --- 10 | 11 | 21 | 22 | ### Package versions 23 | 24 | | package | version | 25 | |---------------|---------| 26 | | Angular | | 27 | | ngx-jodit-pro | | 28 | | jodit | | 29 | 30 | ### Activated plugins: 31 | 32 | - 33 | -------------------------------------------------------------------------------- /docs/runtime.c73397b5506956dd.js: -------------------------------------------------------------------------------- 1 | (()=>{"use strict";var e,s={},i={};function a(e){var n=i[e];if(void 0!==n)return n.exports;var r=i[e]={exports:{}};return s[e](r,r.exports,a),r.exports}a.m=s,e=[],a.O=(n,r,l,o)=>{if(!r){var c=1/0;for(t=0;t=o)&&Object.keys(a.O).every(p=>a.O[p](r[f]))?r.splice(f--,1):(d=!1,o0&&e[t-1][2]>o;t--)e[t]=e[t-1];e[t]=[r,l,o]},a.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return a.d(n,{a:n}),n},a.d=(e,n)=>{for(var r in n)a.o(n,r)&&!a.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:n[r]})},a.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),a.r=e=>{typeof Symbol<"u"&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e={666:0};a.O.j=l=>0===e[l];var n=(l,o)=>{var f,u,[t,c,d]=o,v=0;if(t.some(_=>0!==e[_])){for(f in c)a.o(c,f)&&(a.m[f]=c[f]);if(d)var b=d(a)}for(l&&l(o);v { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/demo-pro-e2e/src/support/commands.ts: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | 11 | // eslint-disable-next-line @typescript-eslint/no-namespace 12 | declare namespace Cypress { 13 | // eslint-disable-next-line @typescript-eslint/no-unused-vars 14 | interface Chainable { 15 | login(email: string, password: string): void; 16 | } 17 | } 18 | // 19 | // -- This is a parent command -- 20 | Cypress.Commands.add('login', (email, password) => { 21 | console.log('Custom command example: Login', email, password); 22 | }); 23 | // 24 | // -- This is a child command -- 25 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 26 | // 27 | // 28 | // -- This is a dual command -- 29 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 30 | // 31 | // 32 | // -- This will overwrite an existing command -- 33 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 34 | -------------------------------------------------------------------------------- /apps/demo-pro/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, ViewChild} from '@angular/core'; 2 | import {JoditProConfig, NgxJoditProComponent} from 'ngx-jodit-pro'; 3 | import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; 4 | 5 | interface FormWithJoditEditor { 6 | editor: string; 7 | } 8 | 9 | declare const Jodit: any; 10 | 11 | @Component({ 12 | selector: 'jodit-root', 13 | templateUrl: './app.component.html', 14 | styleUrls: ['./app.component.scss'], 15 | imports: [ 16 | FormsModule, 17 | NgxJoditProComponent, 18 | ReactiveFormsModule 19 | ] 20 | }) 21 | export class AppComponent { 22 | value = 'Some text'; 23 | formGroup = this.formBuilder.group({ 24 | editor: 'Some text in a reactive form', 25 | }); 26 | _optionsStr = ''; 27 | 28 | @ViewChild('ngxJodit') ngxJodit?: NgxJoditProComponent; 29 | 30 | get optionsStr(): string { 31 | return this._optionsStr; 32 | } 33 | 34 | set optionsStr(value: string) { 35 | this._optionsStr = value ?? ''; 36 | try { 37 | this.options = value !== '' ? JSON.parse(value) : undefined; 38 | } catch (e) { 39 | // ignore 40 | } 41 | } 42 | 43 | options: JoditProConfig = { 44 | tuneBlock: { 45 | popup: { 46 | p: Jodit.atom(['align', 'tune.up', 'tune.remove', 'tune.down']) 47 | } 48 | } 49 | }; 50 | 51 | constructor(private formBuilder: FormBuilder) { 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /libs/ngx-jodit/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-jodit", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "sourceRoot": "libs/ngx-jodit/src", 5 | "prefix": "ngx", 6 | "projectType": "library", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "@nx/angular:package", 11 | "outputs": ["{workspaceRoot}/dist/{projectRoot}"], 12 | "options": { 13 | "project": "libs/ngx-jodit/ng-package.json", 14 | "tsConfig": "libs/ngx-jodit/tsconfig.lib.json" 15 | }, 16 | "configurations": { 17 | "production": { 18 | "tsConfig": "libs/ngx-jodit/tsconfig.lib.prod.json" 19 | }, 20 | "development": {} 21 | }, 22 | "defaultConfiguration": "production" 23 | }, 24 | "test": { 25 | "executor": "@nx/jest:jest", 26 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 27 | "options": { 28 | "jestConfig": "libs/ngx-jodit/jest.config.ts", 29 | "tsConfig": "libs/ngx-jodit/tsconfig.spec.json" 30 | } 31 | }, 32 | "lint": { 33 | "executor": "@nx/eslint:lint" 34 | }, 35 | "version": { 36 | "executor": "@jscutlery/semver:version", 37 | "options": { 38 | "preset": "angular", 39 | "postTargets": ["ngx-jodit:github"], 40 | "baseBranch": "main", 41 | "commitMessageFormat": "build({projectName}): release version ${version}" 42 | } 43 | }, 44 | "github": { 45 | "executor": "@jscutlery/semver:github", 46 | "options": { 47 | "tag": "${tag}", 48 | "notes": "${notes}" 49 | } 50 | }, 51 | "npm": { 52 | "executor": "ngx-deploy-npm:deploy", 53 | "options": { 54 | "access": "public", 55 | "distFolderPath": "dist/libs/ngx-jodit" 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /apps/demo/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import 'jodit/esm/plugins/add-new-line/add-new-line.js'; 2 | import 'jodit/esm/plugins/bold/bold.js'; 3 | import 'jodit/esm/plugins/fullsize/fullsize.js'; 4 | import 'jodit/esm/plugins/indent/indent.js'; 5 | import 'jodit/esm/plugins/source/source.js'; 6 | import 'jodit/esm/plugins/resizer/resizer.js'; 7 | 8 | import {Component, ViewChild} from '@angular/core'; 9 | import { FormBuilder, FormsModule, ReactiveFormsModule } from '@angular/forms'; 10 | import {Jodit} from 'jodit'; 11 | import de from 'jodit/esm/langs/de.js'; 12 | import {JoditConfig, NgxJoditComponent} from 'ngx-jodit'; 13 | 14 | Jodit.lang.de = de; 15 | 16 | interface FormWithJoditEditor { 17 | editor: string; 18 | } 19 | 20 | @Component({ 21 | selector: 'jodit-root', 22 | templateUrl: './app.component.html', 23 | styleUrls: ['./app.component.scss'], 24 | imports: [ 25 | NgxJoditComponent, 26 | FormsModule, 27 | ReactiveFormsModule 28 | ] 29 | }) 30 | export class AppComponent { 31 | value = 'Some text'; 32 | formGroup = this.formBuilder.group({ 33 | editor: 'Some text in a reactive form' 34 | }); 35 | _optionsStr = ''; 36 | 37 | @ViewChild('ngxJodit') ngxJodit?: NgxJoditComponent; 38 | 39 | get optionsStr(): string { 40 | return this._optionsStr; 41 | } 42 | 43 | set optionsStr(value: string) { 44 | this._optionsStr = value; 45 | try { 46 | const parsed = JSON.parse(value); 47 | this.options = { 48 | ...parsed, 49 | uploader: { 50 | insertImageAsBase64URI: true 51 | } as any 52 | } 53 | } catch (e) { 54 | // ignore 55 | } 56 | } 57 | 58 | options: JoditConfig = { 59 | uploader: { 60 | insertImageAsBase64URI: true 61 | } as any 62 | }; 63 | 64 | constructor(private formBuilder: FormBuilder) { 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ngx-jodit-pro", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "library", 5 | "sourceRoot": "libs/ngx-jodit-pro/src", 6 | "prefix": "ngx", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "@nx/angular:package", 11 | "outputs": ["{workspaceRoot}/dist/{projectRoot}"], 12 | "options": { 13 | "project": "libs/ngx-jodit-pro/ng-package.json", 14 | "tsConfig": "libs/ngx-jodit-pro/tsconfig.lib.json" 15 | }, 16 | "configurations": { 17 | "production": { 18 | "tsConfig": "libs/ngx-jodit-pro/tsconfig.lib.prod.json" 19 | }, 20 | "development": {} 21 | }, 22 | "defaultConfiguration": "production" 23 | }, 24 | "test": { 25 | "executor": "@nx/jest:jest", 26 | "outputs": ["{workspaceRoot}/coverage/{projectRoot}"], 27 | "options": { 28 | "jestConfig": "libs/ngx-jodit/jest.config.ts", 29 | "tsConfig": "libs/ngx-jodit-pro/tsconfig.spec.json" 30 | } 31 | }, 32 | "lint": { 33 | "executor": "@nx/eslint:lint" 34 | }, 35 | "version": { 36 | "executor": "@jscutlery/semver:version", 37 | "options": { 38 | "preset": "angular", 39 | "postTargets": ["ngx-jodit-pro:github"], 40 | "baseBranch": "main", 41 | "commitMessageFormat": "build({projectName}): release version ${version}" 42 | } 43 | }, 44 | "github": { 45 | "executor": "@jscutlery/semver:github", 46 | "options": { 47 | "tag": "${tag}", 48 | "notes": "${notes}" 49 | } 50 | }, 51 | "npm": { 52 | "executor": "ngx-deploy-npm:deploy", 53 | "options": { 54 | "access": "public", 55 | "distFolderPath": "dist/libs/ngx-jodit-pro" 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /apps/demo/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | /*************************************************************************************************** 51 | * APPLICATION IMPORTS 52 | */ 53 | -------------------------------------------------------------------------------- /apps/demo-pro/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including 12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * By default, zone.js will patch all possible macroTask and DomEvents 23 | * user can disable parts of macroTask/DomEvents patch by setting following flags 24 | * because those flags need to be set before `zone.js` being loaded, and webpack 25 | * will put import in the top of bundle, so user need to create a separate file 26 | * in this directory (for example: zone-flags.ts), and put the following flags 27 | * into that file, and then add the following code before importing zone.js. 28 | * import './zone-flags'; 29 | * 30 | * The flags allowed in zone-flags.ts are listed here. 31 | * 32 | * The following flags will work for all browsers. 33 | * 34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 37 | * 38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 40 | * 41 | * (window as any).__Zone_enable_cross_context_check = true; 42 | * 43 | */ 44 | 45 | /*************************************************************************************************** 46 | * Zone JS is required by default for Angular itself. 47 | */ 48 | import 'zone.js'; // Included with Angular CLI. 49 | 50 | /*************************************************************************************************** 51 | * APPLICATION IMPORTS 52 | */ 53 | -------------------------------------------------------------------------------- /apps/demo/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | ngx-jodit v3 5 | npm 6 | 7 | 8 | 9 | 18 |
19 | 20 |
21 |

22 | Angular wrapper for Jodit WYSIWYG 23 | editor. It supports Angular >= 16. Fore more information about installation, 24 | use, options and events see Github 25 | README. 26 |

27 | 28 |
29 |
30 |

Template driven form

31 | 32 |
33 |
34 |

Reactive form

35 |
36 | 37 |
38 |
39 |
40 | 41 |

Options

42 |

43 | All 44 | options 45 | from Jodit are supported. Plugins are not supported in this demo because you have to import it in your Typescript 46 | code (more 47 | information). 48 | The options are set via two-way data-binding. Insert 49 | your options as JSON to test it. 50 |

51 |

52 | For example you can insert {"disabled": true } 53 |

54 | 55 |
56 | -------------------------------------------------------------------------------- /decorate-angular-cli.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file decorates the Angular CLI with the Nx CLI to enable features such as computation caching 3 | * and faster execution of tasks. 4 | * 5 | * It does this by: 6 | * 7 | * - Patching the Angular CLI to warn you in case you accidentally use the undecorated ng command. 8 | * - Symlinking the ng to nx command, so all commands run through the Nx CLI 9 | * - Updating the package.json postinstall script to give you control over this script 10 | * 11 | * The Nx CLI decorates the Angular CLI, so the Nx CLI is fully compatible with it. 12 | * Every command you run should work the same when using the Nx CLI, except faster. 13 | * 14 | * Because of symlinking you can still type `ng build/test/lint` in the terminal. The ng command, in this case, 15 | * will point to nx, which will perform optimizations before invoking ng. So the Angular CLI is always invoked. 16 | * The Nx CLI simply does some optimizations before invoking the Angular CLI. 17 | * 18 | * To opt out of this patch: 19 | * - Replace occurrences of nx with ng in your package.json 20 | * - Remove the script from your postinstall script in your package.json 21 | * - Delete and reinstall your node_modules 22 | */ 23 | 24 | const fs = require('fs'); 25 | const os = require('os'); 26 | const cp = require('child_process'); 27 | const isWindows = os.platform() === 'win32'; 28 | let output; 29 | try { 30 | output = require('@nx/workspace').output; 31 | } catch (e) { 32 | console.warn( 33 | 'Angular CLI could not be decorated to enable computation caching. Please ensure @nx/workspace is installed.' 34 | ); 35 | process.exit(0); 36 | } 37 | 38 | /** 39 | * Symlink of ng to nx, so you can keep using `ng build/test/lint` and still 40 | * invoke the Nx CLI and get the benefits of computation caching. 41 | */ 42 | function symlinkNgCLItoNxCLI() { 43 | try { 44 | const ngPath = './node_modules/.bin/ng'; 45 | const nxPath = './node_modules/.bin/nx'; 46 | if (isWindows) { 47 | /** 48 | * This is the most reliable way to create symlink-like behavior on Windows. 49 | * Such that it works in all shells and works with npx. 50 | */ 51 | ['', '.cmd', '.ps1'].forEach((ext) => { 52 | if (fs.existsSync(nxPath + ext)) 53 | fs.writeFileSync(ngPath + ext, fs.readFileSync(nxPath + ext)); 54 | }); 55 | } else { 56 | // If unix-based, symlink 57 | cp.execSync(`ln -sf ./nx ${ngPath}`); 58 | } 59 | } catch (e) { 60 | output.error({ 61 | title: 62 | 'Unable to create a symlink from the Angular CLI to the Nx CLI:' + 63 | e.message, 64 | }); 65 | throw e; 66 | } 67 | } 68 | 69 | try { 70 | symlinkNgCLItoNxCLI(); 71 | require('nx/src/adapter/decorate-cli').decorateCli(); 72 | output.log({ 73 | title: 'Angular CLI has been decorated to enable computation caching.', 74 | }); 75 | } catch (e) { 76 | output.error({ 77 | title: 'Decoration of the Angular CLI did not complete successfully', 78 | }); 79 | } 80 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ngx-jodit-demo 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /apps/demo/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "sourceRoot": "apps/demo/src", 6 | "prefix": "jodit", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "@angular-devkit/build-angular:browser", 11 | "outputs": ["{options.outputPath}"], 12 | "options": { 13 | "outputPath": "dist/apps/demo", 14 | "index": "apps/demo/src/index.html", 15 | "main": "apps/demo/src/main.ts", 16 | "polyfills": "apps/demo/src/polyfills.ts", 17 | "tsConfig": "apps/demo/tsconfig.app.json", 18 | "inlineStyleLanguage": "scss", 19 | "assets": ["apps/demo/src/favicon.ico", "apps/demo/src/assets"], 20 | "styles": [ 21 | "node_modules/bootstrap-icons/font/bootstrap-icons.css", 22 | "node_modules/bootstrap/dist/css/bootstrap.min.css", 23 | "node_modules/jodit/es2021/jodit.min.css", 24 | "apps/demo/src/styles.scss" 25 | ], 26 | "scripts": [] 27 | }, 28 | "configurations": { 29 | "production": { 30 | "budgets": [ 31 | { 32 | "type": "initial", 33 | "maximumWarning": "500kb", 34 | "maximumError": "2mb" 35 | }, 36 | { 37 | "type": "anyComponentStyle", 38 | "maximumWarning": "2kb", 39 | "maximumError": "4kb" 40 | } 41 | ], 42 | "fileReplacements": [ 43 | { 44 | "replace": "apps/demo/src/environments/environment.ts", 45 | "with": "apps/demo/src/environments/environment.prod.ts" 46 | } 47 | ], 48 | "outputHashing": "all" 49 | }, 50 | "development": { 51 | "buildOptimizer": false, 52 | "optimization": false, 53 | "vendorChunk": true, 54 | "extractLicenses": false, 55 | "sourceMap": true, 56 | "namedChunks": true 57 | } 58 | }, 59 | "defaultConfiguration": "production" 60 | }, 61 | "serve": { 62 | "executor": "@angular-devkit/build-angular:dev-server", 63 | "configurations": { 64 | "production": { 65 | "buildTarget": "demo:build:production" 66 | }, 67 | "development": { 68 | "buildTarget": "demo:build:development" 69 | } 70 | }, 71 | "defaultConfiguration": "development", 72 | "continuous": true 73 | }, 74 | "extract-i18n": { 75 | "executor": "@angular-devkit/build-angular:extract-i18n", 76 | "options": { 77 | "buildTarget": "demo:build" 78 | } 79 | }, 80 | "lint": { 81 | "executor": "@nx/eslint:lint" 82 | }, 83 | "test": { 84 | "executor": "@nx/jest:jest", 85 | "outputs": ["{workspaceRoot}/coverage/apps/demo"], 86 | "options": { 87 | "jestConfig": "apps/demo/jest.config.ts", 88 | "tsConfig": "apps/demo/tsconfig.spec.json" 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /apps/demo-pro/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | ngx-jodit-pro v3 7 | 11 | npm 12 | 13 | 14 | 15 | 44 |
45 | 46 |
47 |

48 | Angular wrapper for 49 | Jodit Pro WYSIWYG editor. It 50 | supports Angular >= 16. Fore more information about installation, use, 51 | options and events see 52 | Github README. 56 |

57 | 58 |
59 |
60 |

Template driven form

61 | 66 |
67 |
68 |

Reactive form

69 |
70 | 74 |
75 |
76 |
77 | 78 |

Options

79 |

80 | All 81 | options 84 | from Jodit are supported. 85 | Plugins are not supported in this demo because you have to import it in 87 | your Typescript code (more information). 92 | The options are set via two-way data-binding. Insert your options as JSON to 93 | test it. 94 |

95 |

For example you can insert {{ '{' }} "disabled": true {{ '}' }}

96 | 97 |
98 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jodit", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "nx", 6 | "postinstall": "node ./decorate-angular-cli.js", 7 | "start": "nx serve demo", 8 | "start:pro": "nx serve demo-pro", 9 | "build": "nx build", 10 | "build:lib": "nx build ngx-jodit", 11 | "release:lib": "nx run ngx-jodit:version --releaseAs=patch --push", 12 | "publish:lib": "nx npm ngx-jodit", 13 | "build:lib:pro": "nx build ngx-jodit-pro", 14 | "release:lib:pro": "nx run ngx-jodit-pro:version --releaseAs=patch --push", 15 | "publish:lib:pro": "nx npm ngx-jodit-pro", 16 | "build:docs": "nx build demo && mv -f ./dist/apps/demo/* ./docs", 17 | "update": "nx migrate latest", 18 | "migrate": "npx nx migrate --run-migrations", 19 | "test": "nx test" 20 | }, 21 | "private": true, 22 | "dependencies": { 23 | "@angular/animations": "20.3.9", 24 | "@angular/common": "20.3.9", 25 | "@angular/compiler": "20.3.9", 26 | "@angular/core": "20.3.9", 27 | "@angular/forms": "20.3.9", 28 | "@angular/platform-browser": "20.3.9", 29 | "@angular/platform-browser-dynamic": "20.3.9", 30 | "@angular/router": "20.3.9", 31 | "@nx/angular": "22.1.3", 32 | "bootstrap": "^5.2.2", 33 | "bootstrap-icons": "^1.9.1", 34 | "jodit": "^4.7.9", 35 | "jodit-pro": "^4.7.6", 36 | "rxjs": "7.8.1", 37 | "tslib": "^2.3.0", 38 | "zone.js": "0.15.1" 39 | }, 40 | "devDependencies": { 41 | "@angular-devkit/build-angular": "20.3.9", 42 | "@angular-devkit/core": "20.3.9", 43 | "@angular-devkit/schematics": "20.3.9", 44 | "@angular-eslint/eslint-plugin": "20.7.0", 45 | "@angular-eslint/eslint-plugin-template": "20.7.0", 46 | "@angular-eslint/template-parser": "20.7.0", 47 | "@angular/cli": "~20.3.0", 48 | "@angular/compiler-cli": "20.3.9", 49 | "@angular/language-service": "20.3.9", 50 | "@commitlint/cli": "^17.0.0", 51 | "@commitlint/config-angular": "^17.0.0", 52 | "@jscutlery/semver": "^5.7.1", 53 | "@nx/cypress": "22.1.3", 54 | "@nx/eslint": "22.1.3", 55 | "@nx/eslint-plugin": "22.1.3", 56 | "@nx/jest": "22.1.3", 57 | "@nx/js": "22.1.3", 58 | "@nx/workspace": "22.1.3", 59 | "@schematics/angular": "20.3.9", 60 | "@types/jest": "29.5.14", 61 | "@types/node": "18.16.9", 62 | "@typescript-eslint/eslint-plugin": "7.18.0", 63 | "@typescript-eslint/parser": "7.18.0", 64 | "@typescript-eslint/utils": "^7.16.0", 65 | "ajv": "^8.12.0", 66 | "autoprefixer": "^10.4.0", 67 | "cypress": "^15.7.0", 68 | "cz-conventional-changelog": "^3.3.0", 69 | "eslint": "8.57.1", 70 | "eslint-config-prettier": "10.1.8", 71 | "eslint-plugin-cypress": "2.15.2", 72 | "husky": "^8.0.0", 73 | "jest": "29.7.0", 74 | "jest-environment-jsdom": "29.7.0", 75 | "jest-preset-angular": "14.6.2", 76 | "ng-packagr": "20.3.2", 77 | "ngx-deploy-npm": "^9.0.0", 78 | "nx": "22.1.3", 79 | "postcss": "^8.4.5", 80 | "postcss-import": "14.1.0", 81 | "postcss-preset-env": "7.5.0", 82 | "postcss-url": "10.1.3", 83 | "prettier": "^3.7.3", 84 | "ts-jest": "29.4.6", 85 | "ts-node": "10.9.1", 86 | "typescript": "5.9.3" 87 | }, 88 | "config": { 89 | "commitizen": { 90 | "path": "./node_modules/cz-conventional-changelog" 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /nx.json: -------------------------------------------------------------------------------- 1 | { 2 | "cli": { 3 | "packageManager": "npm" 4 | }, 5 | "generators": { 6 | "@nx/angular:application": { 7 | "style": "scss", 8 | "linter": "eslint", 9 | "unitTestRunner": "jest", 10 | "e2eTestRunner": "cypress" 11 | }, 12 | "@nx/angular:library": { 13 | "linter": "eslint", 14 | "unitTestRunner": "jest" 15 | }, 16 | "@nx/angular:component": { 17 | "style": "scss", 18 | "type": "component" 19 | }, 20 | "@schematics/angular:component": { 21 | "type": "component" 22 | }, 23 | "@nx/angular:directive": { 24 | "type": "directive" 25 | }, 26 | "@schematics/angular:directive": { 27 | "type": "directive" 28 | }, 29 | "@nx/angular:service": { 30 | "type": "service" 31 | }, 32 | "@schematics/angular:service": { 33 | "type": "service" 34 | }, 35 | "@nx/angular:scam": { 36 | "type": "component" 37 | }, 38 | "@nx/angular:scam-directive": { 39 | "type": "directive" 40 | }, 41 | "@nx/angular:guard": { 42 | "typeSeparator": "." 43 | }, 44 | "@schematics/angular:guard": { 45 | "typeSeparator": "." 46 | }, 47 | "@nx/angular:interceptor": { 48 | "typeSeparator": "." 49 | }, 50 | "@schematics/angular:interceptor": { 51 | "typeSeparator": "." 52 | }, 53 | "@nx/angular:module": { 54 | "typeSeparator": "." 55 | }, 56 | "@schematics/angular:module": { 57 | "typeSeparator": "." 58 | }, 59 | "@nx/angular:pipe": { 60 | "typeSeparator": "." 61 | }, 62 | "@schematics/angular:pipe": { 63 | "typeSeparator": "." 64 | }, 65 | "@nx/angular:resolver": { 66 | "typeSeparator": "." 67 | }, 68 | "@schematics/angular:resolver": { 69 | "typeSeparator": "." 70 | } 71 | }, 72 | "defaultProject": "demo", 73 | "$schema": "./node_modules/nx/schemas/nx-schema.json", 74 | "targetDefaults": { 75 | "build": { 76 | "dependsOn": ["^build"], 77 | "inputs": ["production", "^production"], 78 | "cache": true 79 | }, 80 | "e2e": { 81 | "inputs": ["default", "^production"], 82 | "cache": true 83 | }, 84 | "lint": { 85 | "inputs": ["default", "{workspaceRoot}/.eslintrc.json"], 86 | "cache": true 87 | }, 88 | "@nx/jest:jest": { 89 | "inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"], 90 | "cache": true, 91 | "options": { 92 | "passWithNoTests": true 93 | }, 94 | "configurations": { 95 | "ci": { 96 | "ci": true, 97 | "codeCoverage": true 98 | } 99 | } 100 | }, 101 | "@nx/eslint:lint": { 102 | "inputs": ["default", "{workspaceRoot}/.eslintrc.json"], 103 | "cache": true 104 | } 105 | }, 106 | "namedInputs": { 107 | "default": ["{projectRoot}/**/*", "sharedGlobals"], 108 | "sharedGlobals": [], 109 | "production": [ 110 | "default", 111 | "!{projectRoot}/.eslintrc.json", 112 | "!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)", 113 | "!{projectRoot}/tsconfig.spec.json", 114 | "!{projectRoot}/jest.config.[jt]s", 115 | "!{projectRoot}/src/test-setup.[jt]s" 116 | ] 117 | }, 118 | "useInferencePlugins": false, 119 | "defaultBase": "main" 120 | } 121 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). 4 | 5 | ## 3.0.1 (2024-11-20) 6 | 7 | * fix: await jodit ready ([3ff4376](https://github.com/julianpoemp/ngx-jodit/commit/3ff4376)) 8 | * fix: reactive form patch and inner value ([a550c98](https://github.com/julianpoemp/ngx-jodit/commit/a550c98)) 9 | 10 | 11 | 12 | ## 3.0.0 (2024-10-24) 13 | 14 | * chore(project): migrate ngx-deploy-npm to v8 ([9e4765f](https://github.com/julianpoemp/ngx-jodit/commit/9e4765f)) 15 | * chore(project): migrate to Nx 19 ([09c1caf](https://github.com/julianpoemp/ngx-jodit/commit/09c1caf)) 16 | * docs(project): update README.md ([3c98334](https://github.com/julianpoemp/ngx-jodit/commit/3c98334)) 17 | * feat(ngx-jodit-pro): support for jodit-pro v4 ([45cad3b](https://github.com/julianpoemp/ngx-jodit/commit/45cad3b)) 18 | * feat(ngx-jodit-pro): support for template-driven and reactive forms ([f363ff4](https://github.com/julianpoemp/ngx-jodit/commit/f363ff4)), closes [#35](https://github.com/julianpoemp/ngx-jodit/issues/35) 19 | * refactor(ngx-jodit): v3 branch is now main branch ([7610712](https://github.com/julianpoemp/ngx-jodit/commit/7610712)) 20 | 21 | 22 | 23 | # [3.0.0-beta.6](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-pro-3.0.0-beta.5...ngx-jodit-pro-3.0.0-beta.6) (2023-12-19) 24 | 25 | 26 | ### Features 27 | 28 | * **ngx-jodit-pro:** introducing ESM version of jodit-pro package ([7c0c91a](https://github.com/julianpoemp/ngx-jodit/commit/7c0c91a8374b0035d9dd8a0fb079530aec71eab1)) 29 | 30 | 31 | ### BREAKING CHANGES 32 | 33 | * **ngx-jodit-pro:** Du introducing ESM version of jodit package the way of importing jodit-pro changed. See new installation instructions. 34 | 35 | 36 | 37 | # [3.0.0-beta.5](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-pro-3.0.0-beta.4...ngx-jodit-pro-3.0.0-beta.5) (2023-09-26) 38 | 39 | 40 | ### Bug Fixes 41 | 42 | * **ngx-jodit-pro:** [(value)] still resets caret position ([9837b91](https://github.com/julianpoemp/ngx-jodit/commit/9837b91c09cb6388070c9491a42d2e430c2434a8)) 43 | 44 | 45 | 46 | # [3.0.0-beta.4](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-pro-3.0.0-beta.3...ngx-jodit-pro-3.0.0-beta.4) (2023-09-22) 47 | 48 | 49 | ### Bug Fixes 50 | 51 | * **ngx-jodit-pro:** [(value)] not working correctly, e.g. resets cursor ([143e238](https://github.com/julianpoemp/ngx-jodit/commit/143e2381520de9eb7b10d345a554c90c4df67e19)) 52 | 53 | 54 | 55 | # [3.0.0-beta.3](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-pro-3.0.0-beta.2...ngx-jodit-pro-3.0.0-beta.3) (2023-09-18) 56 | 57 | 58 | ### Bug Fixes 59 | 60 | * **ngx-jodit-pro:** ngModel [(value)] not working with outside changes ([3b6daf8](https://github.com/julianpoemp/ngx-jodit/commit/3b6daf88680ddddfe2637258aba425e980eaee24)) 61 | 62 | 63 | 64 | # [3.0.0-beta.2](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-pro-3.0.0-beta.1...ngx-jodit-pro-3.0.0-beta.2) (2023-07-19) 65 | 66 | 67 | ### Bug Fixes 68 | 69 | * **ngx-jodit-pro:** no icons for toolbar buttons visible ([f606990](https://github.com/julianpoemp/ngx-jodit/commit/f60699037ab2b8892e6fb0963bdbd8444f0f14c6)) 70 | 71 | 72 | 73 | # [3.0.0-beta.1](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-pro-3.0.0-beta.0...ngx-jodit-pro-3.0.0-beta.1) (2023-06-30) 74 | 75 | 76 | ### Features 77 | 78 | * **ngx-jodit-pro:** add events joditKeyUp and joditMouseup ([ae748c8](https://github.com/julianpoemp/ngx-jodit/commit/ae748c8e18e6e2502b665a17f611e1b69c938505)) 79 | * **ngx-jodit-pro:** add type for options ([caaca42](https://github.com/julianpoemp/ngx-jodit/commit/caaca4202fe29fb35815ec332cb5ccb721059b4c)) 80 | -------------------------------------------------------------------------------- /apps/demo-pro/project.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "demo-pro", 3 | "$schema": "../../node_modules/nx/schemas/project-schema.json", 4 | "projectType": "application", 5 | "sourceRoot": "apps/demo-pro/src", 6 | "prefix": "jodit", 7 | "tags": [], 8 | "targets": { 9 | "build": { 10 | "executor": "@angular-devkit/build-angular:browser", 11 | "outputs": ["{options.outputPath}"], 12 | "options": { 13 | "outputPath": "dist/apps/demo-pro", 14 | "index": "apps/demo-pro/src/index.html", 15 | "main": "apps/demo-pro/src/main.ts", 16 | "polyfills": "apps/demo-pro/src/polyfills.ts", 17 | "tsConfig": "apps/demo-pro/tsconfig.app.json", 18 | "inlineStyleLanguage": "scss", 19 | "assets": [ 20 | "apps/demo-pro/src/favicon.ico", 21 | "apps/demo-pro/src/assets", 22 | "apps/demo-pro/src/config.js" 23 | ], 24 | "styles": [ 25 | "node_modules/bootstrap-icons/font/bootstrap-icons.css", 26 | "node_modules/bootstrap/dist/css/bootstrap.min.css", 27 | "node_modules/jodit-pro/es2021/jodit.fat.min.css", 28 | "node_modules/jodit-pro/es2021/plugins/tune-block/tune-block.min.css", 29 | "apps/demo-pro/src/styles.scss" 30 | ], 31 | "scripts": [ 32 | "node_modules/jodit-pro/es2021/jodit.min.js", 33 | "node_modules/jodit-pro/es2021/plugins/tune-block/tune-block.min.js", 34 | "node_modules/jodit-pro/es2021/plugins/page-break/page-break.min.js" 35 | ] 36 | }, 37 | "configurations": { 38 | "production": { 39 | "budgets": [ 40 | { 41 | "type": "initial", 42 | "maximumWarning": "500kb", 43 | "maximumError": "2mb" 44 | }, 45 | { 46 | "type": "anyComponentStyle", 47 | "maximumWarning": "2kb", 48 | "maximumError": "4kb" 49 | } 50 | ], 51 | "fileReplacements": [ 52 | { 53 | "replace": "apps/demo-pro/src/environments/environment.ts", 54 | "with": "apps/demo-pro/src/environments/environment.prod.ts" 55 | } 56 | ], 57 | "outputHashing": "all" 58 | }, 59 | "development": { 60 | "buildOptimizer": false, 61 | "optimization": false, 62 | "vendorChunk": true, 63 | "extractLicenses": false, 64 | "sourceMap": true, 65 | "namedChunks": true 66 | } 67 | }, 68 | "defaultConfiguration": "production" 69 | }, 70 | "serve": { 71 | "executor": "@angular-devkit/build-angular:dev-server", 72 | "configurations": { 73 | "production": { 74 | "buildTarget": "demo-pro:build:production" 75 | }, 76 | "development": { 77 | "buildTarget": "demo-pro:build:development" 78 | } 79 | }, 80 | "defaultConfiguration": "development", 81 | "options": { 82 | "port": 4201 83 | }, 84 | "continuous": true 85 | }, 86 | "extract-i18n": { 87 | "executor": "@angular-devkit/build-angular:extract-i18n", 88 | "options": { 89 | "buildTarget": "demo-pro:build" 90 | } 91 | }, 92 | "lint": { 93 | "executor": "@nx/eslint:lint" 94 | }, 95 | "test": { 96 | "executor": "@nx/jest:jest", 97 | "outputs": ["{workspaceRoot}/coverage/apps/demo"], 98 | "options": { 99 | "jestConfig": "apps/demo-pro/jest.config.ts", 100 | "tsConfig": "apps/demo-pro/tsconfig.spec.json" 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ngx-jodit & ngx-jodit-pro 2 | 3 | Angular wrapper for jodit and jodit-pro WYSIWYG editor supporting Angular >=12 and ESM. 4 | 5 | ## About this repository 6 | 7 | There is no affiliation with Jodit. ngx-jodit and ngx-jodit-pro are under MIT-License. Jodit and Jodit-Pro can be under another license. For more information about licenses click on "more Information" next to a version of your choice. and scroll down to "License". 8 | 9 | ## ngx-jodit 10 | 11 | Angular wrapper for Jodit WYSIWYG editor (free). If you want to use Jodit Pro/Multi/OEM see ngx-jodit-pro below. 12 | 13 | ### Compatibility 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
Ngx-joditJoditAngularTypeDemoReadme
npmv4>= v16StandaloneDemoReadme
npmv4v12 - v15ModuleDemoReadme
npmv3v12 - v15ModuleDemoReadme
29 | 30 | ## ngx-jodit-pro 31 | 32 | Angular wrapper for Jodit PRO WYSIWYG editor. You need a license key in order to use this wrapper. 33 | Buy here. 34 | 35 | ### Compatibility 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 |
Ngx-jodit-proJodit ProAngularTypeDemoReadme
npmv4.x>= v16StandaloneDemoReadme
npmv4.xv12 - v15ModuleDemoReadme
v1.x (deprecated)v1.xv12 - v15ModuleDemoReadme
51 | 52 | ## Creating issues 53 | 54 | Please create new issues here only if it's related directly to ngx-jodit or ngx-jodit-pro. Issues related to Jodit itself should be posted [here](https://github.com/xdan/jodit/issues). 55 | 56 | ## Contribution 57 | 58 | This project uses [@jscutlery/semver](https://github.com/jscutlery/semver) with Angular preset. All commit must meet the Angular [commit message schema](https://gist.github.com/brianclements/841ea7bffdb01346392c) requirements. There are only three permitted scopes: "ngx-jodit", "ngx-jodit-pro" and "general" (for changes outside of libraries). 59 | -------------------------------------------------------------------------------- /libs/ngx-jodit/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | This file was generated using [@jscutlery/semver](https://github.com/jscutlery/semver). 4 | 5 | ## 3.2.2 (2025-03-18) 6 | 7 | * fix(ngx-jodit): try to fox IViewOptions issue ref #37 ([bbb08b1](https://github.com/julianpoemp/ngx-jodit/commit/bbb08b1)), closes [#37](https://github.com/julianpoemp/ngx-jodit/issues/37) 8 | 9 | 10 | 11 | ## 3.2.0 (2025-02-13) 12 | 13 | * build(ngx-jodit): change peer dependency to Jodit ^4.5.0 ([08a8423](https://github.com/julianpoemp/ngx-jodit/commit/08a8423)) 14 | * feat(ngx-jodit): include IViewOptions in JoditConfig ([6216069](https://github.com/julianpoemp/ngx-jodit/commit/6216069)), closes [#32](https://github.com/julianpoemp/ngx-jodit/issues/32) 15 | * docs(ngx-jodit): change README.md ([91e4a05](https://github.com/julianpoemp/ngx-jodit/commit/91e4a05)) 16 | 17 | 18 | 19 | ## [3.1.3](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.1.2...ngx-jodit-3.1.3) (2024-08-13) 20 | 21 | 22 | ### Bug Fixes 23 | 24 | * **ngx-jodit:** databinding using [(value)] resets cursor on change ([021a34f](https://github.com/julianpoemp/ngx-jodit/commit/021a34f5494a0fc71ad27e46f2de812cc537fbb6)) 25 | 26 | 27 | 28 | ## [3.1.2](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.1.1...ngx-jodit-3.1.2) (2024-01-25) 29 | 30 | 31 | ### Bug Fixes 32 | 33 | * reactive form gets dirty after (value) initialization ([0761464](https://github.com/julianpoemp/ngx-jodit/commit/07614646f931448c437c10dc9cb7ca9d619e0af4)) 34 | 35 | 36 | 37 | ## [3.1.1](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.1.0...ngx-jodit-3.1.1) (2024-01-24) 38 | 39 | 40 | ### Bug Fixes 41 | 42 | * **ngx-jodit:** Fixed value handling for reactive forms ([5c6aa57](https://github.com/julianpoemp/ngx-jodit/commit/5c6aa574a443bb8eff2faf85072504020fce1fb3)) 43 | 44 | 45 | 46 | # [3.1.0](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.2...ngx-jodit-3.1.0) (2024-01-16) 47 | 48 | 49 | ### Features 50 | 51 | * **ngx-jodit:** ngx-jodit can be used like a Forms component [(ngModel)] support ([a1e3fa1](https://github.com/julianpoemp/ngx-jodit/commit/a1e3fa104c2624c2f8da02be4d9d56b56c0c7af5)) 52 | 53 | 54 | 55 | ## [3.0.2](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.1...ngx-jodit-3.0.2) (2024-01-10) 56 | 57 | 58 | ### Features 59 | 60 | * **ngx-jodit:** new type for Jodit options: JoditConfig ([5949571](https://github.com/julianpoemp/ngx-jodit/commit/5949571ca3ab29de885292e0cbf948a6fd5a658c)) 61 | 62 | 63 | 64 | ## [3.0.1](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.10...ngx-jodit-3.0.1) (2024-01-08) 65 | 66 | 67 | ### Features 68 | 69 | * **ngx-jodit:** Jodit v4 was released as stable version. ngx-jodit v3 now stable. ([503db2a](https://github.com/julianpoemp/ngx-jodit/commit/503db2adea178177551160863715b4baa2f28c9c)) 70 | 71 | 72 | ### BREAKING CHANGES 73 | 74 | * **ngx-jodit:** If you update from the latest beta version to the 75 | stable version you don't have to do anything. If you update from 76 | ngx-jodit v1 you should read the installation instructions of ngx-jodit 77 | v2 AND the breaking changes of Jodit v4: 78 | https://github.com/xdan/jodit/releases/tag/4.0.1 79 | 80 | 81 | 82 | ## [1.0.8](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.7...ngx-jodit-1.0.8) (2023-09-26) 83 | 84 | 85 | ### Bug Fixes 86 | 87 | * **ngx-jodit:** [(value)] still resets caret position ([1b3a7a0](https://github.com/julianpoemp/ngx-jodit/commit/1b3a7a0a4e47faa491c3fe4c2f98d7abb8c7fa44)) 88 | 89 | 90 | 91 | ## [1.0.7](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.6...ngx-jodit-1.0.7) (2023-09-22) 92 | 93 | 94 | ### Bug Fixes 95 | 96 | * **ngx-jodit-pro:** [(value)] not working correctly, e.g. resets cursor ([bf4a223](https://github.com/julianpoemp/ngx-jodit/commit/bf4a223dabeda5dc91cb1b1456804296da9aeefa)) 97 | * **ngx-jodit:** [(value)] not working correctly, e.g. resets cursor ([1821283](https://github.com/julianpoemp/ngx-jodit/commit/182128372ffb21b4be5b7b6907b063800e71a9ce)) 98 | 99 | 100 | 101 | ## [1.0.6](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-1.0.5...ngx-jodit-1.0.6) (2023-09-18) 102 | 103 | 104 | 105 | ## [1.0.5](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.5...ngx-jodit-1.0.5) (2023-09-18) 106 | 107 | 108 | ### Bug Fixes 109 | 110 | * **ngx-jodit:** add missing joditKeyUp event ([32cf560](https://github.com/julianpoemp/ngx-jodit/commit/32cf560452a623543ad178bc1f2dd93357ecd9ca)) 111 | * **ngx-jodit:** ngModel [(value)] not working for outside changes ([35f0e59](https://github.com/julianpoemp/ngx-jodit/commit/35f0e5906781fd9b1665d875485a1e9c6811ab47)) 112 | 113 | 114 | 115 | ## 1.0.4 (2023-06-17) 116 | 117 | 118 | 119 | # [3.0.0-beta.10](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.9...ngx-jodit-3.0.0-beta.10) (2023-11-15) 120 | 121 | 122 | ### Features 123 | 124 | * **ngx-jodit:** ngx-jodit uses the ESM version of Jodit ([d8b06d7](https://github.com/julianpoemp/ngx-jodit/commit/d8b06d7fdb34320bda58b9b95bcd3ee24d4aa8c5)), closes [#18](https://github.com/julianpoemp/ngx-jodit/issues/18) 125 | 126 | 127 | ### BREAKING CHANGES 128 | 129 | * **ngx-jodit:** ngx-jodit v3 now uses the ESM version of jodit. That's 130 | why there are some breaking changes because the way to import the module 131 | and jodit plugins changed. Please have a look on the new installation 132 | instructions. 133 | 134 | 135 | 136 | # [3.0.0-beta.9](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.8...ngx-jodit-3.0.0-beta.9) (2023-10-13) 137 | 138 | 139 | ### Bug Fixes 140 | 141 | * **ngx-jodit:** missing icons for toolbar buttons ([c265329](https://github.com/julianpoemp/ngx-jodit/commit/c26532988d92b3ad402d62327452d779c5ccfc81)) 142 | 143 | 144 | ### BREAKING CHANGES 145 | 146 | * **ngx-jodit:** You have to add the Jodit JS file to the list of your 147 | app's scripts attribute. See installation instructions for more 148 | information 149 | 150 | 151 | 152 | # [3.0.0-beta.8](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.7...ngx-jodit-3.0.0-beta.8) (2023-09-26) 153 | 154 | 155 | ### Bug Fixes 156 | 157 | * **ngx-jodit:** [(value)] still resets caret position ([63b3942](https://github.com/julianpoemp/ngx-jodit/commit/63b39423148a157cbbc6e82ad537668edeb288b3)) 158 | 159 | 160 | 161 | # [3.0.0-beta.7](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.6...ngx-jodit-3.0.0-beta.7) (2023-09-22) 162 | 163 | 164 | ### Bug Fixes 165 | 166 | * **ngx-jodit:** [(value)] not working correctly, e.g. resets cursor ([7ef29e8](https://github.com/julianpoemp/ngx-jodit/commit/7ef29e81cf6656128326fee1354d67cf03be1d69)) 167 | 168 | 169 | 170 | # [3.0.0-beta.6](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.5...ngx-jodit-3.0.0-beta.6) (2023-09-18) 171 | 172 | 173 | ### Bug Fixes 174 | 175 | * **ngx-jodit:** fix ngModel [(value)] not working with outside changes ([36380cb](https://github.com/julianpoemp/ngx-jodit/commit/36380cbce5c8a58fdb1032e4c0934172a174cd10)) 176 | 177 | 178 | 179 | # [3.0.0-beta.5](https://github.com/julianpoemp/ngx-jodit/compare/ngx-jodit-3.0.0-beta.4...ngx-jodit-3.0.0-beta.5) (2023-06-30) 180 | 181 | 182 | ### Features 183 | 184 | * **ngx-jodit:** add events joditKeyUp and joditMouseup ([81a08c6](https://github.com/julianpoemp/ngx-jodit/commit/81a08c66dc2eb9b79e047c2608294fa0f8e25e43)) 185 | * **ngx-jodit:** add type for options ([47660de](https://github.com/julianpoemp/ngx-jodit/commit/47660de12399e4510502f996cd7779c38bfa6660)) 186 | -------------------------------------------------------------------------------- /libs/ngx-jodit/src/lib/ngx-jodit.component.ts: -------------------------------------------------------------------------------- 1 | 2 | import { 3 | AfterViewInit, 4 | ChangeDetectionStrategy, 5 | ChangeDetectorRef, 6 | Component, 7 | ElementRef, 8 | EventEmitter, 9 | forwardRef, 10 | Input, 11 | OnDestroy, 12 | Output, 13 | ViewChild, 14 | } from '@angular/core'; 15 | import {ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR,} from '@angular/forms'; 16 | import {Jodit} from 'jodit'; 17 | import {BehaviorSubject, combineLatest, delay, distinctUntilChanged, filter, Subscription, withLatestFrom,} from 'rxjs'; 18 | 19 | import {JoditConfig} from './types'; 20 | 21 | @Component({ 22 | selector: 'ngx-jodit', 23 | standalone: true, 24 | imports: [FormsModule], 25 | templateUrl: './ngx-jodit.component.html', 26 | providers: [ 27 | { 28 | provide: NG_VALUE_ACCESSOR, 29 | useExisting: forwardRef(() => NgxJoditComponent), 30 | multi: true, 31 | }, 32 | ], 33 | styleUrls: ['./ngx-jodit.component.scss'], 34 | changeDetection: ChangeDetectionStrategy.OnPush, 35 | }) 36 | export class NgxJoditComponent 37 | implements ControlValueAccessor, AfterViewInit, OnDestroy { 38 | @ViewChild('joditContainer') joditContainer!: ElementRef; 39 | jodit?: Jodit; 40 | 41 | /** 42 | * options for jodit. 43 | * You can add more supported options even Typescript doesn't suggest the options. 44 | */ 45 | private _options?: JoditConfig; 46 | 47 | @Input() set options(value: JoditConfig) { 48 | this._options = value; 49 | 50 | if (value) { 51 | this.initJoditContainer(); 52 | } 53 | } 54 | 55 | // value property (subject) 56 | private valueSubject: BehaviorSubject = new BehaviorSubject( 57 | '' 58 | ); 59 | 60 | @Input() set value(value: string) { 61 | const sanitizedText = this.prepareText(value); 62 | if (!this.internValueChange) { 63 | this.valueSubject.next(sanitizedText); 64 | } else { 65 | this.internValueChange = false; 66 | } 67 | this.onChange(sanitizedText); 68 | } 69 | 70 | get value(): string { 71 | return this.valueSubject.getValue(); 72 | } 73 | 74 | @Output() valueChange = new EventEmitter(); 75 | 76 | //events 77 | @Output() joditChange = new EventEmitter(); 78 | @Output() joditKeyDown = new EventEmitter(); 79 | @Output() joditKeyUp = new EventEmitter(); 80 | @Output() joditMousedown = new EventEmitter(); 81 | @Output() joditMouseup = new EventEmitter(); 82 | @Output() joditClick = new EventEmitter(); 83 | @Output() joditFocus = new EventEmitter(); 84 | @Output() joditPaste = new EventEmitter(); 85 | @Output() joditResize = new EventEmitter(); 86 | @Output() joditBeforeEnter = new EventEmitter(); 87 | @Output() joditBeforeCommand = new EventEmitter(); 88 | @Output() joditAfterExec = new EventEmitter(); 89 | @Output() joditAfterPaste = new EventEmitter(); 90 | @Output() joditChangeSelection = new EventEmitter(); 91 | 92 | // Used for delay value assignment to wait for jodit to be initialized 93 | private joditInitializedSubject: BehaviorSubject = 94 | new BehaviorSubject(false); 95 | private valueSubscription?: Subscription; 96 | private internValueChange = false; 97 | 98 | constructor(private readonly cdr: ChangeDetectorRef) { 99 | this.valueSubscription = combineLatest([ 100 | // Handle value changes ... 101 | this.valueSubject.asObservable().pipe(distinctUntilChanged()), 102 | // ...additionally ensuring that the value is reapplied if the editor was not initialized when value was set 103 | this.joditInitializedSubject.pipe( 104 | distinctUntilChanged(), 105 | filter((initialized) => initialized) 106 | ), 107 | ]) 108 | .pipe( 109 | // Pass through the latest value in case of editor initialization 110 | withLatestFrom(this.valueSubject), 111 | // Prevent ExpressionChangedAfterItHasBeenCheckedError 112 | delay(0) 113 | ) 114 | .subscribe(([[_, initialized], text]) => { 115 | if (this.jodit && initialized) { 116 | this.jodit.value = text; 117 | } 118 | }); 119 | } 120 | 121 | isHTML(text: string) { 122 | const elem = document.createElement('div'); 123 | elem.innerHTML = text; 124 | 125 | return ( 126 | text && 127 | elem.childNodes.length > 0 && 128 | elem.childNodes.item(0).nodeType !== 3 129 | ); 130 | } 131 | 132 | ngAfterViewInit() { 133 | this.initJoditContainer(); 134 | } 135 | 136 | ngOnDestroy() { 137 | this.valueSubscription?.unsubscribe(); 138 | this.jodit?.destruct(); 139 | } 140 | 141 | initJoditContainer() { 142 | if (this.joditContainer) { 143 | if (this.jodit) { 144 | this.jodit.destruct(); 145 | this.joditInitializedSubject.next(false); 146 | } 147 | this.jodit = Jodit.make( 148 | this.joditContainer.nativeElement, 149 | this._options as any 150 | ); 151 | this.jodit.value = this.valueSubject.getValue(); 152 | this.jodit.events.on('change', (text: string) => { 153 | this.internValueChange = true; 154 | this.changeValue(text); 155 | this.joditChange.emit(text); 156 | this.onChange(text); 157 | }); 158 | this.jodit.events.on('keydown', (a: KeyboardEvent) => { 159 | this.joditKeyDown.emit(a); 160 | }); 161 | this.jodit.events.on('keyup', (a: KeyboardEvent) => { 162 | this.joditKeyUp.emit(a); 163 | }); 164 | this.jodit.events.on('mousedown', (a: MouseEvent) => { 165 | this.joditMousedown.emit(a); 166 | }); 167 | this.jodit.events.on('mouseup', (a: MouseEvent) => { 168 | this.joditMouseup.emit(a); 169 | }); 170 | this.jodit.events.on('click', (a: PointerEvent) => { 171 | this.joditClick.emit(a); 172 | this.onTouched(); 173 | }); 174 | this.jodit.events.on('focus', (a: FocusEvent) => { 175 | this.joditFocus.emit(a); 176 | }); 177 | this.jodit.events.on('paste', (a: ClipboardEvent) => { 178 | this.joditPaste.emit(a); 179 | }); 180 | this.jodit.events.on('resize', () => { 181 | this.joditResize.emit(); 182 | }); 183 | this.jodit.events.on('beforeEnter', (a: KeyboardEvent) => { 184 | this.joditBeforeEnter.emit(a); 185 | }); 186 | this.jodit.events.on('beforeCommand', (a: string) => { 187 | this.joditBeforeCommand.emit(a); 188 | }); 189 | this.jodit.events.on('afterExec', () => { 190 | this.joditAfterExec.emit(); 191 | }); 192 | this.jodit.events.on('afterPaste', (a: ClipboardEvent) => { 193 | this.joditAfterPaste.emit(a); 194 | }); 195 | this.jodit.events.on('changeSelection', () => { 196 | this.joditChangeSelection.emit(); 197 | }); 198 | 199 | this.joditInitializedSubject.next(true); 200 | } 201 | } 202 | 203 | changeValue(value: string) { 204 | this.valueChange.emit(value); 205 | } 206 | 207 | /* 208 | FUNCTIONS RELEVANT FOR ANGULAR FORMS 209 | */ 210 | 211 | onChange = (text: string) => { 212 | // implemented by user 213 | }; 214 | 215 | onTouched = () => { 216 | // implemented by user 217 | }; 218 | 219 | writeValue(text: string): void { 220 | this.valueSubject.next(this.prepareText(text)); 221 | } 222 | 223 | registerOnChange(fn: (text: string) => void): void { 224 | this.onChange = fn; 225 | } 226 | 227 | registerOnTouched(fn: () => void): void { 228 | this.onTouched = fn; 229 | } 230 | 231 | setDisabledState?(isDisabled: boolean): void { 232 | this.options = { 233 | ...this._options, 234 | disabled: isDisabled, 235 | }; 236 | } 237 | 238 | private prepareText(text: string) { 239 | return this.isHTML(text) ? text : `

${text}

`; 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /libs/ngx-jodit/README.md: -------------------------------------------------------------------------------- 1 | # ngx-jodit v3.x 2 | 3 | Angular wrapper for Jodit WYSIWYG editor. It supports Angular >= 16 and jodit v4. 4 | 5 | ## Compatibility 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
Ngx-joditJoditAngularTypeDemoReadme
npmv4>= v16StandaloneDemoReadme
npmv4v12 - v15ModuleDemoReadme
npmv3v12 - v15ModuleDemoReadme
21 | 22 | ## Jodit Pro, Multi & OEM 23 | 24 | For Jodit Pro, Multi and OEM you have to install the jodit-pro package and another Angular library: [ngx-jodit-pro](https://github.com/julianpoemp/ngx-jodit/blob/main/libs/ngx-jodit-pro/README.md). For more information click [here](https://github.com/julianpoemp/ngx-jodit/tree/v3.x/libs/ngx-jodit-pro). 25 | 26 | ## Demo 27 | 28 | You can find a demo for ngx-jodit 3.x [here](https://github.julianpoemp.com/ngx-jodit/3.x/). 29 | 30 | ## Options 31 | 32 | All [options](https://xdsoft.net/jodit/docs/classes/config.Config.html) from Jodit are supported. 33 | 34 | ## Installation 35 | 36 | 1. Make sure that the latest jodit v4 and ngx-jodit v3 is installed: 37 | ``` 38 | npm install jodit@4 --save 39 | ``` 40 | 2. ``` 41 | npm install ngx-jodit@3 --save 42 | ``` 43 | 3. Add jodit stylesheet to your app's styles in angular.json (or project.json for 44 | Nx). 45 | ``` 46 | ... 47 | , 48 | "styles": [ 49 | ... 50 | "node_modules/jodit/es2021/jodit.min.css", 51 | ... 52 | ], 53 | ... 54 | ``` 55 | 4. Add `NgxJoditComponent` to the `imports` array in your app.module.ts (it's standalone): 56 | ``` 57 | @NgModule({ 58 | ... 59 | imports: [ 60 | ..., 61 | NgxJoditComponent 62 | ], 63 | ... 64 | }) 65 | ``` 66 | 5. Add `"skipLibCheck": true` to compilerOptions in your `tsconfig.app.json`. This is needed because the 67 | check fails to typing errors of the jodit package. **This is still the issue in v4**. If you know any other solution, let me know :): 68 | ``` 69 | ... 70 | "compilerOptions": { 71 | ..., 72 | "skipLibCheck": true 73 | } 74 | ... 75 | ``` 76 | 77 | 6. Each toolbar element by Jodit v4 ESM version is considered as plugin. While basic plugins are imported automatically, you have to import other plugins manually. See section "How to import plugins". 78 | 79 | 7. Now you can use the component. See [example here](https://github.com/julianpoemp/ngx-jodit/blob/v3.x/apps/demo/src/app/app.component.ts). 80 | 81 | - Without AngularForms: 82 | 83 | ```angular2html 84 | 85 | ``` 86 | 87 | - With AngularForms (make sure to import AngularForms): 88 | - Template driven 89 | 90 | ```angular2html 91 | 92 | ``` 93 | - Reactive 94 | ```angular2html 95 |
96 | 97 |
98 | ``` 99 | 100 | If you are facing any issues have a look on [Troubleshooting](https://github.com/julianpoemp/ngx-jodit/blob/main/libs/ngx-jodit/README.md#troubleshooting) first. Create an issue if it's not solved. 101 | 102 | ## How to import plugins 103 | 104 | Jodit v4 automatically imports a [basic set of plugins](https://github.com/xdan/jodit/blob/main/tools/utils/resolve-alias-imports.ts#L59) and the English language. If you want to use more you have to import it separately. For example: 105 | 106 | ```typescript 107 | import {Jodit} from "jodit"; 108 | import 'jodit/esm/plugins/add-new-line/add-new-line.js'; 109 | import 'jodit/esm/plugins/fullsize/fullsize.js'; 110 | import de from 'jodit/esm/langs/de.js'; // <-- make sure "compilerOptions.allowSyntheticDefaultImports" is set to "true" in tsconfig.json 111 | 112 | Jodit.lang.de = de; 113 | 114 | //.. 115 | ``` 116 | 117 | You can import your plugins wherever you want, e.g. in a global ts file that's imported anyway like index.ts or main.ts files. 118 | 119 | ## Options for ngx-jodit 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 |
NameTypeDescription
valuetwo-way data-bindingUpdates as soon as HTML value of the editor changed. You can set your value, too.
optionsone-way data-bindingSets options for Jodit on the fly.
142 | 143 | ## Events for ngx-jodit 144 | 145 | You can bind events using the Angular way, e.g.: 146 | 147 | ```angular2html 148 | 149 | 150 | ``` 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 |
NameDescription
joditChangeTriggers as soon as something of the HTML value changes.
joditKeyDownTriggers as soon as a key is pressed down.
joditMousedownTriggers as soon as the left mouse button is pressed.
joditClickTriggers as soon as the user clicks on the editor.
joditFocusTriggers as soon as Jodit gets focus.
joditPasteTriggers as soon as something is pasted.
joditResizeTriggers as soon as the editor resizes.
joditBeforeEnterTriggers as soon as enter key is pressed.
joditBeforeCommandTriggers before a command is executed.
joditAfterExecTriggers after a command is executed.
joditAfterPasteTriggers after something pasted.
joditChangeSelectionTriggers as soon as selection is changed.
210 | 211 | ## Troubleshooting 212 | 213 | - **Some of the buttons don't show any icon**
Check your options if you used the correct button names. If yes, check the folder `node_modules/jodit/esm/plugins/` for a folder named like the button you want to use. Then import the found plugin to your app as described [here](https://github.com/julianpoemp/ngx-jodit/blob/main/libs/ngx-jodit/README.md#how-to-import-plugins). If that doesn't helpt look in the web console for an error message that indicates a missing plugin. 214 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/src/lib/ngx-jodit-pro.component.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AfterViewInit, 3 | ChangeDetectionStrategy, 4 | ChangeDetectorRef, 5 | Component, 6 | ElementRef, 7 | EventEmitter, 8 | forwardRef, 9 | Input, 10 | OnDestroy, 11 | Output, 12 | ViewChild, 13 | } from '@angular/core'; 14 | 15 | import {IViewOptionsPro} from 'jodit-pro/types/types/view'; 16 | import {IViewOptions} from 'jodit/types/types'; 17 | import {IJodit} from 'jodit/types/types/jodit'; 18 | import {ControlValueAccessor, FormsModule, NG_VALUE_ACCESSOR} from '@angular/forms'; 19 | import {BehaviorSubject, combineLatest, delay, distinctUntilChanged, filter, Subscription, withLatestFrom} from 'rxjs'; 20 | 21 | declare const Jodit: any; 22 | export type JoditProConfig = Partial>; 23 | 24 | @Component({ 25 | selector: 'ngx-jodit-pro', 26 | standalone: true, 27 | imports: [FormsModule], 28 | templateUrl: './ngx-jodit-pro.component.html', 29 | providers: [{ 30 | provide: NG_VALUE_ACCESSOR, 31 | useExisting: forwardRef(() => NgxJoditProComponent), 32 | multi: true 33 | }], 34 | styleUrls: ['./ngx-jodit-pro.component.scss'], 35 | changeDetection: ChangeDetectionStrategy.OnPush 36 | }) 37 | export class NgxJoditProComponent implements ControlValueAccessor, AfterViewInit, OnDestroy { 38 | @ViewChild('joditContainer', {static: false}) joditContainer!: ElementRef; 39 | jodit?: IJodit; 40 | 41 | /** 42 | * options for jodit pro. It's of type partial because Config is imported from jodit packge and doesn't contain jodit-pro options. 43 | * You can add more supported options even Typescript doesn't suggest the options. 44 | */ 45 | private _options?: JoditProConfig = {}; 46 | @Input() set options(value: JoditProConfig) { 47 | this._options = value; 48 | 49 | if (value) { 50 | this.initJoditContainer().then(); 51 | } 52 | } 53 | 54 | // value property (subject) 55 | private valueSubject: BehaviorSubject = new BehaviorSubject(''); 56 | 57 | @Input() set value(value: string) { 58 | const sanitizedText = this.prepareText(value); 59 | if (!this.internValueChange) { 60 | this.valueSubject.next(sanitizedText); 61 | } else { 62 | this.internValueChange = false; 63 | } 64 | this.onChange(sanitizedText); 65 | } 66 | 67 | get value(): string { 68 | return this.valueSubject.getValue(); 69 | } 70 | 71 | @Output() valueChange = new EventEmitter(); 72 | 73 | //events 74 | @Output() joditChange = new EventEmitter(); 75 | @Output() joditKeyDown = new EventEmitter(); 76 | @Output() joditKeyUp = new EventEmitter(); 77 | @Output() joditMousedown = new EventEmitter(); 78 | @Output() joditMouseup = new EventEmitter(); 79 | @Output() joditClick = new EventEmitter(); 80 | @Output() joditFocus = new EventEmitter(); 81 | @Output() joditPaste = new EventEmitter(); 82 | @Output() joditResize = new EventEmitter(); 83 | @Output() joditBeforeEnter = new EventEmitter(); 84 | @Output() joditBeforeCommand = new EventEmitter(); 85 | @Output() joditAfterExec = new EventEmitter(); 86 | @Output() joditAfterPaste = new EventEmitter(); 87 | @Output() joditChangeSelection = new EventEmitter(); 88 | 89 | // Used for delay value assignment to wait for jodit to be initialized 90 | private joditInitializedSubject: BehaviorSubject = new BehaviorSubject(false); 91 | private valueSubscription?: Subscription; 92 | private internValueChange = false; 93 | 94 | constructor( 95 | private readonly cdr: ChangeDetectorRef, 96 | ) { 97 | this.valueSubscription = combineLatest([ 98 | // Handle value changes ... 99 | this.valueSubject.asObservable().pipe(distinctUntilChanged()), 100 | // ...additionally ensuring that the value is reapplied if the editor was not initialized when value was set 101 | this.joditInitializedSubject.pipe(distinctUntilChanged(), filter(initialized => initialized)) 102 | ]).pipe( 103 | // Pass through the latest value in case of editor initialization 104 | withLatestFrom(this.valueSubject), 105 | // Prevent ExpressionChangedAfterItHasBeenCheckedError 106 | delay(0) 107 | ).subscribe(([[_, initialized], text]) => { 108 | if (this.jodit && initialized) { 109 | this.jodit.setEditorValue(text); 110 | } 111 | }); 112 | } 113 | 114 | isHTML(text: string) { 115 | const elem = document.createElement('div'); 116 | elem.innerHTML = text; 117 | 118 | return ( 119 | text && 120 | elem.childNodes.length > 0 && 121 | elem.childNodes.item(0).nodeType !== 3 122 | ); 123 | } 124 | 125 | async ngAfterViewInit() { 126 | await this.initJoditContainer(); 127 | } 128 | 129 | ngOnDestroy() { 130 | this.valueSubscription?.unsubscribe(); 131 | this.jodit?.events.destruct(); 132 | } 133 | 134 | async initJoditContainer() { 135 | if (this.joditContainer?.nativeElement) { 136 | if (this.jodit) { 137 | this.jodit.destruct(); 138 | this.joditInitializedSubject.next(false); 139 | } 140 | this.jodit = Jodit.make(this.joditContainer.nativeElement, this._options) as IJodit; 141 | await this.jodit.waitForReady(); 142 | this.jodit.setEditorValue(this.valueSubject.getValue()); 143 | 144 | this.jodit.events.on('change', (text: string) => { 145 | this.internValueChange = true; 146 | this.changeValue(text); 147 | this.joditChange.emit(text); 148 | this.onChange(text); 149 | }); 150 | this.jodit.events.on('keydown', (a: KeyboardEvent) => { 151 | this.joditKeyDown.emit(a); 152 | }); 153 | this.jodit.events.on('keyup', (a: KeyboardEvent) => { 154 | this.joditKeyUp.emit(a); 155 | }); 156 | this.jodit.events.on('mousedown', (a: MouseEvent) => { 157 | this.joditMousedown.emit(a); 158 | }); 159 | this.jodit.events.on('mouseup', (a: MouseEvent) => { 160 | this.joditMouseup.emit(a); 161 | }); 162 | this.jodit.events.on('click', (a: PointerEvent) => { 163 | this.joditClick.emit(a); 164 | this.onTouched(); 165 | }); 166 | this.jodit.events.on('focus', (a: FocusEvent) => { 167 | this.joditFocus.emit(a); 168 | }); 169 | this.jodit.events.on('paste', (a: ClipboardEvent) => { 170 | this.joditPaste.emit(a); 171 | }); 172 | this.jodit.events.on('resize', () => { 173 | this.joditResize.emit(); 174 | }); 175 | this.jodit.events.on('beforeEnter', (a: KeyboardEvent) => { 176 | this.joditBeforeEnter.emit(a); 177 | }); 178 | this.jodit.events.on('beforeCommand', (a: string) => { 179 | this.joditBeforeCommand.emit(a); 180 | }); 181 | this.jodit.events.on('afterExec', () => { 182 | this.joditAfterExec.emit(); 183 | }); 184 | this.jodit.events.on('afterPaste', (a: ClipboardEvent) => { 185 | this.joditAfterPaste.emit(a); 186 | }); 187 | this.jodit.events.on('changeSelection', () => { 188 | this.joditChangeSelection.emit(); 189 | }); 190 | 191 | this.joditInitializedSubject.next(true); 192 | } 193 | } 194 | 195 | changeValue(value: string) { 196 | this.valueChange.emit(value); 197 | } 198 | 199 | /* 200 | FUNCTIONS RELEVANT FOR ANGULAR FORMS 201 | */ 202 | 203 | onChange = (text: string) => { 204 | // implemented by user 205 | }; 206 | 207 | onTouched = () => { 208 | // implemented by user 209 | }; 210 | 211 | writeValue(text: string): void { 212 | this.valueSubject.next(this.prepareText(text)); 213 | } 214 | 215 | registerOnChange(fn: (text: string) => void): void { 216 | this.onChange = fn; 217 | } 218 | 219 | registerOnTouched(fn: () => void): void { 220 | this.onTouched = fn; 221 | } 222 | 223 | setDisabledState?(isDisabled: boolean): void { 224 | this.options = { 225 | ...this._options, 226 | disabled: isDisabled 227 | }; 228 | } 229 | 230 | private prepareText(text: string) { 231 | return this.isHTML(text) ? text : `

${text}

`; 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /libs/ngx-jodit-pro/README.md: -------------------------------------------------------------------------------- 1 | # ngx-jodit-pro v3.x 2 | 3 | Angular wrapper for Jodit PRO WYSIWYG editor. It supports Angular >= 16 and 4 | jodit-pro v2 beta. You need a license key in order to use this wrapper. 5 | Buy here. 6 | 7 | ## License 8 | 9 | This package does not contain the source code of Jodit Pro. You have to install it as described here (scroll down). This 10 | wrapper is licensed under MIT License, Jodit Pro is licensed 11 | seperately ([see license](https://xdsoft.net/jodit/pro/license/)). 12 | 13 | ## Compatibility 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
Ngx-jodit-proJodit ProAngularTypeDemoReadme
npmv4.x>= v16StandaloneDemoReadme
npmv4.xv12 - v15ModuleDemoReadme
v1.x (deprecated)v1.xv12 - v15ModuleDemoReadme
29 | 30 | ## Demo 31 | 32 | You can find a demo of ngx-jodit-pro 3.x [here](https://github.julianpoemp.com/ngx-jodit-pro/3.x/). 33 | 34 | ## Remarks 35 | 36 | ESM for Jodit-Pro is not currently working. See [issue 34](https://github.com/julianpoemp/ngx-jodit/issues/34). You have to include the es2021 build (see installation). 37 | 38 | ## Installation 39 | 40 | 1. Make sure that jodit-pro@4 AND jodit@4 is installed: 41 | ``` 42 | npm install jodit-pro@4 jodit@4 --save 43 | ``` 44 | 2. ``` 45 | npm install ngx-jodit-pro --save 46 | ``` 47 | 3. Add the following paths to your app's styles and scripts in angular.json (or project.json for 48 | Nx): 49 | ``` 50 | ... 51 | , 52 | "styles": [ 53 | "node_modules/jodit-pro/es2021/jodit.min.css", 54 | ... 55 | ], 56 | "scripts": [ 57 | "node_modules/jodit-pro/es2021/jodit.min.js", 58 | ... 59 | ], 60 | ... 61 | ``` 62 | 63 | 4. Add `NgxJoditProComponent` (standalone) to the `imports` array in your app.module.ts: 64 | ``` 65 | @NgModule({ 66 | ... 67 | imports: [ 68 | ..., 69 | NgxJoditProComponent 70 | ], 71 | ... 72 | }) 73 | ``` 74 | 5. Add `"skipLibCheck": true` to compilerOptions in your `tsconfig.app.json`. This is needed because the 75 | check fails to typing errors of the jodit package. **This is still the issue in v4**. If you know any other solution, let me know :): 76 | ``` 77 | ... 78 | "compilerOptions": { 79 | ..., 80 | "skipLibCheck": true 81 | } 82 | ... 83 | ``` 84 | 85 | 6. Each toolbar element by Jodit v4 is considered as plugin. While basic plugins are imported automatically, you have to import other plugins manually. See section "How to import plugins". 86 | 87 | 7. Now you can use the component. See [example here](https://github.com/julianpoemp/ngx-jodit/tree/main/apps/demo-pro). 88 | 89 | - Without AngularForms: 90 | 91 | ```angular2html 92 | 93 | ``` 94 | 95 | - With AngularForms (make sure to import AngularForms): 96 | - Template driven 97 | 98 | ```angular2html 99 | 100 | ``` 101 | - Reactive 102 | ```angular2html 103 |
104 | 105 |
106 | ``` 107 | 108 | If you are facing any issues have a look on [Troubleshooting](https://github.com/julianpoemp/ngx-jodit/blob/main/libs/ngx-jodit/README.md#troubleshooting) first. Create an issue if it's not solved. 109 | 110 | ## How to import plugins 111 | 112 | You can install plugins from Jodit and Jodit Pro. For more information about Jodit Pro plugins see [Jodit Pro Docs](https://xdsoft.net/jodit/pro/docs/). 113 | 114 | 1. Open folder "node_modules/jodit-pro" or "node_modules/jodit" depending on if you want to add jodit oder jodit-pro plugins. 115 | 2. Open the plugin folder in "esm/plugins", e.g. "tune-block" in "jodit-pro". 116 | 3. Look for the main file named like the plugin e.g. "tune-block.js". 117 | 4. Import "jodit" and the path to this file in a Typescript file of your application. E.g. the Angular component that includes ngx-jodit-pro. For example: 118 | 119 | ```typescript 120 | import "node_modules/jodit-pro/esm/plugins/tune-block/tune-block.js"; 121 | 122 | declare const Jodit: any; // <- needed because of missing ESM, see issue 34 123 | Jodit.lang.de = de; 124 | ``` 125 | 126 | You can import your plugins wherever you want, e.g. in a global ts file that's imported anyway like index.ts or main.ts files. 127 | 128 | Now you can apply the plugin options to ngx-jodit-pro `options` property. For example: 129 | 130 | ```typescript 131 | import {JoditProConfig} from 'ngx-jodit-pro'; 132 | import "node_modules/jodit-pro/esm/plugins/tune-block/tune-block.js"; 133 | 134 | declare const Jodit: any; // <- needed because of missing ESM, see issue 34 135 | 136 | options: JoditProConfig = { 137 | tuneBlock: { 138 | popup: { 139 | p: Jodit.atom(['align', 'tune.up', 'tune.remove', 'tune.down']) 140 | } 141 | } 142 | } 143 | ``` 144 | 145 | ### Add custom plugins 146 | 147 | You can access the initialized Jodit from the attribute "jodit" of the NgxJoditProComponent to use the Pro API: 148 | 149 | Any component.ts: 150 | 151 | ````Typescript 152 | import {ViewChild} from '@angular/core'; 153 | 154 | //... 155 | @ViewChild("joditComponent") 156 | joditComponent ? : NgxJoditProComponent; 157 | 158 | // in ngAfterViewInit 159 | if (this.joditComponent) { 160 | // example: 161 | this.joditComponent.jodit.plugins.add("hello", () => { 162 | alert("hello!"); 163 | }); 164 | } 165 | ```` 166 | 167 | Any component.html: 168 | 169 | ```HTML 170 | 171 | 172 | ``` 173 | 174 | ### Options 175 | 176 | All [options](https://xdsoft.net/jodit/docs/classes/config.Config.html) from Jodit AND JoditPro are supported. Use type "JoditProConfig" for options. 177 | 178 | ### Options for ngx-jodit 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 |
NameTypeDescription
valuetwo-way data-bindingUpdates as soon as HTML value of the editor changed. You can set your value, too.
optionsone-way data-bindingSets options for Jodit
201 | 202 | ## Events for ngx-jodit 203 | 204 | You can bind events using the Angular way, e.g.: 205 | 206 | ```angular2html 207 | 208 | 209 | ``` 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 |
NameDescription
joditChangeTriggers as soon as something of the HTML value changes.
joditKeyDownTriggers as soon as a key is pressed down.
joditKeyUpTriggers as soon as a key is released.
joditMousedownTriggers as soon as the left mouse button is pressed.
joditMouseupTriggers as soon as the left mouse button is released.
joditClickTriggers as soon as the user clicks on the editor.
joditFocusTriggers as soon as Jodit gets focus.
joditPasteTriggers as soon as something is pasted.
joditResizeTriggers as soon as the editor resizes.
joditBeforeEnterTriggers as soon as enter key is pressed.
joditBeforeCommandTriggers before a command is executed.
joditAfterExecTriggers after a command is executed.
joditAfterPasteTriggers after something pasted.
joditChangeSelectionTriggers as soon as selection is changed.
277 | 278 | ## Troubleshooting 279 | 280 | - **Some of the buttons don't show any icon**
Check your options if you used the correct button names. If yes, check the folder `node_modules/jodit/es2021/plugins/` for a folder named like the button you want to use. Then import the found plugin to your app as described [here](https://github.com/julianpoemp/ngx-jodit/blob/main/libs/ngx-jodit-pro/README.md#how-to-import-plugins). If that doesn't helpt look in the web console for an error message that indicates a missing plugin. 281 | -------------------------------------------------------------------------------- /migrations.json: -------------------------------------------------------------------------------- 1 | { 2 | "migrations": [ 3 | { 4 | "version": "20.0.0-beta.7", 5 | "description": "Migration for v20.0.0-beta.7", 6 | "implementation": "./src/migrations/update-20-0-0/move-use-daemon-process", 7 | "package": "nx", 8 | "name": "move-use-daemon-process" 9 | }, 10 | { 11 | "version": "20.0.1", 12 | "description": "Set `useLegacyCache` to true for migrating workspaces", 13 | "implementation": "./src/migrations/update-20-0-1/use-legacy-cache", 14 | "x-repair-skip": true, 15 | "package": "nx", 16 | "name": "use-legacy-cache" 17 | }, 18 | { 19 | "version": "21.0.0-beta.8", 20 | "description": "Removes the legacy cache configuration from nx.json", 21 | "implementation": "./src/migrations/update-21-0-0/remove-legacy-cache", 22 | "package": "nx", 23 | "name": "remove-legacy-cache" 24 | }, 25 | { 26 | "version": "21.0.0-beta.8", 27 | "description": "Removes the legacy cache configuration from nx.json", 28 | "implementation": "./src/migrations/update-21-0-0/remove-custom-tasks-runner", 29 | "package": "nx", 30 | "name": "remove-custom-tasks-runner" 31 | }, 32 | { 33 | "version": "21.0.0-beta.11", 34 | "description": "Updates release version config based on the breaking changes in Nx v21", 35 | "implementation": "./src/migrations/update-21-0-0/release-version-config-changes", 36 | "package": "nx", 37 | "name": "release-version-config-changes" 38 | }, 39 | { 40 | "version": "21.0.0-beta.11", 41 | "description": "Updates release changelog config based on the breaking changes in Nx v21", 42 | "implementation": "./src/migrations/update-21-0-0/release-changelog-config-changes", 43 | "package": "nx", 44 | "name": "release-changelog-config-changes" 45 | }, 46 | { 47 | "version": "21.1.0-beta.2", 48 | "description": "Adds **/nx-rules.mdc and **/nx.instructions.md to .gitignore if not present", 49 | "implementation": "./src/migrations/update-21-1-0/add-gitignore-entry", 50 | "package": "nx", 51 | "name": "21-1-0-add-ignore-entries-for-nx-rule-files" 52 | }, 53 | { 54 | "version": "22.0.0-beta.1", 55 | "description": "Updates release version config based on the breaking changes in Nx v22", 56 | "implementation": "./src/migrations/update-22-0-0/release-version-config-changes", 57 | "package": "nx", 58 | "name": "22-0-0-release-version-config-changes" 59 | }, 60 | { 61 | "version": "22.0.0-beta.2", 62 | "description": "Consolidates releaseTag* options into nested releaseTag object structure", 63 | "implementation": "./src/migrations/update-22-0-0/consolidate-release-tag-config", 64 | "package": "nx", 65 | "name": "22-0-0-consolidate-release-tag-config" 66 | }, 67 | { 68 | "cli": "nx", 69 | "version": "22.1.0-beta.5", 70 | "description": "Updates the nx wrapper.", 71 | "implementation": "./src/migrations/update-22-1-0/update-nx-wrapper", 72 | "package": "nx", 73 | "name": "22-1-0-update-nx-wrapper" 74 | }, 75 | { 76 | "cli": "nx", 77 | "version": "20.0.0-beta.5", 78 | "description": "Replace usage of `getJestProjects` with `getJestProjectsAsync`.", 79 | "implementation": "./src/migrations/update-20-0-0/replace-getJestProjects-with-getJestProjectsAsync", 80 | "package": "@nx/jest", 81 | "name": "replace-getJestProjects-with-getJestProjectsAsync" 82 | }, 83 | { 84 | "cli": "nx", 85 | "version": "21.0.0-beta.9", 86 | "description": "Replace usage of `getJestProjects` with `getJestProjectsAsync`.", 87 | "implementation": "./src/migrations/update-21-0-0/replace-getJestProjects-with-getJestProjectsAsync", 88 | "package": "@nx/jest", 89 | "name": "replace-getJestProjects-with-getJestProjectsAsync-v21" 90 | }, 91 | { 92 | "version": "21.0.0-beta.10", 93 | "description": "Remove the previously deprecated and unused `tsConfig` option from the `@nx/jest:jest` executor.", 94 | "implementation": "./src/migrations/update-21-0-0/remove-tsconfig-option-from-jest-executor", 95 | "package": "@nx/jest", 96 | "name": "remove-tsconfig-option-from-jest-executor" 97 | }, 98 | { 99 | "version": "21.3.0-beta.3", 100 | "description": "Rename the CLI option `testPathPattern` to `testPathPatterns`.", 101 | "implementation": "./src/migrations/update-21-3-0/rename-test-path-pattern", 102 | "package": "@nx/jest", 103 | "name": "rename-test-path-pattern" 104 | }, 105 | { 106 | "version": "20.2.0-beta.5", 107 | "description": "Update TypeScript ESLint packages to v8.13.0 if they are already on v8", 108 | "implementation": "./src/migrations/update-20-2-0/update-typescript-eslint-v8-13-0", 109 | "package": "@nx/eslint", 110 | "name": "update-typescript-eslint-v8.13.0" 111 | }, 112 | { 113 | "version": "20.3.0-beta.1", 114 | "description": "Update ESLint flat config to include .cjs, .mjs, .cts, and .mts files in overrides (if needed)", 115 | "implementation": "./src/migrations/update-20-3-0/add-file-extensions-to-overrides", 116 | "package": "@nx/eslint", 117 | "name": "add-file-extensions-to-overrides" 118 | }, 119 | { 120 | "version": "21.5.0-beta.2", 121 | "description": "Migrate the legacy 'development' custom condition to a workspace-unique custom condition name.", 122 | "factory": "./src/migrations/update-21-5-0/migrate-development-custom-condition", 123 | "package": "@nx/js", 124 | "name": "migrate-development-custom-condition" 125 | }, 126 | { 127 | "version": "22.0.0-beta.0", 128 | "description": "Remove the deprecated `external` and `externalBuildTargets` options from the `@nx/js:swc` and `@nx/js:tsc` executors.", 129 | "factory": "./src/migrations/update-22-0-0/remove-external-options-from-js-executors", 130 | "package": "@nx/js", 131 | "name": "remove-external-options-from-js-executors" 132 | }, 133 | { 134 | "version": "22.1.0-rc.1", 135 | "description": "Removes redundant TypeScript project references from project's tsconfig.json files when runtime tsconfig files (e.g., tsconfig.lib.json, tsconfig.app.json) exist.", 136 | "factory": "./src/migrations/update-22-1-0/remove-redundant-ts-project-references", 137 | "package": "@nx/js", 138 | "name": "remove-redundant-ts-project-references" 139 | }, 140 | { 141 | "version": "21.0.0-beta.10", 142 | "description": "Removes the `tsConfig` and `copyFiles` options from the `@nx/cypress:cypress` executor.", 143 | "implementation": "./src/migrations/update-21-0-0/remove-tsconfig-and-copy-files-options-from-cypress-executor", 144 | "package": "@nx/cypress", 145 | "name": "remove-tsconfig-and-copy-files-options-from-cypress-executor" 146 | }, 147 | { 148 | "cli": "nx", 149 | "version": "20.2.0-beta.2", 150 | "description": "Update the ModuleFederationConfig import use @nx/module-federation.", 151 | "factory": "./src/migrations/update-20-2-0/migrate-mf-imports-to-new-package", 152 | "package": "@nx/angular", 153 | "name": "update-20-2-0-update-module-federation-config-import" 154 | }, 155 | { 156 | "cli": "nx", 157 | "version": "20.2.0-beta.2", 158 | "description": "Update the withModuleFederation import use @nx/module-federation/angular.", 159 | "factory": "./src/migrations/update-20-2-0/migrate-with-mf-import-to-new-package", 160 | "package": "@nx/angular", 161 | "name": "update-20-2-0-update-with-module-federation-import" 162 | }, 163 | { 164 | "cli": "nx", 165 | "version": "20.2.0-beta.5", 166 | "requires": { "@angular/core": ">=19.0.0" }, 167 | "description": "Update the @angular/cli package version to ~19.0.0.", 168 | "factory": "./src/migrations/update-20-2-0/update-angular-cli", 169 | "package": "@nx/angular", 170 | "name": "update-angular-cli-version-19-0-0" 171 | }, 172 | { 173 | "cli": "nx", 174 | "version": "20.2.0-beta.5", 175 | "requires": { "@angular/core": ">=19.0.0" }, 176 | "description": "Add the '@angular/localize/init' polyfill to the 'polyfills' option of targets using esbuild-based executors.", 177 | "factory": "./src/migrations/update-20-2-0/add-localize-polyfill-to-targets", 178 | "package": "@nx/angular", 179 | "name": "add-localize-polyfill-to-targets" 180 | }, 181 | { 182 | "cli": "nx", 183 | "version": "20.2.0-beta.5", 184 | "requires": { "@angular/core": ">=19.0.0" }, 185 | "description": "Update '@angular/ssr' import paths to use the new '/node' entry point when 'CommonEngine' is detected.", 186 | "factory": "./src/migrations/update-20-2-0/update-angular-ssr-imports-to-use-node-entry-point", 187 | "package": "@nx/angular", 188 | "name": "update-angular-ssr-imports-to-use-node-entry-point" 189 | }, 190 | { 191 | "cli": "nx", 192 | "version": "20.2.0-beta.6", 193 | "requires": { "@angular/core": ">=19.0.0" }, 194 | "description": "Disable the Angular ESLint prefer-standalone rule if not set.", 195 | "factory": "./src/migrations/update-20-2-0/disable-angular-eslint-prefer-standalone", 196 | "package": "@nx/angular", 197 | "name": "disable-angular-eslint-prefer-standalone" 198 | }, 199 | { 200 | "cli": "nx", 201 | "version": "20.2.0-beta.8", 202 | "requires": { "@angular/core": ">=19.0.0" }, 203 | "description": "Remove Angular ESLint rules that were removed in v19.0.0.", 204 | "factory": "./src/migrations/update-20-2-0/remove-angular-eslint-rules", 205 | "package": "@nx/angular", 206 | "name": "remove-angular-eslint-rules" 207 | }, 208 | { 209 | "cli": "nx", 210 | "version": "20.2.0-beta.8", 211 | "requires": { "@angular/core": ">=19.0.0" }, 212 | "description": "Remove the deprecated 'tailwindConfig' option from ng-packagr executors. Tailwind CSS configurations located at the project or workspace root will be picked up automatically.", 213 | "factory": "./src/migrations/update-20-2-0/remove-tailwind-config-from-ng-packagr-executors", 214 | "package": "@nx/angular", 215 | "name": "remove-tailwind-config-from-ng-packagr-executors" 216 | }, 217 | { 218 | "cli": "nx", 219 | "version": "20.3.0-beta.2", 220 | "description": "If workspace includes Module Federation projects, ensure the new @nx/module-federation package is installed.", 221 | "factory": "./src/migrations/update-20-3-0/ensure-nx-module-federation-package", 222 | "package": "@nx/angular", 223 | "name": "ensure-nx-module-federation-package" 224 | }, 225 | { 226 | "cli": "nx", 227 | "version": "20.4.0-beta.1", 228 | "requires": { "@angular/core": ">=19.1.0" }, 229 | "description": "Update the @angular/cli package version to ~19.1.0.", 230 | "factory": "./src/migrations/update-20-4-0/update-angular-cli", 231 | "package": "@nx/angular", 232 | "name": "update-angular-cli-version-19-1-0" 233 | }, 234 | { 235 | "cli": "nx", 236 | "version": "20.5.0-beta.5", 237 | "requires": { "@angular/core": ">=19.2.0" }, 238 | "description": "Update the @angular/cli package version to ~19.2.0.", 239 | "factory": "./src/migrations/update-20-5-0/update-angular-cli", 240 | "package": "@nx/angular", 241 | "name": "update-angular-cli-version-19-2-0" 242 | }, 243 | { 244 | "cli": "nx", 245 | "version": "21.0.0-beta.3", 246 | "description": "Set the `continuous` option to `true` for continuous tasks.", 247 | "factory": "./src/migrations/update-21-0-0/set-continuous-option", 248 | "package": "@nx/angular", 249 | "name": "set-continuous-option" 250 | }, 251 | { 252 | "cli": "nx", 253 | "version": "21.2.0-beta.3", 254 | "requires": { "@angular/core": ">=20.0.0" }, 255 | "description": "Update the @angular/cli package version to ~20.0.0.", 256 | "factory": "./src/migrations/update-21-2-0/update-angular-cli", 257 | "package": "@nx/angular", 258 | "name": "update-angular-cli-version-20-0-0" 259 | }, 260 | { 261 | "version": "21.2.0-beta.3", 262 | "requires": { "@angular/core": ">=20.0.0" }, 263 | "description": "Migrate imports of `provideServerRendering` from `@angular/platform-server` to `@angular/ssr`.", 264 | "factory": "./src/migrations/update-21-2-0/migrate-provide-server-rendering-import", 265 | "package": "@nx/angular", 266 | "name": "migrate-provide-server-rendering-import" 267 | }, 268 | { 269 | "version": "21.2.0-beta.3", 270 | "requires": { "@angular/core": ">=20.0.0" }, 271 | "description": "Replace `provideServerRouting` and `provideServerRoutesConfig` with `provideServerRendering` using `withRoutes`.", 272 | "factory": "./src/migrations/update-21-2-0/replace-provide-server-routing", 273 | "package": "@nx/angular", 274 | "name": "replace-provide-server-routing" 275 | }, 276 | { 277 | "version": "21.2.0-beta.3", 278 | "requires": { "@angular/core": ">=20.0.0" }, 279 | "description": "Update the generator defaults to maintain the previous style guide behavior.", 280 | "factory": "./src/migrations/update-21-2-0/set-generator-defaults-for-previous-style-guide", 281 | "package": "@nx/angular", 282 | "name": "set-generator-defaults-for-previous-style-guide" 283 | }, 284 | { 285 | "version": "21.2.0-beta.3", 286 | "requires": { "@angular/core": ">=20.0.0" }, 287 | "description": "Update 'moduleResolution' to 'bundler' in TypeScript configurations. You can read more about this here: https://www.typescriptlang.org/tsconfig/#moduleResolution.", 288 | "factory": "./src/migrations/update-21-2-0/update-module-resolution", 289 | "package": "@nx/angular", 290 | "name": "update-module-resolution" 291 | }, 292 | { 293 | "cli": "nx", 294 | "version": "21.3.0-beta.4", 295 | "requires": { "@angular/core": ">=20.1.0" }, 296 | "description": "Update the @angular/cli package version to ~20.1.0.", 297 | "factory": "./src/migrations/update-21-3-0/update-angular-cli", 298 | "package": "@nx/angular", 299 | "name": "update-angular-cli-version-20-1-0" 300 | }, 301 | { 302 | "version": "21.5.0-beta.0", 303 | "description": "Set the 'tsConfig' option to build and test targets to help with Angular migration issues.", 304 | "factory": "./src/migrations/update-21-5-0/set-tsconfig-option", 305 | "package": "@nx/angular", 306 | "name": "set-tsconfig-option" 307 | }, 308 | { 309 | "cli": "nx", 310 | "version": "21.5.0-beta.2", 311 | "requires": { "@angular/core": ">=20.2.0" }, 312 | "description": "Update the @angular/cli package version to ~20.2.0.", 313 | "factory": "./src/migrations/update-21-5-0/update-angular-cli", 314 | "package": "@nx/angular", 315 | "name": "update-angular-cli-version-20-2-0" 316 | }, 317 | { 318 | "version": "21.5.0-beta.2", 319 | "requires": { "@angular/core": ">=20.2.0" }, 320 | "description": "Remove any Karma configuration files that only contain the default content. The default configuration is automatically available without a specific project configurationfile.", 321 | "factory": "./src/migrations/update-21-5-0/remove-default-karma-configuration-files", 322 | "package": "@nx/angular", 323 | "name": "remove-default-karma-configuration-files" 324 | }, 325 | { 326 | "cli": "nx", 327 | "version": "21.6.1-beta.2", 328 | "requires": { "@angular/core": ">=20.3.0" }, 329 | "description": "Update the @angular/cli package version to ~20.3.0.", 330 | "factory": "./src/migrations/update-21-6-1/update-angular-cli", 331 | "package": "@nx/angular", 332 | "name": "update-angular-cli-version-20-3-0" 333 | }, 334 | { 335 | "version": "20.0.0", 336 | "description": "Replaces usages of the deprecated InjectFlags enum", 337 | "factory": "./bundles/inject-flags.cjs#migrate", 338 | "package": "@angular/core", 339 | "name": "inject-flags" 340 | }, 341 | { 342 | "version": "20.0.0", 343 | "description": "Replaces usages of the deprecated TestBed.get method with TestBed.inject", 344 | "factory": "./bundles/test-bed-get.cjs#migrate", 345 | "package": "@angular/core", 346 | "name": "test-bed-get" 347 | }, 348 | { 349 | "version": "20.0.0", 350 | "description": "Converts the entire application to block control flow syntax", 351 | "factory": "./bundles/control-flow-migration.cjs#migrate", 352 | "optional": true, 353 | "package": "@angular/core", 354 | "name": "control-flow-migration" 355 | }, 356 | { 357 | "version": "20.0.0", 358 | "description": "Moves imports of `DOCUMENT` from `@angular/common` to `@angular/core`", 359 | "factory": "./bundles/document-core.cjs#migrate", 360 | "package": "@angular/core", 361 | "name": "document-core" 362 | }, 363 | { 364 | "version": "20.2.0", 365 | "description": "Replaces usages of the deprecated Router.getCurrentNavigation method with the Router.currentNavigation signal", 366 | "factory": "./bundles/router-current-navigation.cjs#migrate", 367 | "optional": true, 368 | "package": "@angular/core", 369 | "name": "router-current-navigation" 370 | }, 371 | { 372 | "version": "20.3.0", 373 | "description": "Adds `BootstrapContext` to `bootstrapApplication` calls in `main.server.ts` to support server rendering.", 374 | "factory": "./bundles/add-bootstrap-context-to-server-main.cjs#migrate", 375 | "package": "@angular/core", 376 | "name": "add-bootstrap-context-to-server-main" 377 | } 378 | ] 379 | } 380 | -------------------------------------------------------------------------------- /docs/3rdpartylicenses.txt: -------------------------------------------------------------------------------- 1 | @angular/common 2 | MIT 3 | 4 | @angular/core 5 | MIT 6 | 7 | @angular/forms 8 | MIT 9 | 10 | @angular/platform-browser 11 | MIT 12 | 13 | autobind-decorator 14 | MIT 15 | MIT License 16 | 17 | Copyright (c) Andrey Popp 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in all 27 | copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. 36 | 37 | 38 | bootstrap 39 | MIT 40 | The MIT License (MIT) 41 | 42 | Copyright (c) 2011-2022 Twitter, Inc. 43 | Copyright (c) 2011-2022 The Bootstrap Authors 44 | 45 | Permission is hereby granted, free of charge, to any person obtaining a copy 46 | of this software and associated documentation files (the "Software"), to deal 47 | in the Software without restriction, including without limitation the rights 48 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 49 | copies of the Software, and to permit persons to whom the Software is 50 | furnished to do so, subject to the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be included in 53 | all copies or substantial portions of the Software. 54 | 55 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 56 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 57 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 58 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 59 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 60 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 61 | THE SOFTWARE. 62 | 63 | 64 | bootstrap-icons 65 | MIT 66 | The MIT License (MIT) 67 | 68 | Copyright (c) 2019-2021 The Bootstrap Authors 69 | 70 | Permission is hereby granted, free of charge, to any person obtaining a copy 71 | of this software and associated documentation files (the "Software"), to deal 72 | in the Software without restriction, including without limitation the rights 73 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 74 | copies of the Software, and to permit persons to whom the Software is 75 | furnished to do so, subject to the following conditions: 76 | 77 | The above copyright notice and this permission notice shall be included in 78 | all copies or substantial portions of the Software. 79 | 80 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 81 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 82 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 83 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 84 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 85 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 86 | THE SOFTWARE. 87 | 88 | 89 | jodit 90 | MIT 91 | Copyright (c) 2013-2023 http://xdsoft.net 92 | 93 | Permission is hereby granted, free of charge, to any person obtaining a copy 94 | of this software and associated documentation files (the "Software"), to deal 95 | in the Software without restriction, including without limitation the rights 96 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 97 | copies of the Software, and to permit persons to whom the Software is 98 | furnished to do so, subject to the following conditions: 99 | 100 | The above copyright notice and this permission notice shall be included in 101 | all copies or substantial portions of the Software. 102 | 103 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 104 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 105 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 106 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 107 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 108 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 109 | THE SOFTWARE. 110 | 111 | 112 | ngx-jodit 113 | MIT 114 | 115 | rxjs 116 | Apache-2.0 117 | Apache License 118 | Version 2.0, January 2004 119 | http://www.apache.org/licenses/ 120 | 121 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 122 | 123 | 1. Definitions. 124 | 125 | "License" shall mean the terms and conditions for use, reproduction, 126 | and distribution as defined by Sections 1 through 9 of this document. 127 | 128 | "Licensor" shall mean the copyright owner or entity authorized by 129 | the copyright owner that is granting the License. 130 | 131 | "Legal Entity" shall mean the union of the acting entity and all 132 | other entities that control, are controlled by, or are under common 133 | control with that entity. For the purposes of this definition, 134 | "control" means (i) the power, direct or indirect, to cause the 135 | direction or management of such entity, whether by contract or 136 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 137 | outstanding shares, or (iii) beneficial ownership of such entity. 138 | 139 | "You" (or "Your") shall mean an individual or Legal Entity 140 | exercising permissions granted by this License. 141 | 142 | "Source" form shall mean the preferred form for making modifications, 143 | including but not limited to software source code, documentation 144 | source, and configuration files. 145 | 146 | "Object" form shall mean any form resulting from mechanical 147 | transformation or translation of a Source form, including but 148 | not limited to compiled object code, generated documentation, 149 | and conversions to other media types. 150 | 151 | "Work" shall mean the work of authorship, whether in Source or 152 | Object form, made available under the License, as indicated by a 153 | copyright notice that is included in or attached to the work 154 | (an example is provided in the Appendix below). 155 | 156 | "Derivative Works" shall mean any work, whether in Source or Object 157 | form, that is based on (or derived from) the Work and for which the 158 | editorial revisions, annotations, elaborations, or other modifications 159 | represent, as a whole, an original work of authorship. For the purposes 160 | of this License, Derivative Works shall not include works that remain 161 | separable from, or merely link (or bind by name) to the interfaces of, 162 | the Work and Derivative Works thereof. 163 | 164 | "Contribution" shall mean any work of authorship, including 165 | the original version of the Work and any modifications or additions 166 | to that Work or Derivative Works thereof, that is intentionally 167 | submitted to Licensor for inclusion in the Work by the copyright owner 168 | or by an individual or Legal Entity authorized to submit on behalf of 169 | the copyright owner. For the purposes of this definition, "submitted" 170 | means any form of electronic, verbal, or written communication sent 171 | to the Licensor or its representatives, including but not limited to 172 | communication on electronic mailing lists, source code control systems, 173 | and issue tracking systems that are managed by, or on behalf of, the 174 | Licensor for the purpose of discussing and improving the Work, but 175 | excluding communication that is conspicuously marked or otherwise 176 | designated in writing by the copyright owner as "Not a Contribution." 177 | 178 | "Contributor" shall mean Licensor and any individual or Legal Entity 179 | on behalf of whom a Contribution has been received by Licensor and 180 | subsequently incorporated within the Work. 181 | 182 | 2. Grant of Copyright License. Subject to the terms and conditions of 183 | this License, each Contributor hereby grants to You a perpetual, 184 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 185 | copyright license to reproduce, prepare Derivative Works of, 186 | publicly display, publicly perform, sublicense, and distribute the 187 | Work and such Derivative Works in Source or Object form. 188 | 189 | 3. Grant of Patent License. Subject to the terms and conditions of 190 | this License, each Contributor hereby grants to You a perpetual, 191 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 192 | (except as stated in this section) patent license to make, have made, 193 | use, offer to sell, sell, import, and otherwise transfer the Work, 194 | where such license applies only to those patent claims licensable 195 | by such Contributor that are necessarily infringed by their 196 | Contribution(s) alone or by combination of their Contribution(s) 197 | with the Work to which such Contribution(s) was submitted. If You 198 | institute patent litigation against any entity (including a 199 | cross-claim or counterclaim in a lawsuit) alleging that the Work 200 | or a Contribution incorporated within the Work constitutes direct 201 | or contributory patent infringement, then any patent licenses 202 | granted to You under this License for that Work shall terminate 203 | as of the date such litigation is filed. 204 | 205 | 4. Redistribution. You may reproduce and distribute copies of the 206 | Work or Derivative Works thereof in any medium, with or without 207 | modifications, and in Source or Object form, provided that You 208 | meet the following conditions: 209 | 210 | (a) You must give any other recipients of the Work or 211 | Derivative Works a copy of this License; and 212 | 213 | (b) You must cause any modified files to carry prominent notices 214 | stating that You changed the files; and 215 | 216 | (c) You must retain, in the Source form of any Derivative Works 217 | that You distribute, all copyright, patent, trademark, and 218 | attribution notices from the Source form of the Work, 219 | excluding those notices that do not pertain to any part of 220 | the Derivative Works; and 221 | 222 | (d) If the Work includes a "NOTICE" text file as part of its 223 | distribution, then any Derivative Works that You distribute must 224 | include a readable copy of the attribution notices contained 225 | within such NOTICE file, excluding those notices that do not 226 | pertain to any part of the Derivative Works, in at least one 227 | of the following places: within a NOTICE text file distributed 228 | as part of the Derivative Works; within the Source form or 229 | documentation, if provided along with the Derivative Works; or, 230 | within a display generated by the Derivative Works, if and 231 | wherever such third-party notices normally appear. The contents 232 | of the NOTICE file are for informational purposes only and 233 | do not modify the License. You may add Your own attribution 234 | notices within Derivative Works that You distribute, alongside 235 | or as an addendum to the NOTICE text from the Work, provided 236 | that such additional attribution notices cannot be construed 237 | as modifying the License. 238 | 239 | You may add Your own copyright statement to Your modifications and 240 | may provide additional or different license terms and conditions 241 | for use, reproduction, or distribution of Your modifications, or 242 | for any such Derivative Works as a whole, provided Your use, 243 | reproduction, and distribution of the Work otherwise complies with 244 | the conditions stated in this License. 245 | 246 | 5. Submission of Contributions. Unless You explicitly state otherwise, 247 | any Contribution intentionally submitted for inclusion in the Work 248 | by You to the Licensor shall be under the terms and conditions of 249 | this License, without any additional terms or conditions. 250 | Notwithstanding the above, nothing herein shall supersede or modify 251 | the terms of any separate license agreement you may have executed 252 | with Licensor regarding such Contributions. 253 | 254 | 6. Trademarks. This License does not grant permission to use the trade 255 | names, trademarks, service marks, or product names of the Licensor, 256 | except as required for reasonable and customary use in describing the 257 | origin of the Work and reproducing the content of the NOTICE file. 258 | 259 | 7. Disclaimer of Warranty. Unless required by applicable law or 260 | agreed to in writing, Licensor provides the Work (and each 261 | Contributor provides its Contributions) on an "AS IS" BASIS, 262 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 263 | implied, including, without limitation, any warranties or conditions 264 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 265 | PARTICULAR PURPOSE. You are solely responsible for determining the 266 | appropriateness of using or redistributing the Work and assume any 267 | risks associated with Your exercise of permissions under this License. 268 | 269 | 8. Limitation of Liability. In no event and under no legal theory, 270 | whether in tort (including negligence), contract, or otherwise, 271 | unless required by applicable law (such as deliberate and grossly 272 | negligent acts) or agreed to in writing, shall any Contributor be 273 | liable to You for damages, including any direct, indirect, special, 274 | incidental, or consequential damages of any character arising as a 275 | result of this License or out of the use or inability to use the 276 | Work (including but not limited to damages for loss of goodwill, 277 | work stoppage, computer failure or malfunction, or any and all 278 | other commercial damages or losses), even if such Contributor 279 | has been advised of the possibility of such damages. 280 | 281 | 9. Accepting Warranty or Additional Liability. While redistributing 282 | the Work or Derivative Works thereof, You may choose to offer, 283 | and charge a fee for, acceptance of support, warranty, indemnity, 284 | or other liability obligations and/or rights consistent with this 285 | License. However, in accepting such obligations, You may act only 286 | on Your own behalf and on Your sole responsibility, not on behalf 287 | of any other Contributor, and only if You agree to indemnify, 288 | defend, and hold each Contributor harmless for any liability 289 | incurred by, or claims asserted against, such Contributor by reason 290 | of your accepting any such warranty or additional liability. 291 | 292 | END OF TERMS AND CONDITIONS 293 | 294 | APPENDIX: How to apply the Apache License to your work. 295 | 296 | To apply the Apache License to your work, attach the following 297 | boilerplate notice, with the fields enclosed by brackets "[]" 298 | replaced with your own identifying information. (Don't include 299 | the brackets!) The text should be enclosed in the appropriate 300 | comment syntax for the file format. We also recommend that a 301 | file or class name and description of purpose be included on the 302 | same "printed page" as the copyright notice for easier 303 | identification within third-party archives. 304 | 305 | Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors 306 | 307 | Licensed under the Apache License, Version 2.0 (the "License"); 308 | you may not use this file except in compliance with the License. 309 | You may obtain a copy of the License at 310 | 311 | http://www.apache.org/licenses/LICENSE-2.0 312 | 313 | Unless required by applicable law or agreed to in writing, software 314 | distributed under the License is distributed on an "AS IS" BASIS, 315 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 316 | See the License for the specific language governing permissions and 317 | limitations under the License. 318 | 319 | 320 | 321 | tslib 322 | 0BSD 323 | Copyright (c) Microsoft Corporation. 324 | 325 | Permission to use, copy, modify, and/or distribute this software for any 326 | purpose with or without fee is hereby granted. 327 | 328 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 329 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 330 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 331 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 332 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 333 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 334 | PERFORMANCE OF THIS SOFTWARE. 335 | 336 | zone.js 337 | MIT 338 | The MIT License 339 | 340 | Copyright (c) 2010-2023 Google LLC. https://angular.io/license 341 | 342 | Permission is hereby granted, free of charge, to any person obtaining a copy 343 | of this software and associated documentation files (the "Software"), to deal 344 | in the Software without restriction, including without limitation the rights 345 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 346 | copies of the Software, and to permit persons to whom the Software is 347 | furnished to do so, subject to the following conditions: 348 | 349 | The above copyright notice and this permission notice shall be included in 350 | all copies or substantial portions of the Software. 351 | 352 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 353 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 354 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 355 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 356 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 357 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 358 | THE SOFTWARE. 359 | -------------------------------------------------------------------------------- /docs/polyfills.e8c516cd4b0b98b5.js: -------------------------------------------------------------------------------- 1 | "use strict";(self.webpackChunkdemo=self.webpackChunkdemo||[]).push([[429],{538:(ie,Ee,de)=>{de(583)},583:()=>{!function(e){const n=e.performance;function i(M){n&&n.mark&&n.mark(M)}function o(M,T){n&&n.measure&&n.measure(M,T)}i("Zone");const c=e.__Zone_symbol_prefix||"__zone_symbol__";function a(M){return c+M}const y=!0===e[a("forceDuplicateZoneCheck")];if(e.Zone){if(y||"function"!=typeof e.Zone.__symbol__)throw new Error("Zone already loaded.");return e.Zone}let d=(()=>{class M{static assertZonePatched(){if(e.Promise!==oe.ZoneAwarePromise)throw new Error("Zone.js has detected that ZoneAwarePromise `(window|global).Promise` has been overwritten.\nMost likely cause is that a Promise polyfill has been loaded after Zone.js (Polyfilling Promise api is not necessary when zone.js is loaded. If you must load one, do so before loading zone.js.)")}static get root(){let t=M.current;for(;t.parent;)t=t.parent;return t}static get current(){return U.zone}static get currentTask(){return re}static __load_patch(t,r,k=!1){if(oe.hasOwnProperty(t)){if(!k&&y)throw Error("Already loaded patch: "+t)}else if(!e["__Zone_disable_"+t]){const C="Zone:"+t;i(C),oe[t]=r(e,M,z),o(C,C)}}get parent(){return this._parent}get name(){return this._name}constructor(t,r){this._parent=t,this._name=r?r.name||"unnamed":"",this._properties=r&&r.properties||{},this._zoneDelegate=new v(this,this._parent&&this._parent._zoneDelegate,r)}get(t){const r=this.getZoneWith(t);if(r)return r._properties[t]}getZoneWith(t){let r=this;for(;r;){if(r._properties.hasOwnProperty(t))return r;r=r._parent}return null}fork(t){if(!t)throw new Error("ZoneSpec required!");return this._zoneDelegate.fork(this,t)}wrap(t,r){if("function"!=typeof t)throw new Error("Expecting function got: "+t);const k=this._zoneDelegate.intercept(this,t,r),C=this;return function(){return C.runGuarded(k,this,arguments,r)}}run(t,r,k,C){U={parent:U,zone:this};try{return this._zoneDelegate.invoke(this,t,r,k,C)}finally{U=U.parent}}runGuarded(t,r=null,k,C){U={parent:U,zone:this};try{try{return this._zoneDelegate.invoke(this,t,r,k,C)}catch($){if(this._zoneDelegate.handleError(this,$))throw $}}finally{U=U.parent}}runTask(t,r,k){if(t.zone!=this)throw new Error("A task can only be run in the zone of creation! (Creation: "+(t.zone||K).name+"; Execution: "+this.name+")");if(t.state===x&&(t.type===Q||t.type===P))return;const C=t.state!=E;C&&t._transitionTo(E,A),t.runCount++;const $=re;re=t,U={parent:U,zone:this};try{t.type==P&&t.data&&!t.data.isPeriodic&&(t.cancelFn=void 0);try{return this._zoneDelegate.invokeTask(this,t,r,k)}catch(l){if(this._zoneDelegate.handleError(this,l))throw l}}finally{t.state!==x&&t.state!==h&&(t.type==Q||t.data&&t.data.isPeriodic?C&&t._transitionTo(A,E):(t.runCount=0,this._updateTaskCount(t,-1),C&&t._transitionTo(x,E,x))),U=U.parent,re=$}}scheduleTask(t){if(t.zone&&t.zone!==this){let k=this;for(;k;){if(k===t.zone)throw Error(`can not reschedule task to ${this.name} which is descendants of the original zone ${t.zone.name}`);k=k.parent}}t._transitionTo(X,x);const r=[];t._zoneDelegates=r,t._zone=this;try{t=this._zoneDelegate.scheduleTask(this,t)}catch(k){throw t._transitionTo(h,X,x),this._zoneDelegate.handleError(this,k),k}return t._zoneDelegates===r&&this._updateTaskCount(t,1),t.state==X&&t._transitionTo(A,X),t}scheduleMicroTask(t,r,k,C){return this.scheduleTask(new p(I,t,r,k,C,void 0))}scheduleMacroTask(t,r,k,C,$){return this.scheduleTask(new p(P,t,r,k,C,$))}scheduleEventTask(t,r,k,C,$){return this.scheduleTask(new p(Q,t,r,k,C,$))}cancelTask(t){if(t.zone!=this)throw new Error("A task can only be cancelled in the zone of creation! (Creation: "+(t.zone||K).name+"; Execution: "+this.name+")");if(t.state===A||t.state===E){t._transitionTo(G,A,E);try{this._zoneDelegate.cancelTask(this,t)}catch(r){throw t._transitionTo(h,G),this._zoneDelegate.handleError(this,r),r}return this._updateTaskCount(t,-1),t._transitionTo(x,G),t.runCount=0,t}}_updateTaskCount(t,r){const k=t._zoneDelegates;-1==r&&(t._zoneDelegates=null);for(let C=0;CM.hasTask(t,r),onScheduleTask:(M,T,t,r)=>M.scheduleTask(t,r),onInvokeTask:(M,T,t,r,k,C)=>M.invokeTask(t,r,k,C),onCancelTask:(M,T,t,r)=>M.cancelTask(t,r)};class v{constructor(T,t,r){this._taskCounts={microTask:0,macroTask:0,eventTask:0},this.zone=T,this._parentDelegate=t,this._forkZS=r&&(r&&r.onFork?r:t._forkZS),this._forkDlgt=r&&(r.onFork?t:t._forkDlgt),this._forkCurrZone=r&&(r.onFork?this.zone:t._forkCurrZone),this._interceptZS=r&&(r.onIntercept?r:t._interceptZS),this._interceptDlgt=r&&(r.onIntercept?t:t._interceptDlgt),this._interceptCurrZone=r&&(r.onIntercept?this.zone:t._interceptCurrZone),this._invokeZS=r&&(r.onInvoke?r:t._invokeZS),this._invokeDlgt=r&&(r.onInvoke?t:t._invokeDlgt),this._invokeCurrZone=r&&(r.onInvoke?this.zone:t._invokeCurrZone),this._handleErrorZS=r&&(r.onHandleError?r:t._handleErrorZS),this._handleErrorDlgt=r&&(r.onHandleError?t:t._handleErrorDlgt),this._handleErrorCurrZone=r&&(r.onHandleError?this.zone:t._handleErrorCurrZone),this._scheduleTaskZS=r&&(r.onScheduleTask?r:t._scheduleTaskZS),this._scheduleTaskDlgt=r&&(r.onScheduleTask?t:t._scheduleTaskDlgt),this._scheduleTaskCurrZone=r&&(r.onScheduleTask?this.zone:t._scheduleTaskCurrZone),this._invokeTaskZS=r&&(r.onInvokeTask?r:t._invokeTaskZS),this._invokeTaskDlgt=r&&(r.onInvokeTask?t:t._invokeTaskDlgt),this._invokeTaskCurrZone=r&&(r.onInvokeTask?this.zone:t._invokeTaskCurrZone),this._cancelTaskZS=r&&(r.onCancelTask?r:t._cancelTaskZS),this._cancelTaskDlgt=r&&(r.onCancelTask?t:t._cancelTaskDlgt),this._cancelTaskCurrZone=r&&(r.onCancelTask?this.zone:t._cancelTaskCurrZone),this._hasTaskZS=null,this._hasTaskDlgt=null,this._hasTaskDlgtOwner=null,this._hasTaskCurrZone=null;const k=r&&r.onHasTask;(k||t&&t._hasTaskZS)&&(this._hasTaskZS=k?r:b,this._hasTaskDlgt=t,this._hasTaskDlgtOwner=this,this._hasTaskCurrZone=T,r.onScheduleTask||(this._scheduleTaskZS=b,this._scheduleTaskDlgt=t,this._scheduleTaskCurrZone=this.zone),r.onInvokeTask||(this._invokeTaskZS=b,this._invokeTaskDlgt=t,this._invokeTaskCurrZone=this.zone),r.onCancelTask||(this._cancelTaskZS=b,this._cancelTaskDlgt=t,this._cancelTaskCurrZone=this.zone))}fork(T,t){return this._forkZS?this._forkZS.onFork(this._forkDlgt,this.zone,T,t):new d(T,t)}intercept(T,t,r){return this._interceptZS?this._interceptZS.onIntercept(this._interceptDlgt,this._interceptCurrZone,T,t,r):t}invoke(T,t,r,k,C){return this._invokeZS?this._invokeZS.onInvoke(this._invokeDlgt,this._invokeCurrZone,T,t,r,k,C):t.apply(r,k)}handleError(T,t){return!this._handleErrorZS||this._handleErrorZS.onHandleError(this._handleErrorDlgt,this._handleErrorCurrZone,T,t)}scheduleTask(T,t){let r=t;if(this._scheduleTaskZS)this._hasTaskZS&&r._zoneDelegates.push(this._hasTaskDlgtOwner),r=this._scheduleTaskZS.onScheduleTask(this._scheduleTaskDlgt,this._scheduleTaskCurrZone,T,t),r||(r=t);else if(t.scheduleFn)t.scheduleFn(t);else{if(t.type!=I)throw new Error("Task is missing scheduleFn.");R(t)}return r}invokeTask(T,t,r,k){return this._invokeTaskZS?this._invokeTaskZS.onInvokeTask(this._invokeTaskDlgt,this._invokeTaskCurrZone,T,t,r,k):t.callback.apply(r,k)}cancelTask(T,t){let r;if(this._cancelTaskZS)r=this._cancelTaskZS.onCancelTask(this._cancelTaskDlgt,this._cancelTaskCurrZone,T,t);else{if(!t.cancelFn)throw Error("Task is not cancelable");r=t.cancelFn(t)}return r}hasTask(T,t){try{this._hasTaskZS&&this._hasTaskZS.onHasTask(this._hasTaskDlgt,this._hasTaskCurrZone,T,t)}catch(r){this.handleError(T,r)}}_updateTaskCount(T,t){const r=this._taskCounts,k=r[T],C=r[T]=k+t;if(C<0)throw new Error("More tasks executed then were scheduled.");0!=k&&0!=C||this.hasTask(this.zone,{microTask:r.microTask>0,macroTask:r.macroTask>0,eventTask:r.eventTask>0,change:T})}}class p{constructor(T,t,r,k,C,$){if(this._zone=null,this.runCount=0,this._zoneDelegates=null,this._state="notScheduled",this.type=T,this.source=t,this.data=k,this.scheduleFn=C,this.cancelFn=$,!r)throw new Error("callback is not defined");this.callback=r;const l=this;this.invoke=T===Q&&k&&k.useG?p.invokeTask:function(){return p.invokeTask.call(e,l,this,arguments)}}static invokeTask(T,t,r){T||(T=this),ee++;try{return T.runCount++,T.zone.runTask(T,t,r)}finally{1==ee&&_(),ee--}}get zone(){return this._zone}get state(){return this._state}cancelScheduleRequest(){this._transitionTo(x,X)}_transitionTo(T,t,r){if(this._state!==t&&this._state!==r)throw new Error(`${this.type} '${this.source}': can not transition to '${T}', expecting state '${t}'${r?" or '"+r+"'":""}, was '${this._state}'.`);this._state=T,T==x&&(this._zoneDelegates=null)}toString(){return this.data&&typeof this.data.handleId<"u"?this.data.handleId.toString():Object.prototype.toString.call(this)}toJSON(){return{type:this.type,state:this.state,source:this.source,zone:this.zone.name,runCount:this.runCount}}}const L=a("setTimeout"),Z=a("Promise"),N=a("then");let J,B=[],H=!1;function q(M){if(J||e[Z]&&(J=e[Z].resolve(0)),J){let T=J[N];T||(T=J.then),T.call(J,M)}else e[L](M,0)}function R(M){0===ee&&0===B.length&&q(_),M&&B.push(M)}function _(){if(!H){for(H=!0;B.length;){const M=B;B=[];for(let T=0;TU,onUnhandledError:W,microtaskDrainDone:W,scheduleMicroTask:R,showUncaughtError:()=>!d[a("ignoreConsoleErrorUncaughtError")],patchEventTarget:()=>[],patchOnProperties:W,patchMethod:()=>W,bindArguments:()=>[],patchThen:()=>W,patchMacroTask:()=>W,patchEventPrototype:()=>W,isIEOrEdge:()=>!1,getGlobalObjects:()=>{},ObjectDefineProperty:()=>W,ObjectGetOwnPropertyDescriptor:()=>{},ObjectCreate:()=>{},ArraySlice:()=>[],patchClass:()=>W,wrapWithCurrentZone:()=>W,filterProperties:()=>[],attachOriginToPatched:()=>W,_redefineProperty:()=>W,patchCallbacks:()=>W,nativeScheduleMicroTask:q};let U={parent:null,zone:new d(null,null)},re=null,ee=0;function W(){}o("Zone","Zone"),e.Zone=d}(typeof window<"u"&&window||typeof self<"u"&&self||global);const ie=Object.getOwnPropertyDescriptor,Ee=Object.defineProperty,de=Object.getPrototypeOf,ge=Object.create,Ve=Array.prototype.slice,Se="addEventListener",Oe="removeEventListener",Ze=Zone.__symbol__(Se),Ne=Zone.__symbol__(Oe),ce="true",ae="false",ke=Zone.__symbol__("");function Ie(e,n){return Zone.current.wrap(e,n)}function Me(e,n,i,o,c){return Zone.current.scheduleMacroTask(e,n,i,o,c)}const j=Zone.__symbol__,Pe=typeof window<"u",Te=Pe?window:void 0,Y=Pe&&Te||"object"==typeof self&&self||global,ct="removeAttribute";function Le(e,n){for(let i=e.length-1;i>=0;i--)"function"==typeof e[i]&&(e[i]=Ie(e[i],n+"_"+i));return e}function Fe(e){return!e||!1!==e.writable&&!("function"==typeof e.get&&typeof e.set>"u")}const Be=typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope,we=!("nw"in Y)&&typeof Y.process<"u"&&"[object process]"==={}.toString.call(Y.process),Ae=!we&&!Be&&!(!Pe||!Te.HTMLElement),Ue=typeof Y.process<"u"&&"[object process]"==={}.toString.call(Y.process)&&!Be&&!(!Pe||!Te.HTMLElement),Re={},We=function(e){if(!(e=e||Y.event))return;let n=Re[e.type];n||(n=Re[e.type]=j("ON_PROPERTY"+e.type));const i=this||e.target||Y,o=i[n];let c;return Ae&&i===Te&&"error"===e.type?(c=o&&o.call(this,e.message,e.filename,e.lineno,e.colno,e.error),!0===c&&e.preventDefault()):(c=o&&o.apply(this,arguments),null!=c&&!c&&e.preventDefault()),c};function qe(e,n,i){let o=ie(e,n);if(!o&&i&&ie(i,n)&&(o={enumerable:!0,configurable:!0}),!o||!o.configurable)return;const c=j("on"+n+"patched");if(e.hasOwnProperty(c)&&e[c])return;delete o.writable,delete o.value;const a=o.get,y=o.set,d=n.slice(2);let b=Re[d];b||(b=Re[d]=j("ON_PROPERTY"+d)),o.set=function(v){let p=this;!p&&e===Y&&(p=Y),p&&("function"==typeof p[b]&&p.removeEventListener(d,We),y&&y.call(p,null),p[b]=v,"function"==typeof v&&p.addEventListener(d,We,!1))},o.get=function(){let v=this;if(!v&&e===Y&&(v=Y),!v)return null;const p=v[b];if(p)return p;if(a){let L=a.call(this);if(L)return o.set.call(this,L),"function"==typeof v[ct]&&v.removeAttribute(n),L}return null},Ee(e,n,o),e[c]=!0}function Xe(e,n,i){if(n)for(let o=0;ofunction(y,d){const b=i(y,d);return b.cbIdx>=0&&"function"==typeof d[b.cbIdx]?Me(b.name,d[b.cbIdx],b,c):a.apply(y,d)})}function ue(e,n){e[j("OriginalDelegate")]=n}let ze=!1,je=!1;function ft(){if(ze)return je;ze=!0;try{const e=Te.navigator.userAgent;(-1!==e.indexOf("MSIE ")||-1!==e.indexOf("Trident/")||-1!==e.indexOf("Edge/"))&&(je=!0)}catch{}return je}Zone.__load_patch("ZoneAwarePromise",(e,n,i)=>{const o=Object.getOwnPropertyDescriptor,c=Object.defineProperty,y=i.symbol,d=[],b=!0===e[y("DISABLE_WRAPPING_UNCAUGHT_PROMISE_REJECTION")],v=y("Promise"),p=y("then"),L="__creationTrace__";i.onUnhandledError=l=>{if(i.showUncaughtError()){const u=l&&l.rejection;u?console.error("Unhandled Promise rejection:",u instanceof Error?u.message:u,"; Zone:",l.zone.name,"; Task:",l.task&&l.task.source,"; Value:",u,u instanceof Error?u.stack:void 0):console.error(l)}},i.microtaskDrainDone=()=>{for(;d.length;){const l=d.shift();try{l.zone.runGuarded(()=>{throw l.throwOriginal?l.rejection:l})}catch(u){N(u)}}};const Z=y("unhandledPromiseRejectionHandler");function N(l){i.onUnhandledError(l);try{const u=n[Z];"function"==typeof u&&u.call(this,l)}catch{}}function B(l){return l&&l.then}function H(l){return l}function J(l){return t.reject(l)}const q=y("state"),R=y("value"),_=y("finally"),K=y("parentPromiseValue"),x=y("parentPromiseState"),X="Promise.then",A=null,E=!0,G=!1,h=0;function I(l,u){return s=>{try{z(l,u,s)}catch(f){z(l,!1,f)}}}const P=function(){let l=!1;return function(s){return function(){l||(l=!0,s.apply(null,arguments))}}},Q="Promise resolved with itself",oe=y("currentTaskTrace");function z(l,u,s){const f=P();if(l===s)throw new TypeError(Q);if(l[q]===A){let g=null;try{("object"==typeof s||"function"==typeof s)&&(g=s&&s.then)}catch(w){return f(()=>{z(l,!1,w)})(),l}if(u!==G&&s instanceof t&&s.hasOwnProperty(q)&&s.hasOwnProperty(R)&&s[q]!==A)re(s),z(l,s[q],s[R]);else if(u!==G&&"function"==typeof g)try{g.call(s,f(I(l,u)),f(I(l,!1)))}catch(w){f(()=>{z(l,!1,w)})()}else{l[q]=u;const w=l[R];if(l[R]=s,l[_]===_&&u===E&&(l[q]=l[x],l[R]=l[K]),u===G&&s instanceof Error){const m=n.currentTask&&n.currentTask.data&&n.currentTask.data[L];m&&c(s,oe,{configurable:!0,enumerable:!1,writable:!0,value:m})}for(let m=0;m{try{const D=l[R],S=!!s&&_===s[_];S&&(s[K]=D,s[x]=w);const O=u.run(m,void 0,S&&m!==J&&m!==H?[]:[D]);z(s,!0,O)}catch(D){z(s,!1,D)}},s)}const M=function(){},T=e.AggregateError;class t{static toString(){return"function ZoneAwarePromise() { [native code] }"}static resolve(u){return z(new this(null),E,u)}static reject(u){return z(new this(null),G,u)}static any(u){if(!u||"function"!=typeof u[Symbol.iterator])return Promise.reject(new T([],"All promises were rejected"));const s=[];let f=0;try{for(let m of u)f++,s.push(t.resolve(m))}catch{return Promise.reject(new T([],"All promises were rejected"))}if(0===f)return Promise.reject(new T([],"All promises were rejected"));let g=!1;const w=[];return new t((m,D)=>{for(let S=0;S{g||(g=!0,m(O))},O=>{w.push(O),f--,0===f&&(g=!0,D(new T(w,"All promises were rejected")))})})}static race(u){let s,f,g=new this((D,S)=>{s=D,f=S});function w(D){s(D)}function m(D){f(D)}for(let D of u)B(D)||(D=this.resolve(D)),D.then(w,m);return g}static all(u){return t.allWithCallback(u)}static allSettled(u){return(this&&this.prototype instanceof t?this:t).allWithCallback(u,{thenCallback:f=>({status:"fulfilled",value:f}),errorCallback:f=>({status:"rejected",reason:f})})}static allWithCallback(u,s){let f,g,w=new this((O,V)=>{f=O,g=V}),m=2,D=0;const S=[];for(let O of u){B(O)||(O=this.resolve(O));const V=D;try{O.then(F=>{S[V]=s?s.thenCallback(F):F,m--,0===m&&f(S)},F=>{s?(S[V]=s.errorCallback(F),m--,0===m&&f(S)):g(F)})}catch(F){g(F)}m++,D++}return m-=2,0===m&&f(S),w}constructor(u){const s=this;if(!(s instanceof t))throw new Error("Must be an instanceof Promise.");s[q]=A,s[R]=[];try{const f=P();u&&u(f(I(s,E)),f(I(s,G)))}catch(f){z(s,!1,f)}}get[Symbol.toStringTag](){return"Promise"}get[Symbol.species](){return t}then(u,s){let f=this.constructor?.[Symbol.species];(!f||"function"!=typeof f)&&(f=this.constructor||t);const g=new f(M),w=n.current;return this[q]==A?this[R].push(w,g,u,s):ee(this,w,g,u,s),g}catch(u){return this.then(null,u)}finally(u){let s=this.constructor?.[Symbol.species];(!s||"function"!=typeof s)&&(s=t);const f=new s(M);f[_]=_;const g=n.current;return this[q]==A?this[R].push(g,f,u,u):ee(this,g,f,u,u),f}}t.resolve=t.resolve,t.reject=t.reject,t.race=t.race,t.all=t.all;const r=e[v]=e.Promise;e.Promise=t;const k=y("thenPatched");function C(l){const u=l.prototype,s=o(u,"then");if(s&&(!1===s.writable||!s.configurable))return;const f=u.then;u[p]=f,l.prototype.then=function(g,w){return new t((D,S)=>{f.call(this,D,S)}).then(g,w)},l[k]=!0}return i.patchThen=C,r&&(C(r),le(e,"fetch",l=>function $(l){return function(u,s){let f=l.apply(u,s);if(f instanceof t)return f;let g=f.constructor;return g[k]||C(g),f}}(l))),Promise[n.__symbol__("uncaughtPromiseErrors")]=d,t}),Zone.__load_patch("toString",e=>{const n=Function.prototype.toString,i=j("OriginalDelegate"),o=j("Promise"),c=j("Error"),a=function(){if("function"==typeof this){const v=this[i];if(v)return"function"==typeof v?n.call(v):Object.prototype.toString.call(v);if(this===Promise){const p=e[o];if(p)return n.call(p)}if(this===Error){const p=e[c];if(p)return n.call(p)}}return n.call(this)};a[i]=n,Function.prototype.toString=a;const y=Object.prototype.toString;Object.prototype.toString=function(){return"function"==typeof Promise&&this instanceof Promise?"[object Promise]":y.call(this)}});let ye=!1;if(typeof window<"u")try{const e=Object.defineProperty({},"passive",{get:function(){ye=!0}});window.addEventListener("test",e,e),window.removeEventListener("test",e,e)}catch{ye=!1}const ht={useG:!0},te={},Ye={},$e=new RegExp("^"+ke+"(\\w+)(true|false)$"),Ke=j("propagationStopped");function Je(e,n){const i=(n?n(e):e)+ae,o=(n?n(e):e)+ce,c=ke+i,a=ke+o;te[e]={},te[e][ae]=c,te[e][ce]=a}function dt(e,n,i,o){const c=o&&o.add||Se,a=o&&o.rm||Oe,y=o&&o.listeners||"eventListeners",d=o&&o.rmAll||"removeAllListeners",b=j(c),v="."+c+":",p="prependListener",L="."+p+":",Z=function(R,_,K){if(R.isRemoved)return;const x=R.callback;let X;"object"==typeof x&&x.handleEvent&&(R.callback=E=>x.handleEvent(E),R.originalDelegate=x);try{R.invoke(R,_,[K])}catch(E){X=E}const A=R.options;return A&&"object"==typeof A&&A.once&&_[a].call(_,K.type,R.originalDelegate?R.originalDelegate:R.callback,A),X};function N(R,_,K){if(!(_=_||e.event))return;const x=R||_.target||e,X=x[te[_.type][K?ce:ae]];if(X){const A=[];if(1===X.length){const E=Z(X[0],x,_);E&&A.push(E)}else{const E=X.slice();for(let G=0;G{throw G})}}}const B=function(R){return N(this,R,!1)},H=function(R){return N(this,R,!0)};function J(R,_){if(!R)return!1;let K=!0;_&&void 0!==_.useG&&(K=_.useG);const x=_&&_.vh;let X=!0;_&&void 0!==_.chkDup&&(X=_.chkDup);let A=!1;_&&void 0!==_.rt&&(A=_.rt);let E=R;for(;E&&!E.hasOwnProperty(c);)E=de(E);if(!E&&R[c]&&(E=R),!E||E[b])return!1;const G=_&&_.eventNameToString,h={},I=E[b]=E[c],P=E[j(a)]=E[a],Q=E[j(y)]=E[y],oe=E[j(d)]=E[d];let z;_&&_.prepend&&(z=E[j(_.prepend)]=E[_.prepend]);const t=K?function(s){if(!h.isExisting)return I.call(h.target,h.eventName,h.capture?H:B,h.options)}:function(s){return I.call(h.target,h.eventName,s.invoke,h.options)},r=K?function(s){if(!s.isRemoved){const f=te[s.eventName];let g;f&&(g=f[s.capture?ce:ae]);const w=g&&s.target[g];if(w)for(let m=0;mfunction(c,a){c[Ke]=!0,o&&o.apply(c,a)})}function Et(e,n,i,o,c){const a=Zone.__symbol__(o);if(n[a])return;const y=n[a]=n[o];n[o]=function(d,b,v){return b&&b.prototype&&c.forEach(function(p){const L=`${i}.${o}::`+p,Z=b.prototype;try{if(Z.hasOwnProperty(p)){const N=e.ObjectGetOwnPropertyDescriptor(Z,p);N&&N.value?(N.value=e.wrapWithCurrentZone(N.value,L),e._redefineProperty(b.prototype,p,N)):Z[p]&&(Z[p]=e.wrapWithCurrentZone(Z[p],L))}else Z[p]&&(Z[p]=e.wrapWithCurrentZone(Z[p],L))}catch{}}),y.call(n,d,b,v)},e.attachOriginToPatched(n[o],y)}function et(e,n,i){if(!i||0===i.length)return n;const o=i.filter(a=>a.target===e);if(!o||0===o.length)return n;const c=o[0].ignoreProperties;return n.filter(a=>-1===c.indexOf(a))}function tt(e,n,i,o){e&&Xe(e,et(e,n,i),o)}function He(e){return Object.getOwnPropertyNames(e).filter(n=>n.startsWith("on")&&n.length>2).map(n=>n.substring(2))}Zone.__load_patch("util",(e,n,i)=>{const o=He(e);i.patchOnProperties=Xe,i.patchMethod=le,i.bindArguments=Le,i.patchMacroTask=lt;const c=n.__symbol__("BLACK_LISTED_EVENTS"),a=n.__symbol__("UNPATCHED_EVENTS");e[a]&&(e[c]=e[a]),e[c]&&(n[c]=n[a]=e[c]),i.patchEventPrototype=_t,i.patchEventTarget=dt,i.isIEOrEdge=ft,i.ObjectDefineProperty=Ee,i.ObjectGetOwnPropertyDescriptor=ie,i.ObjectCreate=ge,i.ArraySlice=Ve,i.patchClass=ve,i.wrapWithCurrentZone=Ie,i.filterProperties=et,i.attachOriginToPatched=ue,i._redefineProperty=Object.defineProperty,i.patchCallbacks=Et,i.getGlobalObjects=()=>({globalSources:Ye,zoneSymbolEventNames:te,eventNames:o,isBrowser:Ae,isMix:Ue,isNode:we,TRUE_STR:ce,FALSE_STR:ae,ZONE_SYMBOL_PREFIX:ke,ADD_EVENT_LISTENER_STR:Se,REMOVE_EVENT_LISTENER_STR:Oe})});const Ce=j("zoneTask");function pe(e,n,i,o){let c=null,a=null;i+=o;const y={};function d(v){const p=v.data;return p.args[0]=function(){return v.invoke.apply(this,arguments)},p.handleId=c.apply(e,p.args),v}function b(v){return a.call(e,v.data.handleId)}c=le(e,n+=o,v=>function(p,L){if("function"==typeof L[0]){const Z={isPeriodic:"Interval"===o,delay:"Timeout"===o||"Interval"===o?L[1]||0:void 0,args:L},N=L[0];L[0]=function(){try{return N.apply(this,arguments)}finally{Z.isPeriodic||("number"==typeof Z.handleId?delete y[Z.handleId]:Z.handleId&&(Z.handleId[Ce]=null))}};const B=Me(n,L[0],Z,d,b);if(!B)return B;const H=B.data.handleId;return"number"==typeof H?y[H]=B:H&&(H[Ce]=B),H&&H.ref&&H.unref&&"function"==typeof H.ref&&"function"==typeof H.unref&&(B.ref=H.ref.bind(H),B.unref=H.unref.bind(H)),"number"==typeof H||H?H:B}return v.apply(e,L)}),a=le(e,i,v=>function(p,L){const Z=L[0];let N;"number"==typeof Z?N=y[Z]:(N=Z&&Z[Ce],N||(N=Z)),N&&"string"==typeof N.type?"notScheduled"!==N.state&&(N.cancelFn&&N.data.isPeriodic||0===N.runCount)&&("number"==typeof Z?delete y[Z]:Z&&(Z[Ce]=null),N.zone.cancelTask(N)):v.apply(e,L)})}Zone.__load_patch("legacy",e=>{const n=e[Zone.__symbol__("legacyPatch")];n&&n()}),Zone.__load_patch("timers",e=>{const n="set",i="clear";pe(e,n,i,"Timeout"),pe(e,n,i,"Interval"),pe(e,n,i,"Immediate")}),Zone.__load_patch("requestAnimationFrame",e=>{pe(e,"request","cancel","AnimationFrame"),pe(e,"mozRequest","mozCancel","AnimationFrame"),pe(e,"webkitRequest","webkitCancel","AnimationFrame")}),Zone.__load_patch("blocking",(e,n)=>{const i=["alert","prompt","confirm"];for(let o=0;ofunction(b,v){return n.current.run(a,e,v,d)})}),Zone.__load_patch("EventTarget",(e,n,i)=>{(function gt(e,n){n.patchEventPrototype(e,n)})(e,i),function mt(e,n){if(Zone[n.symbol("patchEventTarget")])return;const{eventNames:i,zoneSymbolEventNames:o,TRUE_STR:c,FALSE_STR:a,ZONE_SYMBOL_PREFIX:y}=n.getGlobalObjects();for(let b=0;b{ve("MutationObserver"),ve("WebKitMutationObserver")}),Zone.__load_patch("IntersectionObserver",(e,n,i)=>{ve("IntersectionObserver")}),Zone.__load_patch("FileReader",(e,n,i)=>{ve("FileReader")}),Zone.__load_patch("on_property",(e,n,i)=>{!function Tt(e,n){if(we&&!Ue||Zone[e.symbol("patchEvents")])return;const i=n.__Zone_ignore_on_properties;let o=[];if(Ae){const c=window;o=o.concat(["Document","SVGElement","Element","HTMLElement","HTMLBodyElement","HTMLMediaElement","HTMLFrameSetElement","HTMLFrameElement","HTMLIFrameElement","HTMLMarqueeElement","Worker"]);const a=function ut(){try{const e=Te.navigator.userAgent;if(-1!==e.indexOf("MSIE ")||-1!==e.indexOf("Trident/"))return!0}catch{}return!1}()?[{target:c,ignoreProperties:["error"]}]:[];tt(c,He(c),i&&i.concat(a),de(c))}o=o.concat(["XMLHttpRequest","XMLHttpRequestEventTarget","IDBIndex","IDBRequest","IDBOpenDBRequest","IDBDatabase","IDBTransaction","IDBCursor","WebSocket"]);for(let c=0;c{!function pt(e,n){const{isBrowser:i,isMix:o}=n.getGlobalObjects();(i||o)&&e.customElements&&"customElements"in e&&n.patchCallbacks(n,e.customElements,"customElements","define",["connectedCallback","disconnectedCallback","adoptedCallback","attributeChangedCallback"])}(e,i)}),Zone.__load_patch("XHR",(e,n)=>{!function b(v){const p=v.XMLHttpRequest;if(!p)return;const L=p.prototype;let N=L[Ze],B=L[Ne];if(!N){const h=v.XMLHttpRequestEventTarget;if(h){const I=h.prototype;N=I[Ze],B=I[Ne]}}const H="readystatechange",J="scheduled";function q(h){const I=h.data,P=I.target;P[a]=!1,P[d]=!1;const Q=P[c];N||(N=P[Ze],B=P[Ne]),Q&&B.call(P,H,Q);const oe=P[c]=()=>{if(P.readyState===P.DONE)if(!I.aborted&&P[a]&&h.state===J){const U=P[n.__symbol__("loadfalse")];if(0!==P.status&&U&&U.length>0){const re=h.invoke;h.invoke=function(){const ee=P[n.__symbol__("loadfalse")];for(let W=0;Wfunction(h,I){return h[o]=0==I[2],h[y]=I[1],K.apply(h,I)}),X=j("fetchTaskAborting"),A=j("fetchTaskScheduling"),E=le(L,"send",()=>function(h,I){if(!0===n.current[A]||h[o])return E.apply(h,I);{const P={target:h,url:h[y],isPeriodic:!1,args:I,aborted:!1},Q=Me("XMLHttpRequest.send",R,P,q,_);h&&!0===h[d]&&!P.aborted&&Q.state===J&&Q.invoke()}}),G=le(L,"abort",()=>function(h,I){const P=function Z(h){return h[i]}(h);if(P&&"string"==typeof P.type){if(null==P.cancelFn||P.data&&P.data.aborted)return;P.zone.cancelTask(P)}else if(!0===n.current[X])return G.apply(h,I)})}(e);const i=j("xhrTask"),o=j("xhrSync"),c=j("xhrListener"),a=j("xhrScheduled"),y=j("xhrURL"),d=j("xhrErrorBeforeScheduled")}),Zone.__load_patch("geolocation",e=>{e.navigator&&e.navigator.geolocation&&function at(e,n){const i=e.constructor.name;for(let o=0;o{const b=function(){return d.apply(this,Le(arguments,i+"."+c))};return ue(b,d),b})(a)}}}(e.navigator.geolocation,["getCurrentPosition","watchPosition"])}),Zone.__load_patch("PromiseRejectionEvent",(e,n)=>{function i(o){return function(c){Qe(e,o).forEach(y=>{const d=e.PromiseRejectionEvent;if(d){const b=new d(o,{promise:c.promise,reason:c.rejection});y.invoke(b)}})}}e.PromiseRejectionEvent&&(n[j("unhandledPromiseRejectionHandler")]=i("unhandledrejection"),n[j("rejectionHandledHandler")]=i("rejectionhandled"))}),Zone.__load_patch("queueMicrotask",(e,n,i)=>{!function yt(e,n){n.patchMethod(e,"queueMicrotask",i=>function(o,c){Zone.current.scheduleMicroTask("queueMicrotask",c[0])})}(e,i)})}},ie=>{ie(ie.s=538)}]); --------------------------------------------------------------------------------