diff --git a/packages/ckeditor5-admonition/.editorconfig b/packages/ckeditor5-admonition/.editorconfig new file mode 100644 index 000000000..37ea8ff91 --- /dev/null +++ b/packages/ckeditor5-admonition/.editorconfig @@ -0,0 +1,19 @@ +# Configurations to normalize the IDE behavior. +# http://editorconfig.org/ + +root = true + +[*] +indent_style = tab +tab_width = 4 +charset = utf-8 +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{js,jsx,ts}] +quote_type = single + +[package.json] +indent_style = space +tab_width = 2 diff --git a/packages/ckeditor5-admonition/.eslintrc.cjs b/packages/ckeditor5-admonition/.eslintrc.cjs new file mode 100644 index 000000000..aa41a27ad --- /dev/null +++ b/packages/ckeditor5-admonition/.eslintrc.cjs @@ -0,0 +1,46 @@ +/* eslint-env node */ + +'use strict'; + +module.exports = { + extends: 'ckeditor5', + parser: '@typescript-eslint/parser', + plugins: [ + '@typescript-eslint' + ], + root: true, + ignorePatterns: [ + // Ignore the entire `dist/` (the NIM build). + 'dist/**', + // Ignore compiled JavaScript files, as they are generated automatically. + 'src/**/*.js', + // Also, do not check typing declarations, too. + 'src/**/*.d.ts' + ], + rules: { + // This rule disallows importing from any path other than the package main entrypoint. + 'ckeditor5-rules/allow-imports-only-from-main-package-entry-point': 'error', + // This rule ensures that all imports from `@ckeditor/*` packages are done through the main package entry points. + // This is required for the editor types to work properly and to ease migration to the installation methods + // introduced in CKEditor 5 version 42.0.0. + 'ckeditor5-rules/no-legacy-imports': 'error', + // As required by the ECMAScript (ESM) standard, all imports must include a file extension. + // If the import does not include it, this rule will try to automatically detect the correct file extension. + 'ckeditor5-rules/require-file-extensions-in-imports': [ + 'error', + { + extensions: [ '.ts', '.js', '.json' ] + } + ] + }, + overrides: [ + { + files: [ 'tests/**/*.[jt]s', 'sample/**/*.[jt]s' ], + rules: { + // To write complex tests, you may need to import files that are not exported in DLL files by default. + // Hence, imports CKEditor 5 packages in test files are not checked. + 'ckeditor5-rules/ckeditor-imports': 'off' + } + } + ] +}; diff --git a/packages/ckeditor5-admonition/.gitattributes b/packages/ckeditor5-admonition/.gitattributes new file mode 100644 index 000000000..41be6fafe --- /dev/null +++ b/packages/ckeditor5-admonition/.gitattributes @@ -0,0 +1,19 @@ +* text=auto + +*.htaccess eol=lf +*.cgi eol=lf +*.sh eol=lf + +*.css text +*.htm text +*.html text +*.js text +*.ts text +*.json text +*.php text +*.txt text +*.md text + +*.png -text +*.gif -text +*.jpg -text diff --git a/packages/ckeditor5-admonition/.gitignore b/packages/ckeditor5-admonition/.gitignore new file mode 100644 index 000000000..437dda1d0 --- /dev/null +++ b/packages/ckeditor5-admonition/.gitignore @@ -0,0 +1,10 @@ +build/ +coverage/ +dist/ +node_modules/ +tmp/ +sample/ckeditor.dist.js + +# Ignore compiled TypeScript files. +src/**/*.js +src/**/*.d.ts diff --git a/packages/ckeditor5-admonition/.stylelintrc b/packages/ckeditor5-admonition/.stylelintrc new file mode 100644 index 000000000..1d86a41f9 --- /dev/null +++ b/packages/ckeditor5-admonition/.stylelintrc @@ -0,0 +1,3 @@ +{ + "extends": "stylelint-config-ckeditor5" +} diff --git a/packages/ckeditor5-admonition/LICENSE.md b/packages/ckeditor5-admonition/LICENSE.md new file mode 100644 index 000000000..b60c76711 --- /dev/null +++ b/packages/ckeditor5-admonition/LICENSE.md @@ -0,0 +1,6 @@ +Software License Agreement +========================== + +Copyright (c) 2025. All rights reserved. + +Licensed under the terms of [MIT license](https://opensource.org/licenses/MIT). diff --git a/packages/ckeditor5-admonition/README.md b/packages/ckeditor5-admonition/README.md new file mode 100644 index 000000000..f38e132f9 --- /dev/null +++ b/packages/ckeditor5-admonition/README.md @@ -0,0 +1,141 @@ +@triliumnext/ckeditor5-admonition +================================= + +This package was created by the [ckeditor5-package-generator](https://www.npmjs.com/package/ckeditor5-package-generator) package. + +## Table of contents + +* [Developing the package](#developing-the-package) +* [Available scripts](#available-scripts) + * [`start`](#start) + * [`test`](#test) + * [`lint`](#lint) + * [`stylelint`](#stylelint) + * [`build:dist`](#builddist) + * [`translations:synchronize`](#translationssynchronize) + * [`translations:validate`](#translationsvalidate) + * [`ts:build` and `ts:clear`](#tsbuild-and-tsclear) +* [License](#license) + +## Developing the package + +To read about the CKEditor 5 Framework, visit the [CKEditor 5 Framework documentation](https://ckeditor.com/docs/ckeditor5/latest/framework/index.html). + +## Available scripts + +NPM scripts are a convenient way to provide commands in a project. They are defined in the `package.json` file and shared with people contributing to the project. It ensures developers use the same command with the same options (flags). + +All the scripts can be executed by running `npm run + + + + + + + + + + + + + + + + + + + + diff --git a/packages/ckeditor5-admonition/sample/index.html b/packages/ckeditor5-admonition/sample/index.html new file mode 100644 index 000000000..090ab66ac --- /dev/null +++ b/packages/ckeditor5-admonition/sample/index.html @@ -0,0 +1,123 @@ + + + + + + + CKEditor 5 – Development Sample + + + + + +

CKEditor 5 – Development Sample

+ +
+

Development environment

+

+ This is a demo of the classic + editor + build that loads your plugin (Admonition) generated by the + tool. You can modify this + sample and use it to validate whether a plugin or a set of plugins work fine. +

+

+ Admonition inserts text into the editor. You can click the + CKEditor 5 icon in the toolbar and see the results. +

+ +

Helpful resources

+ + +

The directory structure

+ +

+ The code snippet below presents the directory structure. +

+ +
.
+├─ lang
+│  └─ contexts.json    # Entries used for creating translations.
+├─ sample
+│  ├─ dll.html         # The editor initialized using the DLL builds. Check README for details.
+│  ├─ index.html       # The currently displayed file.
+│  └─ ckeditor.ts      # The editor initialization script.
+├─ src
+│  ├─ admonition.ts
+│  ├─ augmentation.ts  # Type augmentations for the `@ckeditor/ckeditor5-core` module. Read more in PluginsMap and CommandsMap.
+│  ├─ index.ts         # The modules exported by the package when using the DLL builds.
+│  └─ **/*.ts          # All TypeScript source files should be saved here.
+├─ tests
+│  ├─ admonition.ts
+│  ├─ index.ts         # Tests for the plugin.
+│  └─ **/*.ts          # All tests should be saved here.
+├─ theme
+│  ├─ icons
+│  │  ├─ ckeditor.svg  # The CKEditor 5 icon displayed in the toolbar.
+│  │  └─ **/*.svg      # All icon files should be saved here.
+│  └─ **/*.css         # All CSS files should be saved here.
+├─ typings
+│  └─ **/*.d.ts        # Files containing type definitions.
+├─ .editorconfig
+├─ ...
+├─ README.md
+└─ tsconfig.json       # TypeScript configuration file.
+ +

Reporting issues

+

If you found a problem with CKEditor 5 or the package generator, please, report an issue:

+ +
+ + + + + diff --git a/packages/ckeditor5-admonition/scripts/build-dist.mjs b/packages/ckeditor5-admonition/scripts/build-dist.mjs new file mode 100644 index 000000000..992a19a95 --- /dev/null +++ b/packages/ckeditor5-admonition/scripts/build-dist.mjs @@ -0,0 +1,65 @@ +#!/usr/bin/env node + +/** + * @license Copyright (c) 2020-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +/* eslint-env node */ + +import { createRequire } from 'module'; +import upath from 'upath'; +import chalk from 'chalk'; +import { build } from '@ckeditor/ckeditor5-dev-build-tools'; + +function dist( path ) { + return upath.join( 'dist', path ); +} + +( async () => { + const tsconfig = 'tsconfig.dist.ckeditor5.json'; + + /** + * Step 1 + */ + console.log( chalk.cyan( '1/2: Generating NPM build...' ) ); + + const require = createRequire( import.meta.url ); + const pkg = require( upath.resolve( process.cwd(), './package.json' ) ); + + await build( { + input: 'src/index.ts', + output: dist( './index.js' ), + tsconfig: 'tsconfig.dist.json', + external: [ + 'ckeditor5', + 'ckeditor5-premium-features', + ...Object.keys( { + ...pkg.dependencies, + ...pkg.peerDependencies + } ) + ], + clean: true, + sourceMap: true, + declarations: true, + translations: '**/*.po' + } ); + + /** + * Step 2 + */ + console.log( chalk.cyan( '2/2: Generating browser build...' ) ); + + await build( { + output: dist( 'browser/index.js' ), + tsconfig, + sourceMap: true, + minify: true, + browser: true, + name: 'CKAdmonition', + external: [ + 'ckeditor5', + 'ckeditor5-premium-features' + ] + } ); +} )(); diff --git a/packages/ckeditor5-admonition/src/admonition.ts b/packages/ckeditor5-admonition/src/admonition.ts new file mode 100644 index 000000000..336f106d2 --- /dev/null +++ b/packages/ckeditor5-admonition/src/admonition.ts @@ -0,0 +1,39 @@ +import { Plugin, ButtonView } from 'ckeditor5'; + +import ckeditor5Icon from '../theme/icons/ckeditor.svg'; + +export default class Admonition extends Plugin { + public static get pluginName() { + return 'Admonition' as const; + } + + public init(): void { + const editor = this.editor; + const t = editor.t; + const model = editor.model; + + // Register the "admonition" button, so it can be displayed in the toolbar. + editor.ui.componentFactory.add( 'admonition', locale => { + const view = new ButtonView( locale ); + + view.set( { + label: t( 'Admonition' ), + icon: ckeditor5Icon, + tooltip: true + } ); + + // Insert a text into the editor after clicking the button. + this.listenTo( view, 'execute', () => { + model.change( writer => { + const textNode = writer.createText( 'Hello CKEditor 5!' ); + + model.insertContent( textNode ); + } ); + + editor.editing.view.focus(); + } ); + + return view; + } ); + } +} diff --git a/packages/ckeditor5-admonition/src/augmentation.ts b/packages/ckeditor5-admonition/src/augmentation.ts new file mode 100644 index 000000000..40203aa8a --- /dev/null +++ b/packages/ckeditor5-admonition/src/augmentation.ts @@ -0,0 +1,7 @@ +import type { Admonition } from './index.js'; + +declare module '@ckeditor/ckeditor5-core' { + interface PluginsMap { + [ Admonition.pluginName ]: Admonition; + } +} diff --git a/packages/ckeditor5-admonition/src/index.ts b/packages/ckeditor5-admonition/src/index.ts new file mode 100644 index 000000000..939fa8314 --- /dev/null +++ b/packages/ckeditor5-admonition/src/index.ts @@ -0,0 +1,8 @@ +import ckeditor from './../theme/icons/ckeditor.svg'; +import './augmentation.js'; + +export { default as Admonition } from './admonition.js'; + +export const icons = { + ckeditor +}; diff --git a/packages/ckeditor5-admonition/tests/admonition.ts b/packages/ckeditor5-admonition/tests/admonition.ts new file mode 100644 index 000000000..a7357ed12 --- /dev/null +++ b/packages/ckeditor5-admonition/tests/admonition.ts @@ -0,0 +1,56 @@ +import { describe, expect, it, beforeEach, afterEach } from 'vitest'; +import { ClassicEditor, Essentials, Paragraph, Heading } from 'ckeditor5'; +import Admonition from '../src/admonition.js'; + +describe( 'Admonition', () => { + it( 'should be named', () => { + expect( Admonition.pluginName ).to.equal( 'Admonition' ); + } ); + + describe( 'init()', () => { + let domElement: HTMLElement, editor: ClassicEditor; + + beforeEach( async () => { + domElement = document.createElement( 'div' ); + document.body.appendChild( domElement ); + + editor = await ClassicEditor.create( domElement, { + licenseKey: 'GPL', + plugins: [ + Paragraph, + Heading, + Essentials, + Admonition + ], + toolbar: [ + 'admonition' + ] + } ); + } ); + + afterEach( () => { + domElement.remove(); + return editor.destroy(); + } ); + + it( 'should load Admonition', () => { + const myPlugin = editor.plugins.get( 'Admonition' ); + + expect( myPlugin ).to.be.an.instanceof( Admonition ); + } ); + + it( 'should add an icon to the toolbar', () => { + expect( editor.ui.componentFactory.has( 'admonition' ) ).to.equal( true ); + } ); + + it( 'should add a text into the editor after clicking the icon', () => { + const icon = editor.ui.componentFactory.create( 'admonition' ); + + expect( editor.getData() ).to.equal( '' ); + + icon.fire( 'execute' ); + + expect( editor.getData() ).to.equal( '

Hello CKEditor 5!

' ); + } ); + } ); +} ); diff --git a/packages/ckeditor5-admonition/tests/index.ts b/packages/ckeditor5-admonition/tests/index.ts new file mode 100644 index 000000000..1c3ad627e --- /dev/null +++ b/packages/ckeditor5-admonition/tests/index.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from 'vitest'; +import { Admonition as AdmonitionDll, icons } from '../src/index.js'; +import Admonition from '../src/admonition.js'; + +import ckeditor from './../theme/icons/ckeditor.svg'; + +describe( 'CKEditor5 Admonition DLL', () => { + it( 'exports Admonition', () => { + expect( AdmonitionDll ).to.equal( Admonition ); + } ); + + describe( 'icons', () => { + it( 'exports the "ckeditor" icon', () => { + expect( icons.ckeditor ).to.equal( ckeditor ); + } ); + } ); +} ); diff --git a/packages/ckeditor5-admonition/theme/icons/ckeditor.svg b/packages/ckeditor5-admonition/theme/icons/ckeditor.svg new file mode 100644 index 000000000..25436f4b8 --- /dev/null +++ b/packages/ckeditor5-admonition/theme/icons/ckeditor.svg @@ -0,0 +1 @@ + diff --git a/packages/ckeditor5-admonition/tsconfig.dist.json b/packages/ckeditor5-admonition/tsconfig.dist.json new file mode 100644 index 000000000..d174edb34 --- /dev/null +++ b/packages/ckeditor5-admonition/tsconfig.dist.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "bundler", + "rootDir": "./src", + "types": [ + "./typings/types" + ] + } +} diff --git a/packages/ckeditor5-admonition/tsconfig.json b/packages/ckeditor5-admonition/tsconfig.json new file mode 100644 index 000000000..069e3cb16 --- /dev/null +++ b/packages/ckeditor5-admonition/tsconfig.json @@ -0,0 +1,38 @@ +{ + "compilerOptions": { + /** + * TypeScript automagically loads typings from all "@types/*" packages if the "compilerOptions.types" array is not defined in + * this file. However, if some dependencies have "@types/*" packages as their dependencies, they'll also be loaded as well. + * As a result, TypeScript loaded "@types/node" which we don't want to use, because it allows using Node.js specific APIs that + * are not available in the browsers. + * + * To avoid such issues, we defined this empty "types" to disable automatic inclusion of the "@types/*" packages. + */ + "types": [], + "lib": [ + "ES2019", // Must match the "target". + "ES2020.String", + "DOM", + "DOM.Iterable" + ], + "noImplicitAny": true, + "noImplicitOverride": true, + "strict": true, + "target": "es2019", + "sourceMap": true, + "allowJs": true, + "moduleDetection": "force", + "moduleResolution": "NodeNext", + "module": "NodeNext", + "skipLibCheck": true, + "typeRoots": [ + "typings", + "node_modules/@types" + ] + }, + "include": [ + "./sample", + "./src", + "./typings" + ] +} diff --git a/packages/ckeditor5-admonition/tsconfig.release.json b/packages/ckeditor5-admonition/tsconfig.release.json new file mode 100644 index 000000000..b0b26a24d --- /dev/null +++ b/packages/ckeditor5-admonition/tsconfig.release.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "sourceMap": false, + "declaration": true + }, + "exclude": [ + "./tests/", + "./src", + "./sample/" + ] +} diff --git a/packages/ckeditor5-admonition/tsconfig.test.json b/packages/ckeditor5-admonition/tsconfig.test.json new file mode 100644 index 000000000..065d98e49 --- /dev/null +++ b/packages/ckeditor5-admonition/tsconfig.test.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "types": [ + "@types/mocha" + ], + "sourceMap": true + }, + "include": [ + "./sample", + "./src", + "./tests", + "./typings" + ] +} diff --git a/packages/ckeditor5-admonition/typings/ckeditor5-inspector.d.ts b/packages/ckeditor5-admonition/typings/ckeditor5-inspector.d.ts new file mode 100644 index 000000000..d50ee49c4 --- /dev/null +++ b/packages/ckeditor5-admonition/typings/ckeditor5-inspector.d.ts @@ -0,0 +1,7 @@ +declare module '@ckeditor/ckeditor5-inspector' { + const inspector: { + attach( editor: any ): void; + }; + + export default inspector; +} diff --git a/packages/ckeditor5-admonition/typings/types.d.ts b/packages/ckeditor5-admonition/typings/types.d.ts new file mode 100644 index 000000000..4333ece78 --- /dev/null +++ b/packages/ckeditor5-admonition/typings/types.d.ts @@ -0,0 +1,4 @@ +declare module '*.svg' { + const content: string; + export default content; +} diff --git a/packages/ckeditor5-admonition/vitest.config.ts b/packages/ckeditor5-admonition/vitest.config.ts new file mode 100644 index 000000000..2758520eb --- /dev/null +++ b/packages/ckeditor5-admonition/vitest.config.ts @@ -0,0 +1,40 @@ +/** + * @license Copyright (c) 2023-2024, CKSource Holding sp. z o.o. All rights reserved. + * For licensing, see LICENSE.md. + */ + +import { defineConfig } from 'vitest/config'; +import svg from 'vite-plugin-svgo'; + +export default defineConfig( { + plugins: [ + svg() + ], + test: { + browser: { + enabled: true, + name: 'chrome', + provider: 'webdriverio', + providerOptions: {}, + headless: true, + ui: false + }, + include: [ + 'tests/**/*.[jt]s' + ], + globals: true, + watch: false, + coverage: { + thresholds: { + lines: 100, + functions: 100, + branches: 100, + statements: 100 + }, + provider: 'istanbul', + include: [ + 'src' + ] + } + } +} );