commit 907bee052741fa1b6c53c355c417dd9faf48d615 Author: Sahatsawat Kanpai Date: Wed Jan 15 17:58:02 2025 +0700 ✨ init project with ckeditor5-export template, with new ckeditor.svg content resized into 20x20 px diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..37ea8ff --- /dev/null +++ b/.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/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..aa41a27 --- /dev/null +++ b/.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/.gitattributes b/.gitattributes new file mode 100644 index 0000000..41be6fa --- /dev/null +++ b/.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/.gitignore b/.gitignore new file mode 100644 index 0000000..437dda1 --- /dev/null +++ b/.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/.stylelintrc b/.stylelintrc new file mode 100644 index 0000000..1d86a41 --- /dev/null +++ b/.stylelintrc @@ -0,0 +1,3 @@ +{ + "extends": "stylelint-config-ckeditor5" +} diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..de483eb --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,6 @@ +Software License Agreement +========================== + +Copyright (c) 2024. All rights reserved. + +Licensed under the terms of [MIT license](https://opensource.org/licenses/MIT). diff --git a/README.md b/README.md new file mode 100644 index 0000000..7e888ef --- /dev/null +++ b/README.md @@ -0,0 +1,141 @@ +@esi_package/ckeditor5-import +============================= + +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/sample/index.html b/sample/index.html new file mode 100644 index 0000000..ac31c8f --- /dev/null +++ b/sample/index.html @@ -0,0 +1,92 @@ + + + + + + + CKEditor 5 – Development Sample + + + + + +

CKEditor 5 – Development Sample

+ +
+

ในการทดลองวัดความยาวของวัตถุชิ้นหนึ่งที่มีความยาวประมาณ + 6 เซนติเมตร ด้วยไม้บรรทัดที่มีความละเอียด 0.1 เซนติเมตร โดยทำการวัดทั้งหมด 5 ครั้ง ได้ข้อมูลดังนี้

+

5.84 6.00 6.26 5.90 + 12.25

+

ถ้าจะต้องรายงานค่าเฉลี่ยของการวัดความยาวครั้งนี้    +   + และรายงานความคลายเคลื่อนของความยาวเฉลี่ย    +   + ด้วยสูตร

+

+    +  

+

เมื่อ    +   + และ    +   + คือ ค่าที่มากที่สุด + และค่าที่น้อยที่สุดของข้อมูล ตามลำดับ

+

ข้อใดแสดงผลการรายงานการวัดความยาวได้ถูกต้อง +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ตารางเรียนปีการศึกษา 2567 ภาคปลาย (Spring2024)
วันเวลา0900 - 12001300 - 16001630 - 1900
วันพฤหัสProb StatSeminarComSys Security
lathmive + + + + + +
+
+
+ + + + + diff --git a/scripts/build-dist.mjs b/scripts/build-dist.mjs new file mode 100644 index 0000000..498384f --- /dev/null +++ b/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: 'ckeditor5-import', + external: [ + 'ckeditor5', + 'ckeditor5-premium-features' + ] + } ); +} )(); diff --git a/src/augmentation.ts b/src/augmentation.ts new file mode 100644 index 0000000..b8e8650 --- /dev/null +++ b/src/augmentation.ts @@ -0,0 +1,7 @@ +import type { Import } from './index.js'; + +declare module '@ckeditor/ckeditor5-core' { + interface PluginsMap { + [ Import.pluginName ]: Import; + } +} diff --git a/src/import.ts b/src/import.ts new file mode 100644 index 0000000..f5a9ce6 --- /dev/null +++ b/src/import.ts @@ -0,0 +1,112 @@ +import { Plugin, ButtonView } from 'ckeditor5'; + +import ckeditor5Icon from '../theme/icons/ckeditor.svg'; + +import { asBlob } from 'html-docx-js-typescript'; +import { saveAs } from 'file-saver'; + +import Temml from 'temml'; + +export default class Import extends Plugin { + public static get pluginName() { + return 'Import' as const; + } + + public init(): void { + const editor = this.editor; + const t = editor.t; + const model = editor.model; + + // Add the "importButton" to feature components. + editor.ui.componentFactory.add( 'importButton', locale => { + const view = new ButtonView( locale ); + + view.set( { + label: t( 'Import' ), + 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(); + // } ); + + // Insert a text into the editor after clicking the button. + // this.listenTo( view, 'execute', async () => { + // asBlob(this.editor.getData()).then((data: any) => { + // saveAs(data, 'file.docx') // save as docx file + // }) // asBlob() return Promise + + // editor.editing.view.focus(); + // } ); + + // POST fetch docx and download + this.listenTo( view, 'execute', async () => { + const parser = new DOMParser(); + const doc = parser.parseFromString(this.editor.getData(), "text/html"); + + // pre-process mathlive script to html MathML tag with the help of temml + for (const mathliveElement of doc.querySelectorAll('script[type="math/tex"]')) { + const temmlWrapperElement = document.createElement('span'); + const temmlMathMLString = Temml.render(mathliveElement.textContent ?? "", temmlWrapperElement); + mathliveElement.replaceWith(temmlWrapperElement); + } + + // pre-process for table + for (const table of doc.querySelectorAll('table')) { + // pre-process table for border and centering and inner border + table.style.borderCollapse = 'collapse'; + table.style.borderSpacing = '0'; + table.style.border = '1px solid #b3b3b3'; + table.style.margin = 'auto'; + // pre-process table for padding + for (const td of table.querySelectorAll('td')) { + td.style.padding = '8px'; + } + // pre-process table for inner border + for (const tr of table.querySelectorAll('tr')) { + for (const td of tr.querySelectorAll('td')) { + td.style.border = '1px solid #b3b3b3'; + } + } + // pre-process table for header background color rgba(0,0,0,.05) to hex #f2f2f2 + // and it's own border + // and padding + const ths = table.querySelectorAll('th'); + for (const th of ths) { + th.style.backgroundColor = '#f2f2f2'; + th.style.border = '1px solid #b3b3b3'; + th.style.padding = '8px'; + } + } + + console.log(doc.body.innerHTML); + + fetch('http://localhost:8080/aspose/html-to-word', { + method: 'POST', + body: doc.body.innerHTML, + headers: { + 'Content-Type': 'text/plain' + } + }) + .then(response => response.blob()) + .then(blob => { + saveAs(blob, 'stou.docx') // save as docx file + }) + .catch(error => { + console.error('Error:', error); + }); + editor.editing.view.focus(); + } ); + + return view; + } ); + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..0a5fe4d --- /dev/null +++ b/src/index.ts @@ -0,0 +1,8 @@ +import ckeditor from './../theme/icons/ckeditor.svg'; +import './augmentation.js'; + +export { default as Import } from './import.js'; + +export const icons = { + ckeditor +}; diff --git a/tests/import.ts b/tests/import.ts new file mode 100644 index 0000000..b600563 --- /dev/null +++ b/tests/import.ts @@ -0,0 +1,55 @@ +import { describe, expect, it, beforeEach, afterEach } from 'vitest'; +import { ClassicEditor, Essentials, Paragraph, Heading } from 'ckeditor5'; +import Import from '../src/import.js'; + +describe( 'Import', () => { + it( 'should be named', () => { + expect( Import.pluginName ).to.equal( 'Import' ); + } ); + + describe( 'init()', () => { + let domElement: HTMLElement, editor: ClassicEditor; + + beforeEach( async () => { + domElement = document.createElement( 'div' ); + document.body.appendChild( domElement ); + + editor = await ClassicEditor.create( domElement, { + plugins: [ + Paragraph, + Heading, + Essentials, + Import + ], + toolbar: [ + 'importButton' + ] + } ); + } ); + + afterEach( () => { + domElement.remove(); + return editor.destroy(); + } ); + + it( 'should load Import', () => { + const myPlugin = editor.plugins.get( 'Import' ); + + expect( myPlugin ).to.be.an.instanceof( Import ); + } ); + + it( 'should add an icon to the toolbar', () => { + expect( editor.ui.componentFactory.has( 'importButton' ) ).to.equal( true ); + } ); + + it( 'should add a text into the editor after clicking the icon', () => { + const icon = editor.ui.componentFactory.create( 'importButton' ); + + expect( editor.getData() ).to.equal( '' ); + + icon.fire( 'execute' ); + + expect( editor.getData() ).to.equal( '

Hello CKEditor 5!

' ); + } ); + } ); +} ); diff --git a/tests/index.ts b/tests/index.ts new file mode 100644 index 0000000..b25c644 --- /dev/null +++ b/tests/index.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from 'vitest'; +import { Import as ImportDll, icons } from '../src/index.js'; +import Import from '../src/import.js'; + +import ckeditor from './../theme/icons/ckeditor.svg'; + +describe( 'CKEditor5 Import DLL', () => { + it( 'exports Import', () => { + expect( ImportDll ).to.equal( Import ); + } ); + + describe( 'icons', () => { + it( 'exports the "ckeditor" icon', () => { + expect( icons.ckeditor ).to.equal( ckeditor ); + } ); + } ); +} ); diff --git a/theme/icons/ckeditor.svg b/theme/icons/ckeditor.svg new file mode 100644 index 0000000..c0514eb --- /dev/null +++ b/theme/icons/ckeditor.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tsconfig.dist.json b/tsconfig.dist.json new file mode 100644 index 0000000..d174edb --- /dev/null +++ b/tsconfig.dist.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "bundler", + "rootDir": "./src", + "types": [ + "./typings/types" + ] + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..069e3cb --- /dev/null +++ b/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/tsconfig.release.json b/tsconfig.release.json new file mode 100644 index 0000000..b0b26a2 --- /dev/null +++ b/tsconfig.release.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "sourceMap": false, + "declaration": true + }, + "exclude": [ + "./tests/", + "./src", + "./sample/" + ] +} diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 0000000..065d98e --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "types": [ + "@types/mocha" + ], + "sourceMap": true + }, + "include": [ + "./sample", + "./src", + "./tests", + "./typings" + ] +} diff --git a/typings/ckeditor5-inspector.d.ts b/typings/ckeditor5-inspector.d.ts new file mode 100644 index 0000000..d50ee49 --- /dev/null +++ b/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/typings/types.d.ts b/typings/types.d.ts new file mode 100644 index 0000000..4333ece --- /dev/null +++ b/typings/types.d.ts @@ -0,0 +1,4 @@ +declare module '*.svg' { + const content: string; + export default content; +} diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..2758520 --- /dev/null +++ b/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' + ] + } + } +} ); diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..3d4c232 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,27 @@ +const path = require('path'); + +module.exports = { + entry: './src/index.ts', // Entry point of your app + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist'), + }, + module: { + rules: [ + { + test: /\.css$/, // Process CSS files + use: ['style-loader', 'css-loader'], + }, + { + test: /\.ts$/, // Process TypeScript files + use: 'ts-loader', + exclude: /node_modules/, + }, + ], + }, + resolve: { + extensions: ['.ts', '.js'], // Resolve these extensions + }, + devtool: 'source-map', // Enable source maps for easier debugging + mode: 'development', // Set to 'production' for production builds +};