From 370bee259010bcd4799d557af1cecee10f2af2ce Mon Sep 17 00:00:00 2001 From: Fedik Date: Sun, 25 Jun 2023 16:57:27 +0300 Subject: [PATCH 01/53] Codemirror deps and build --- .../javascript/build-codemirror.es6.js | 90 ++++ build/build.js | 7 + package-lock.json | 464 +++++++++++++++++- package.json | 13 +- 4 files changed, 562 insertions(+), 12 deletions(-) create mode 100644 build/build-modules-js/javascript/build-codemirror.es6.js diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js new file mode 100644 index 0000000000000..7500574456b70 --- /dev/null +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -0,0 +1,90 @@ +/** + * Build codemirror modules + */ +/* eslint-disable import/no-extraneous-dependencies */ + +const { + existsSync, readFile, writeFile, mkdir, mkdirs, ensureDir, readdirSync, +} = require('fs-extra'); +const rollup = require('rollup'); +const { nodeResolve } = require('@rollup/plugin-node-resolve'); +const replace = require('@rollup/plugin-replace'); +const { minify } = require('terser'); +const {resolve} = require("path"); + +// Find a list of installed codemirror modules +const retrieveListOfModules = () => { + const cmModules = []; + + // Get @codemirror module roots + const roots = []; + module.paths.forEach((path) => { + const fullPath = `${path}/@codemirror`; + if (existsSync(fullPath)) { + roots.push(fullPath); + } + }); + + // List of modules + roots.forEach((rootPath) => { + readdirSync(rootPath).forEach((subModule) => { + cmModules.push(`@codemirror/${subModule}`); + }); + }); + + return cmModules; +}; + +// Build the module +const buildModule = async (module, externalModules, destFile) => { + const build = await rollup.rollup({ + input: module, + external: externalModules, + plugins: [ + nodeResolve(), + replace({ + preventAssignment: true, + 'process.env.NODE_ENV': '"production"', + }), + ], + }); + + build.write({ + format: 'es', + sourcemap: false, + file: destFile, + }); + build.close(); +}; + +// Minify a js file +const createMinified = (filePath) => { + const destFile = filePath.replace('.js', '.min.js'); + // Read source + readFile(filePath, { encoding: 'utf8' }).then((src) => { + // Minify + minify(src, { sourceMap: false, format: { comments: false } }).then((result) => { + // Save result + writeFile(destFile, result.code, { encoding: 'utf8', mode: 0o644 }); + }); + }); +}; + +module.exports.compileCodemirror = async () => { + // eslint-disable-next-line no-console + console.log('Building Codemirror Components...'); + + const cmModules = retrieveListOfModules(); + const destBasePath = 'media/vendor/codemirror/js'; + + cmModules.forEach((module) => { + const destFile = `${module.replace('@codemirror/', '')}.js`; + const destPath = `${destBasePath}/${destFile}`; + + buildModule(module, cmModules, destPath).then(() => { + createMinified(destPath); + }); + }); + + // console.log('compileCodemirror', cmModules, resultFiles); +}; diff --git a/build/build.js b/build/build.js index c258932384a3d..20f7af0cda523 100644 --- a/build/build.js +++ b/build/build.js @@ -34,6 +34,7 @@ const { mediaManager, watchMediaManager } = require('./build-modules-js/javascri const { compressFiles } = require('./build-modules-js/compress.es6.js'); const { versioning } = require('./build-modules-js/versioning.es6.js'); const { Timer } = require('./build-modules-js/utils/timer.es6.js'); +const { compileCodemirror } = require('./build-modules-js/javascript/build-codemirror.es6.js'); // The settings const options = require('../package.json'); @@ -68,6 +69,7 @@ Program .option('--compile-js, --compile-js path', 'Handles ES6, ES5 and web component scripts') .option('--compile-css, --compile-css path', 'Compiles all the scss files to css') .option('--compile-bs', 'Compiles all the Bootstrap component scripts.') + .option('--compile-codemirror', 'Compiles all the codemirror component.') .option('--watch', 'Watch file changes and re-compile (ATM only works for the js in the media_source).') .option('--com-media', 'Compile the Media Manager client side App.') .option('--watch-com-media', 'Watch and Compile the Media Manager client side App.') @@ -125,6 +127,11 @@ if (cliOptions.compileBs) { bootstrapJs(); } +// Compile codemirror +if (cliOptions.compileCodemirror) { + compileCodemirror(); +} + // Gzip js/css files if (cliOptions.gzip) { compressFiles(); diff --git a/package-lock.json b/package-lock.json index f0781a4090dec..7a922c7d1fc61 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,17 @@ "license": "GPL-2.0-or-later", "dependencies": { "@claviska/jquery-minicolors": "^2.3.6", + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/lang-php": "^6.0.0", + "@codemirror/lang-xml": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", "@fortawesome/fontawesome-free": "^6.4.0", "@joomla/joomla-a11y-checker": "^1.0.0", "@popperjs/core": "^2.11.8", @@ -20,7 +31,6 @@ "bootstrap": "~5.2.3", "choices.js": "^9.1.0", "chosen-js": "^1.8.7", - "codemirror": "^5.65.13", "cropperjs": "^1.5.13", "diff": "^5.1.0", "dotenv": "^16.3.1", @@ -1777,6 +1787,148 @@ "jquery": ">= 1.7.x" } }, + "node_modules/@codemirror/autocomplete": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.8.1.tgz", + "integrity": "sha512-HpphvDcTdOx+9R3eUw9hZK9JA77jlaBF0kOt2McbyfvY0rX9pnMoO8rkkZc0GzSbzhIY4m5xJ0uHHgjfqHNmXQ==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.6.0", + "@lezer/common": "^1.0.0" + }, + "peerDependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.4.tgz", + "integrity": "sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.2.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-css": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.0.tgz", + "integrity": "sha512-oyIdJM29AyRPM3+PPq1I2oIk8NpUfEN3kAM05XWDDs6o3gSneIKaVJifT2P+fqONLou2uIgXynFyMUDQvo/szA==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-html": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.5.tgz", + "integrity": "sha512-dUCSxkIw2G+chaUfw3Gfu5kkN83vJQN8gfQDp9iEHsIZluMJA0YJveT12zg/28BJx+uPsbQ6VimKCgx3oJrZxA==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.2.2", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.0" + } + }, + "node_modules/@codemirror/lang-javascript": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.1.9.tgz", + "integrity": "sha512-z3jdkcqOEBT2txn2a87A0jSy6Te3679wg/U8QzMeftFt+4KA6QooMwfdFzJiuC3L6fXKfTXZcDocoaxMYfGz0w==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-php": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.1.tgz", + "integrity": "sha512-ublojMdw/PNWa7qdN5TMsjmqkNuTBD3k6ndZ4Z0S25SBAiweFGyY68AS3xNcIOlb6DDFDvKlinLQ40vSLqf8xA==", + "dependencies": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/php": "^1.0.0" + } + }, + "node_modules/@codemirror/lang-xml": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.0.2.tgz", + "integrity": "sha512-JQYZjHL2LAfpiZI2/qZ/qzDuSqmGKMwyApYmEUUCTxLM4MWS7sATUEfIguZQr9Zjx/7gcdnewb039smF6nC2zw==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + } + }, + "node_modules/@codemirror/language": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.8.0.tgz", + "integrity": "sha512-r1paAyWOZkfY0RaYEZj3Kul+MiQTEbDvYqf8gPGaRvNneHXCmfSaAVFjwRUPlgxS8yflMxw2CTu6uCMp8R8A2g==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.3.0.tgz", + "integrity": "sha512-tzxOVQNoDhhwFNfcTO2IB74wQoWarARcH6gv3YufPpiJ9yhcb7zD6JCkO5+FWARskqRFc8GFa6E+wUyOvADl5A==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.0.tgz", + "integrity": "sha512-64/M40YeJPToKvGO6p3fijo2vwUEj4nACEAXElCaYQ50HrXSvRaK+NHEhSh73WFBGdvIdhrV+lL9PdJy2RfCYA==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz", + "integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==" + }, + "node_modules/@codemirror/view": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.14.0.tgz", + "integrity": "sha512-I263FPs4In42MNmrdwN2DfmYPFMVMXgT7o/mxdGp4jv5LPs8i0FOxzmxF5yeeQdYSTztb2ZhmPIu0ahveInVTg==", + "dependencies": { + "@codemirror/state": "^6.1.4", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -2073,6 +2225,73 @@ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", "dev": true }, + "node_modules/@lezer/common": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.3.tgz", + "integrity": "sha512-JH4wAXCgUOcCGNekQPLhVeUtIqjH0yPBs7vvUdSjyQama9618IOKFJwkv2kcqdhF0my8hQEgCTEJU0GIgnahvA==" + }, + "node_modules/@lezer/css": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.2.tgz", + "integrity": "sha512-5TKMAReXukfEmIiZprDlGfZVfOOCyEStFi1YLzxclm9H3G/HHI49/2wzlRT6bQw5r7PoZVEtjTItEkb/UuZQyg==", + "dependencies": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/highlight": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.6.tgz", + "integrity": "sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/html": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.4.tgz", + "integrity": "sha512-HdJYMVZcT4YsMo7lW3ipL4NoyS2T67kMPuSVS5TgLGqmaCjEU/D6xv7zsa1ktvTK5lwk7zzF1e3eU6gBZIPm5g==", + "dependencies": { + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@lezer/javascript": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.3.tgz", + "integrity": "sha512-k7Eo9z9B1supZ5cCD4ilQv/RZVN30eUQL+gGbr6ybrEY3avBAL5MDiYi2aa23Aj0A79ry4rJRvPAwE2TM8bd+A==", + "dependencies": { + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.7.tgz", + "integrity": "sha512-ssHKb3p0MxhJXT2i7UBmgAY1BIM3Uq/D772Qutu3EVmxWIyNMU12nQ0rL3Fhu+MiFtiTzyTmd3xGwEf3ON5PSA==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/php": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.1.tgz", + "integrity": "sha512-aqdCQJOXJ66De22vzdwnuC502hIaG9EnPK2rSi+ebXyUd+j7GAX1mRjWZOVOmf3GST1YUfUCu6WXDiEgDGOVwA==", + "dependencies": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.1.0" + } + }, + "node_modules/@lezer/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-jMDXrV953sDAUEMI25VNrI9dz94Ai96FfeglytFINhhwQ867HKlCE2jt3AwZTCT7M528WxdDWv/Ty8e9wizwmQ==", + "dependencies": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3315,11 +3534,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/codemirror": { - "version": "5.65.13", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.13.tgz", - "integrity": "sha512-SVWEzKXmbHmTQQWaz03Shrh4nybG0wXx2MEu3FO4ezbPW8IbnZEd5iGHGEffSUaitKYa3i+pHpBsSvw8sPHtzg==" - }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -3456,6 +3670,11 @@ "node": ">=10" } }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, "node_modules/cropperjs": { "version": "1.5.13", "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.13.tgz", @@ -9064,6 +9283,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/style-mod": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.3.tgz", + "integrity": "sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==" + }, "node_modules/style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", @@ -9978,6 +10202,11 @@ "vuex": ">=2.5" } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -11323,6 +11552,142 @@ "integrity": "sha512-8Ro6D4GCrmOl41+6w4NFhEOpx8vjxwVRI69bulXsFDt49uVRKhLU5TnzEV7AmOJrylkVq+ugnYNMiGHBieeKUQ==", "requires": {} }, + "@codemirror/autocomplete": { + "version": "6.8.1", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.8.1.tgz", + "integrity": "sha512-HpphvDcTdOx+9R3eUw9hZK9JA77jlaBF0kOt2McbyfvY0rX9pnMoO8rkkZc0GzSbzhIY4m5xJ0uHHgjfqHNmXQ==", + "requires": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.6.0", + "@lezer/common": "^1.0.0" + } + }, + "@codemirror/commands": { + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.2.4.tgz", + "integrity": "sha512-42lmDqVH0ttfilLShReLXsDfASKLXzfyC36bzwcqzox9PlHulMcsUOfHXNo2X2aFMVNUoQ7j+d4q5bnfseYoOA==", + "requires": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.2.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0" + } + }, + "@codemirror/lang-css": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.2.0.tgz", + "integrity": "sha512-oyIdJM29AyRPM3+PPq1I2oIk8NpUfEN3kAM05XWDDs6o3gSneIKaVJifT2P+fqONLou2uIgXynFyMUDQvo/szA==", + "requires": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.2", + "@lezer/css": "^1.0.0" + } + }, + "@codemirror/lang-html": { + "version": "6.4.5", + "resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.5.tgz", + "integrity": "sha512-dUCSxkIw2G+chaUfw3Gfu5kkN83vJQN8gfQDp9iEHsIZluMJA0YJveT12zg/28BJx+uPsbQ6VimKCgx3oJrZxA==", + "requires": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.2.2", + "@lezer/common": "^1.0.0", + "@lezer/css": "^1.1.0", + "@lezer/html": "^1.3.0" + } + }, + "@codemirror/lang-javascript": { + "version": "6.1.9", + "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.1.9.tgz", + "integrity": "sha512-z3jdkcqOEBT2txn2a87A0jSy6Te3679wg/U8QzMeftFt+4KA6QooMwfdFzJiuC3L6fXKfTXZcDocoaxMYfGz0w==", + "requires": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.6.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/javascript": "^1.0.0" + } + }, + "@codemirror/lang-php": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-php/-/lang-php-6.0.1.tgz", + "integrity": "sha512-ublojMdw/PNWa7qdN5TMsjmqkNuTBD3k6ndZ4Z0S25SBAiweFGyY68AS3xNcIOlb6DDFDvKlinLQ40vSLqf8xA==", + "requires": { + "@codemirror/lang-html": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/php": "^1.0.0" + } + }, + "@codemirror/lang-xml": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/@codemirror/lang-xml/-/lang-xml-6.0.2.tgz", + "integrity": "sha512-JQYZjHL2LAfpiZI2/qZ/qzDuSqmGKMwyApYmEUUCTxLM4MWS7sATUEfIguZQr9Zjx/7gcdnewb039smF6nC2zw==", + "requires": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/language": "^6.4.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/xml": "^1.0.0" + } + }, + "@codemirror/language": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.8.0.tgz", + "integrity": "sha512-r1paAyWOZkfY0RaYEZj3Kul+MiQTEbDvYqf8gPGaRvNneHXCmfSaAVFjwRUPlgxS8yflMxw2CTu6uCMp8R8A2g==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "@codemirror/lint": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.3.0.tgz", + "integrity": "sha512-tzxOVQNoDhhwFNfcTO2IB74wQoWarARcH6gv3YufPpiJ9yhcb7zD6JCkO5+FWARskqRFc8GFa6E+wUyOvADl5A==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "@codemirror/search": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.0.tgz", + "integrity": "sha512-64/M40YeJPToKvGO6p3fijo2vwUEj4nACEAXElCaYQ50HrXSvRaK+NHEhSh73WFBGdvIdhrV+lL9PdJy2RfCYA==", + "requires": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "@codemirror/state": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.2.1.tgz", + "integrity": "sha512-RupHSZ8+OjNT38zU9fKH2sv+Dnlr8Eb8sl4NOnnqz95mCFTZUaiRP8Xv5MeeaG0px2b8Bnfe7YGwCV3nsBhbuw==" + }, + "@codemirror/view": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.14.0.tgz", + "integrity": "sha512-I263FPs4In42MNmrdwN2DfmYPFMVMXgT7o/mxdGp4jv5LPs8i0FOxzmxF5yeeQdYSTztb2ZhmPIu0ahveInVTg==", + "requires": { + "@codemirror/state": "^6.1.4", + "style-mod": "^4.0.0", + "w3c-keyname": "^2.2.4" + } + }, "@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -11551,6 +11916,73 @@ } } }, + "@lezer/common": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.0.3.tgz", + "integrity": "sha512-JH4wAXCgUOcCGNekQPLhVeUtIqjH0yPBs7vvUdSjyQama9618IOKFJwkv2kcqdhF0my8hQEgCTEJU0GIgnahvA==" + }, + "@lezer/css": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.1.2.tgz", + "integrity": "sha512-5TKMAReXukfEmIiZprDlGfZVfOOCyEStFi1YLzxclm9H3G/HHI49/2wzlRT6bQw5r7PoZVEtjTItEkb/UuZQyg==", + "requires": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "@lezer/highlight": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.1.6.tgz", + "integrity": "sha512-cmSJYa2us+r3SePpRCjN5ymCqCPv+zyXmDl0ciWtVaNiORT/MxM7ZgOMQZADD0o51qOaOg24qc/zBViOIwAjJg==", + "requires": { + "@lezer/common": "^1.0.0" + } + }, + "@lezer/html": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.4.tgz", + "integrity": "sha512-HdJYMVZcT4YsMo7lW3ipL4NoyS2T67kMPuSVS5TgLGqmaCjEU/D6xv7zsa1ktvTK5lwk7zzF1e3eU6gBZIPm5g==", + "requires": { + "@lezer/common": "^1.0.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "@lezer/javascript": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.4.3.tgz", + "integrity": "sha512-k7Eo9z9B1supZ5cCD4ilQv/RZVN30eUQL+gGbr6ybrEY3avBAL5MDiYi2aa23Aj0A79ry4rJRvPAwE2TM8bd+A==", + "requires": { + "@lezer/highlight": "^1.1.3", + "@lezer/lr": "^1.3.0" + } + }, + "@lezer/lr": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.3.7.tgz", + "integrity": "sha512-ssHKb3p0MxhJXT2i7UBmgAY1BIM3Uq/D772Qutu3EVmxWIyNMU12nQ0rL3Fhu+MiFtiTzyTmd3xGwEf3ON5PSA==", + "requires": { + "@lezer/common": "^1.0.0" + } + }, + "@lezer/php": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/php/-/php-1.0.1.tgz", + "integrity": "sha512-aqdCQJOXJ66De22vzdwnuC502hIaG9EnPK2rSi+ebXyUd+j7GAX1mRjWZOVOmf3GST1YUfUCu6WXDiEgDGOVwA==", + "requires": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.1.0" + } + }, + "@lezer/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@lezer/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-jMDXrV953sDAUEMI25VNrI9dz94Ai96FfeglytFINhhwQ867HKlCE2jt3AwZTCT7M528WxdDWv/Ty8e9wizwmQ==", + "requires": { + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -12469,11 +12901,6 @@ "string-width": "^4.2.0" } }, - "codemirror": { - "version": "5.65.13", - "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.13.tgz", - "integrity": "sha512-SVWEzKXmbHmTQQWaz03Shrh4nybG0wXx2MEu3FO4ezbPW8IbnZEd5iGHGEffSUaitKYa3i+pHpBsSvw8sPHtzg==" - }, "color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", @@ -12589,6 +13016,11 @@ "yaml": "^1.10.0" } }, + "crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, "cropperjs": { "version": "1.5.13", "resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-1.5.13.tgz", @@ -16661,6 +17093,11 @@ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, + "style-mod": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.3.tgz", + "integrity": "sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw==" + }, "style-search": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", @@ -17372,6 +17809,11 @@ "flatted": "^3.0.5" } }, + "w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 4a9b9fb8fe524..e907179801d1b 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,18 @@ ], "dependencies": { "@claviska/jquery-minicolors": "^2.3.6", + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", + "@codemirror/lang-html": "^6.0.0", + "@codemirror/lang-javascript": "^6.0.0", + "@codemirror/lang-php": "^6.0.0", + "@codemirror/lang-xml": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", "@fortawesome/fontawesome-free": "^6.4.0", "@joomla/joomla-a11y-checker": "^1.0.0", "@popperjs/core": "^2.11.8", @@ -47,7 +59,6 @@ "bootstrap": "~5.2.3", "choices.js": "^9.1.0", "chosen-js": "^1.8.7", - "codemirror": "^5.65.13", "cropperjs": "^1.5.13", "diff": "^5.1.0", "dotenv": "^16.3.1", From 14ae91d82505140028e5640ad7e498b14ada3556 Mon Sep 17 00:00:00 2001 From: Fedik Date: Sun, 25 Jun 2023 18:03:48 +0300 Subject: [PATCH 02/53] Codemirror deps and build --- .../javascript/build-codemirror.es6.js | 39 ++++++++++++------- package-lock.json | 1 + 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 7500574456b70..4ce61712fd99a 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -4,22 +4,21 @@ /* eslint-disable import/no-extraneous-dependencies */ const { - existsSync, readFile, writeFile, mkdir, mkdirs, ensureDir, readdirSync, + existsSync, readFile, writeFile, readdirSync, } = require('fs-extra'); const rollup = require('rollup'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); const replace = require('@rollup/plugin-replace'); const { minify } = require('terser'); -const {resolve} = require("path"); -// Find a list of installed codemirror modules -const retrieveListOfModules = () => { +// Find a list of modules for given provider, eg all sub @codemirror/... +const retrieveListOfChildModules = (provider) => { const cmModules = []; // Get @codemirror module roots const roots = []; module.paths.forEach((path) => { - const fullPath = `${path}/@codemirror`; + const fullPath = `${path}/${provider}`; if (existsSync(fullPath)) { roots.push(fullPath); } @@ -28,7 +27,7 @@ const retrieveListOfModules = () => { // List of modules roots.forEach((rootPath) => { readdirSync(rootPath).forEach((subModule) => { - cmModules.push(`@codemirror/${subModule}`); + cmModules.push(`${provider}/${subModule}`); }); }); @@ -39,7 +38,7 @@ const retrieveListOfModules = () => { const buildModule = async (module, externalModules, destFile) => { const build = await rollup.rollup({ input: module, - external: externalModules, + external: externalModules || [], plugins: [ nodeResolve(), replace({ @@ -49,14 +48,15 @@ const buildModule = async (module, externalModules, destFile) => { ], }); - build.write({ + await build.write({ format: 'es', sourcemap: false, file: destFile, }); - build.close(); + await build.close(); }; + // Minify a js file const createMinified = (filePath) => { const destFile = filePath.replace('.js', '.min.js'); @@ -74,17 +74,30 @@ module.exports.compileCodemirror = async () => { // eslint-disable-next-line no-console console.log('Building Codemirror Components...'); - const cmModules = retrieveListOfModules(); + const cmModules = retrieveListOfChildModules('@codemirror'); + const lModules = retrieveListOfChildModules('@lezer'); + const externalModules = [...cmModules, ...lModules]; const destBasePath = 'media/vendor/codemirror/js'; + // Prepare @codemirror modules cmModules.forEach((module) => { - const destFile = `${module.replace('@codemirror/', '')}.js`; + const destFile = `${module.replace('@codemirror/', 'codemirror-')}.js`; + const destPath = `${destBasePath}/${destFile}`; + + buildModule(module, externalModules, destPath).then(() => { + createMinified(destPath); + }); + }); + + // Prepare @lezer modules which @codemirror depends on + lModules.forEach((module) => { + const destFile = `${module.replace('@lezer/', 'lezer-')}.js`; const destPath = `${destBasePath}/${destFile}`; - buildModule(module, cmModules, destPath).then(() => { + buildModule(module, externalModules, destPath).then(() => { createMinified(destPath); }); }); - // console.log('compileCodemirror', cmModules, resultFiles); + // console.log('compileCodemirror', cmModules, lModules); }; diff --git a/package-lock.json b/package-lock.json index 7a922c7d1fc61..43e856f8f3806 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@claviska/jquery-minicolors": "^2.3.6", "@codemirror/autocomplete": "^6.0.0", "@codemirror/commands": "^6.0.0", + "@codemirror/lang-css": "^6.0.0", "@codemirror/lang-html": "^6.0.0", "@codemirror/lang-javascript": "^6.0.0", "@codemirror/lang-php": "^6.0.0", From 012ca927cbb3f7ab33760350e5094bbc29e11f9f Mon Sep 17 00:00:00 2001 From: Fedik Date: Sun, 25 Jun 2023 18:22:09 +0300 Subject: [PATCH 03/53] Codemirror deps and build --- build/build-modules-js/init/localise-packages.es6.js | 5 +---- build/build-modules-js/settings.json | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/build/build-modules-js/init/localise-packages.es6.js b/build/build-modules-js/init/localise-packages.es6.js index 6f99e50ed4acc..fc0c056644e27 100644 --- a/build/build-modules-js/init/localise-packages.es6.js +++ b/build/build-modules-js/init/localise-packages.es6.js @@ -2,7 +2,6 @@ const { existsSync, copy, writeFile, mkdir, mkdirs, ensureDir, } = require('fs-extra'); const { dirname, join } = require('path'); -const { codeMirror } = require('./exemptions/codemirror.es6.js'); const { tinyMCE } = require('./exemptions/tinymce.es6.js'); const RootPath = process.cwd(); @@ -65,9 +64,7 @@ const resolvePackage = async (vendor, packageName, mediaVendorPath, options, reg const promises = []; - if (packageName === 'codemirror') { - promises.push(codeMirror(packageName, moduleOptions.version)); - } else if (packageName === 'tinymce') { + if (packageName === 'tinymce') { promises.push(tinyMCE(packageName, moduleOptions.version)); } else { await mkdirs(join(mediaVendorPath, vendorName)); diff --git a/build/build-modules-js/settings.json b/build/build-modules-js/settings.json index 77797fdd9d277..bd8293db96631 100644 --- a/build/build-modules-js/settings.json +++ b/build/build-modules-js/settings.json @@ -609,7 +609,7 @@ ], "licenseFilename": "LICENSE.md" }, - "codemirror": { + "@codemirror/view": { "name": "codemirror", "licenseFilename": "LICENSE" }, From 00048d8da752d8fae7ffb0ad6aa0e415341e5109 Mon Sep 17 00:00:00 2001 From: Fedik Date: Sun, 25 Jun 2023 18:44:53 +0300 Subject: [PATCH 04/53] Codemirror progress bar --- .../javascript/build-codemirror.es6.js | 33 ++++++++++++------- package-lock.json | 22 +++++++++++++ package.json | 1 + 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 4ce61712fd99a..96ff57091819d 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -6,6 +6,7 @@ const { existsSync, readFile, writeFile, readdirSync, } = require('fs-extra'); +const cliProgress = require('cli-progress'); const rollup = require('rollup'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); const replace = require('@rollup/plugin-replace'); @@ -56,18 +57,15 @@ const buildModule = async (module, externalModules, destFile) => { await build.close(); }; - // Minify a js file -const createMinified = (filePath) => { +const createMinified = async (filePath) => { const destFile = filePath.replace('.js', '.min.js'); // Read source - readFile(filePath, { encoding: 'utf8' }).then((src) => { - // Minify - minify(src, { sourceMap: false, format: { comments: false } }).then((result) => { - // Save result - writeFile(destFile, result.code, { encoding: 'utf8', mode: 0o644 }); - }); - }); + const src = await readFile(filePath, { encoding: 'utf8' }); + // Minify + const min = await minify(src, { sourceMap: false, format: { comments: false } }); + // Save result + await writeFile(destFile, min.code, { encoding: 'utf8', mode: 0o644 }); }; module.exports.compileCodemirror = async () => { @@ -79,13 +77,23 @@ module.exports.compileCodemirror = async () => { const externalModules = [...cmModules, ...lModules]; const destBasePath = 'media/vendor/codemirror/js'; + const progressBar = new cliProgress.SingleBar({ + stopOnComplete: true, + format: '{bar} {percentage}% | {value}/{total} files done', + }, cliProgress.Presets.shades_classic); + const totalSteps = (cmModules.length + lModules.length) * 2; + progressBar.start(totalSteps, 0); + // Prepare @codemirror modules cmModules.forEach((module) => { const destFile = `${module.replace('@codemirror/', 'codemirror-')}.js`; const destPath = `${destBasePath}/${destFile}`; buildModule(module, externalModules, destPath).then(() => { - createMinified(destPath); + progressBar.increment(); + createMinified(destPath).then(() => { + progressBar.increment(); + }); }); }); @@ -95,7 +103,10 @@ module.exports.compileCodemirror = async () => { const destPath = `${destBasePath}/${destFile}`; buildModule(module, externalModules, destPath).then(() => { - createMinified(destPath); + progressBar.increment(); + createMinified(destPath).then(() => { + progressBar.increment(); + }); }); }); diff --git a/package-lock.json b/package-lock.json index 43e856f8f3806..2db501fee2a17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -68,6 +68,7 @@ "@vue/compiler-sfc": "^3.3.4", "autoprefixer": "^10.4.14", "chokidar": "^3.5.3", + "cli-progress": "^3.12.0", "commander": "^8.3.0", "core-js": "^3.31.0", "cssnano": "^5.1.15", @@ -3504,6 +3505,18 @@ "node": ">=8" } }, + "node_modules/cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dev": true, + "dependencies": { + "string-width": "^4.2.3" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/cli-table3": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", @@ -12882,6 +12895,15 @@ "restore-cursor": "^3.1.0" } }, + "cli-progress": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.12.0.tgz", + "integrity": "sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==", + "dev": true, + "requires": { + "string-width": "^4.2.3" + } + }, "cli-table3": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", diff --git a/package.json b/package.json index e907179801d1b..1bc51b65c7a65 100644 --- a/package.json +++ b/package.json @@ -95,6 +95,7 @@ "@vue/compiler-sfc": "^3.3.4", "autoprefixer": "^10.4.14", "chokidar": "^3.5.3", + "cli-progress": "^3.12.0", "commander": "^8.3.0", "core-js": "^3.31.0", "cssnano": "^5.1.15", From 70c2c91e1a56f4b329004a7fd7c9923d3be76c3f Mon Sep 17 00:00:00 2001 From: Fedik Date: Sun, 25 Jun 2023 20:00:22 +0300 Subject: [PATCH 05/53] Codemirror build --- .../javascript/build-codemirror.es6.js | 14 +- build/build-modules-js/settings.json | 124 +++++++++++++++++- build/build.js | 1 + 3 files changed, 133 insertions(+), 6 deletions(-) diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 96ff57091819d..04878498bf64d 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -76,6 +76,7 @@ module.exports.compileCodemirror = async () => { const lModules = retrieveListOfChildModules('@lezer'); const externalModules = [...cmModules, ...lModules]; const destBasePath = 'media/vendor/codemirror/js'; + const tasks = []; const progressBar = new cliProgress.SingleBar({ stopOnComplete: true, @@ -89,12 +90,13 @@ module.exports.compileCodemirror = async () => { const destFile = `${module.replace('@codemirror/', 'codemirror-')}.js`; const destPath = `${destBasePath}/${destFile}`; - buildModule(module, externalModules, destPath).then(() => { + const task = buildModule(module, externalModules, destPath).then(() => { progressBar.increment(); - createMinified(destPath).then(() => { + return createMinified(destPath).then(() => { progressBar.increment(); }); }); + tasks.push(task); }); // Prepare @lezer modules which @codemirror depends on @@ -102,13 +104,15 @@ module.exports.compileCodemirror = async () => { const destFile = `${module.replace('@lezer/', 'lezer-')}.js`; const destPath = `${destBasePath}/${destFile}`; - buildModule(module, externalModules, destPath).then(() => { + const task2 = buildModule(module, externalModules, destPath).then(() => { progressBar.increment(); - createMinified(destPath).then(() => { + return createMinified(destPath).then(() => { progressBar.increment(); }); }); + tasks.push(task2); }); + // console.log('compileCodemirror', cmModules, lModules, tasks); - // console.log('compileCodemirror', cmModules, lModules); + return Promise.all(tasks); }; diff --git a/build/build-modules-js/settings.json b/build/build-modules-js/settings.json index bd8293db96631..0c5a2c851137a 100644 --- a/build/build-modules-js/settings.json +++ b/build/build-modules-js/settings.json @@ -611,7 +611,129 @@ }, "@codemirror/view": { "name": "codemirror", - "licenseFilename": "LICENSE" + "licenseFilename": "LICENSE", + "provideAssets": [ + { + "name": "@codemirror/autocomplete", + "type": "script", + "uri": "codemirror-autocomplete.min.js", + "importmap": true + }, + { + "name": "@codemirror/commands", + "type": "script", + "uri": "codemirror-commands.min.js", + "importmap": true + }, + { + "name": "@codemirror/lang-css", + "type": "script", + "uri": "codemirror-lang-css.min.js", + "importmap": true + }, + { + "name": "@codemirror/lang-html", + "type": "script", + "uri": "codemirror-lang-html.min.js", + "importmap": true + }, + { + "name": "@codemirror/lang-javascript", + "type": "script", + "uri": "codemirror-lang-javascript.min.js", + "importmap": true + }, + { + "name": "@codemirror/lang-php", + "type": "script", + "uri": "codemirror-lang-php.min.js", + "importmap": true + }, + { + "name": "@codemirror/lang-xml", + "type": "script", + "uri": "codemirror-lang-xml.min.js", + "importmap": true + }, + { + "name": "@codemirror/language", + "type": "script", + "uri": "codemirror-language.min.js", + "importmap": true + }, + { + "name": "@codemirror/lint", + "type": "script", + "uri": "codemirror-lint.min.js", + "importmap": true + }, + { + "name": "@codemirror/search", + "type": "script", + "uri": "codemirror-search.min.js", + "importmap": true + }, + { + "name": "@codemirror/state", + "type": "script", + "uri": "codemirror-state.min.js", + "importmap": true + }, + { + "name": "@codemirror/view", + "type": "script", + "uri": "codemirror-view.min.js", + "importmap": true + }, + { + "name": "@lezer/common", + "type": "script", + "uri": "lezer-common.min.js", + "importmap": true + }, + { + "name": "@lezer/css", + "type": "script", + "uri": "lezer-css.min.js", + "importmap": true + }, + { + "name": "@lezer/highlight", + "type": "script", + "uri": "lezer-highlight.min.js", + "importmap": true + }, + { + "name": "@lezer/html", + "type": "script", + "uri": "lezer-html.min.js", + "importmap": true + }, + { + "name": "@lezer/javascript", + "type": "script", + "uri": "lezer-javascript.min.js", + "importmap": true + }, + { + "name": "@lezer/lr", + "type": "script", + "uri": "lezer-lr.min.js", + "importmap": true + }, + { + "name": "@lezer/php", + "type": "script", + "uri": "@lezer-php.min.js", + "importmap": true + }, + { + "name": "@lezer/xml", + "type": "script", + "uri": "lezer-xml.min.js", + "importmap": true + } + ] }, "tinymce": { "name": "tinymce", diff --git a/build/build.js b/build/build.js index 20f7af0cda523..b4f7dd66c57ef 100644 --- a/build/build.js +++ b/build/build.js @@ -168,6 +168,7 @@ if (cliOptions.prepare) { .then(() => scripts(options, Program.args[0])) .then(() => mediaManager()) .then(() => bootstrapJs()) + .then(() => compileCodemirror()) .then(() => bench.stop('Build')) .then(() => { process.exit(0); }) .catch((err) => { From c988652e51864d1adb1296abab804743a681a3dd Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 26 Jun 2023 14:51:22 +0300 Subject: [PATCH 06/53] Codemirror registry file --- .../init/common/resolve-package-file.js | 19 +++ .../init/localise-packages.es6.js | 20 +-- .../javascript/build-codemirror.es6.js | 66 ++++++++-- build/build-modules-js/settings.json | 124 +----------------- .../plg_editors_codemirror/joomla.asset.json | 21 +++ 5 files changed, 100 insertions(+), 150 deletions(-) create mode 100644 build/build-modules-js/init/common/resolve-package-file.js create mode 100644 build/media_source/plg_editors_codemirror/joomla.asset.json diff --git a/build/build-modules-js/init/common/resolve-package-file.js b/build/build-modules-js/init/common/resolve-package-file.js new file mode 100644 index 0000000000000..07449b87ebf2b --- /dev/null +++ b/build/build-modules-js/init/common/resolve-package-file.js @@ -0,0 +1,19 @@ +const { existsSync } = require('fs-extra'); +/** + * Find full path for package file. + * Replacement for require.resolve(), as it is broken for packages with "exports" property. + * + * @param {string} relativePath Relative path to the file to resolve, in format packageName/file-name.js + * @returns {string|boolean} + */ +module.exports.resolvePackageFile = (relativePath) => { + for (let i = 0, l = module.paths.length; i < l; i += 1) { + const path = module.paths[i]; + const fullPath = `${path}/${relativePath}`; + if (existsSync(fullPath)) { + return fullPath; + } + } + + return false; +}; diff --git a/build/build-modules-js/init/localise-packages.es6.js b/build/build-modules-js/init/localise-packages.es6.js index fc0c056644e27..b26bf6d7901fb 100644 --- a/build/build-modules-js/init/localise-packages.es6.js +++ b/build/build-modules-js/init/localise-packages.es6.js @@ -3,28 +3,10 @@ const { } = require('fs-extra'); const { dirname, join } = require('path'); const { tinyMCE } = require('./exemptions/tinymce.es6.js'); +const { resolvePackageFile } = require('./common/resolve-package-file'); const RootPath = process.cwd(); -/** - * Find full path for package file. - * Replacement for require.resolve(), as it is broken for packages with "exports" property. - * - * @param {string} relativePath Relative path to the file to resolve, in format packageName/file-name.js - * @returns {string|boolean} - */ -const resolvePackageFile = (relativePath) => { - for (let i = 0, l = module.paths.length; i < l; i += 1) { - const path = module.paths[i]; - const fullPath = `${path}/${relativePath}`; - if (existsSync(fullPath)) { - return fullPath; - } - } - - return false; -}; - /** * * @param {object} files the object of files map, eg {"src.js": "js/src.js"} diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 04878498bf64d..2da03ad1e8871 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -1,25 +1,26 @@ /** * Build codemirror modules */ -/* eslint-disable import/no-extraneous-dependencies */ +/* eslint-disable import/no-extraneous-dependencies, global-require, import/no-dynamic-require */ const { - existsSync, readFile, writeFile, readdirSync, + existsSync, readFileSync, writeFile, readdirSync, } = require('fs-extra'); const cliProgress = require('cli-progress'); const rollup = require('rollup'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); const replace = require('@rollup/plugin-replace'); const { minify } = require('terser'); +const { resolvePackageFile } = require('../init/common/resolve-package-file'); -// Find a list of modules for given provider, eg all sub @codemirror/... -const retrieveListOfChildModules = (provider) => { +// Find a list of modules for given scope, eg all sub @codemirror/... +const retrieveListOfChildModules = (scope) => { const cmModules = []; // Get @codemirror module roots const roots = []; module.paths.forEach((path) => { - const fullPath = `${path}/${provider}`; + const fullPath = `${path}/${scope}`; if (existsSync(fullPath)) { roots.push(fullPath); } @@ -28,7 +29,7 @@ const retrieveListOfChildModules = (provider) => { // List of modules roots.forEach((rootPath) => { readdirSync(rootPath).forEach((subModule) => { - cmModules.push(`${provider}/${subModule}`); + cmModules.push(`${scope}/${subModule}`); }); }); @@ -61,13 +62,56 @@ const buildModule = async (module, externalModules, destFile) => { const createMinified = async (filePath) => { const destFile = filePath.replace('.js', '.min.js'); // Read source - const src = await readFile(filePath, { encoding: 'utf8' }); + const src = readFileSync(filePath, { encoding: 'utf8' }); // Minify const min = await minify(src, { sourceMap: false, format: { comments: false } }); // Save result await writeFile(destFile, min.code, { encoding: 'utf8', mode: 0o644 }); }; +// Update joomla.asset.json for codemirror +const updateAssetRegistry = async (modules, externalModules) => { + const srcPath = 'build/media_source/plg_editors_codemirror/joomla.asset.json'; + const destPath = 'media/plg_editors_codemirror/joomla.asset.json'; + + // Get base JSON and update + const registry = JSON.parse(readFileSync(srcPath, { encoding: 'utf8' })); + + // Create asset for each module + modules.forEach((module) => { + const packageName = module.package; + const modulePathJson = resolvePackageFile(`${packageName}/package.json`); + const moduleOptions = require(modulePathJson); + const asset = { + type: 'script', + name: module.package, + uri: module.uri.replace('.js', '.min.js'), + importmap: true, + package: module.package, + version: moduleOptions.version, + dependencies: [], + }; + + // Check for known modules to be used as dependency + if (moduleOptions.dependencies) { + Object.entries(moduleOptions.dependencies).forEach(([key]) => { + if (externalModules.includes(key)) { + asset.dependencies.push(key); + } + }); + } + + registry.assets.push(asset); + }); + + // Write assets registry + await writeFile( + destPath, + JSON.stringify(registry, null, 2), + { encoding: 'utf8', mode: 0o644 }, + ); +}; + module.exports.compileCodemirror = async () => { // eslint-disable-next-line no-console console.log('Building Codemirror Components...'); @@ -76,6 +120,7 @@ module.exports.compileCodemirror = async () => { const lModules = retrieveListOfChildModules('@lezer'); const externalModules = [...cmModules, ...lModules]; const destBasePath = 'media/vendor/codemirror/js'; + const assets = []; const tasks = []; const progressBar = new cliProgress.SingleBar({ @@ -89,6 +134,7 @@ module.exports.compileCodemirror = async () => { cmModules.forEach((module) => { const destFile = `${module.replace('@codemirror/', 'codemirror-')}.js`; const destPath = `${destBasePath}/${destFile}`; + assets.push({ package: module, uri: destPath }); const task = buildModule(module, externalModules, destPath).then(() => { progressBar.increment(); @@ -103,6 +149,7 @@ module.exports.compileCodemirror = async () => { lModules.forEach((module) => { const destFile = `${module.replace('@lezer/', 'lezer-')}.js`; const destPath = `${destBasePath}/${destFile}`; + assets.push({ package: module, uri: destPath }); const task2 = buildModule(module, externalModules, destPath).then(() => { progressBar.increment(); @@ -114,5 +161,8 @@ module.exports.compileCodemirror = async () => { }); // console.log('compileCodemirror', cmModules, lModules, tasks); - return Promise.all(tasks); + return Promise.all(tasks).then(() => { + progressBar.stop(); + return updateAssetRegistry(assets, externalModules); + }); }; diff --git a/build/build-modules-js/settings.json b/build/build-modules-js/settings.json index a5d016f817fa6..c60416d1dc739 100644 --- a/build/build-modules-js/settings.json +++ b/build/build-modules-js/settings.json @@ -619,129 +619,7 @@ }, "@codemirror/view": { "name": "codemirror", - "licenseFilename": "LICENSE", - "provideAssets": [ - { - "name": "@codemirror/autocomplete", - "type": "script", - "uri": "codemirror-autocomplete.min.js", - "importmap": true - }, - { - "name": "@codemirror/commands", - "type": "script", - "uri": "codemirror-commands.min.js", - "importmap": true - }, - { - "name": "@codemirror/lang-css", - "type": "script", - "uri": "codemirror-lang-css.min.js", - "importmap": true - }, - { - "name": "@codemirror/lang-html", - "type": "script", - "uri": "codemirror-lang-html.min.js", - "importmap": true - }, - { - "name": "@codemirror/lang-javascript", - "type": "script", - "uri": "codemirror-lang-javascript.min.js", - "importmap": true - }, - { - "name": "@codemirror/lang-php", - "type": "script", - "uri": "codemirror-lang-php.min.js", - "importmap": true - }, - { - "name": "@codemirror/lang-xml", - "type": "script", - "uri": "codemirror-lang-xml.min.js", - "importmap": true - }, - { - "name": "@codemirror/language", - "type": "script", - "uri": "codemirror-language.min.js", - "importmap": true - }, - { - "name": "@codemirror/lint", - "type": "script", - "uri": "codemirror-lint.min.js", - "importmap": true - }, - { - "name": "@codemirror/search", - "type": "script", - "uri": "codemirror-search.min.js", - "importmap": true - }, - { - "name": "@codemirror/state", - "type": "script", - "uri": "codemirror-state.min.js", - "importmap": true - }, - { - "name": "@codemirror/view", - "type": "script", - "uri": "codemirror-view.min.js", - "importmap": true - }, - { - "name": "@lezer/common", - "type": "script", - "uri": "lezer-common.min.js", - "importmap": true - }, - { - "name": "@lezer/css", - "type": "script", - "uri": "lezer-css.min.js", - "importmap": true - }, - { - "name": "@lezer/highlight", - "type": "script", - "uri": "lezer-highlight.min.js", - "importmap": true - }, - { - "name": "@lezer/html", - "type": "script", - "uri": "lezer-html.min.js", - "importmap": true - }, - { - "name": "@lezer/javascript", - "type": "script", - "uri": "lezer-javascript.min.js", - "importmap": true - }, - { - "name": "@lezer/lr", - "type": "script", - "uri": "lezer-lr.min.js", - "importmap": true - }, - { - "name": "@lezer/php", - "type": "script", - "uri": "@lezer-php.min.js", - "importmap": true - }, - { - "name": "@lezer/xml", - "type": "script", - "uri": "lezer-xml.min.js", - "importmap": true - } - ] + "licenseFilename": "LICENSE" }, "tinymce": { "name": "tinymce", diff --git a/build/media_source/plg_editors_codemirror/joomla.asset.json b/build/media_source/plg_editors_codemirror/joomla.asset.json new file mode 100644 index 0000000000000..d6ccccba2c8ed --- /dev/null +++ b/build/media_source/plg_editors_codemirror/joomla.asset.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://developer.joomla.org/schemas/json-schema/web_assets.json", + "name": "plg_editors_codemirror", + "version": "5.0.0", + "description": "Joomla CMS", + "license": "GPL-2.0-or-later", + "assets": [ + { + "name": "webcomponent.editor-codemirror", + "type": "script", + "uri": "plg_editors_codemirror/joomla-editor-codemirror.min.js", + "dependencies": [ + "core", + "wcpolyfill" + ], + "attributes": { + "type": "module" + } + } + ] +} From 4c684577a381858ed567bd2ab32aef5b31c7fdaa Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 26 Jun 2023 15:08:53 +0300 Subject: [PATCH 07/53] Codemirror build --- .../javascript/build-codemirror.es6.js | 20 +++++++++---------- .../plg_editors_codemirror/joomla.asset.json | 1 + 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 2da03ad1e8871..054633451868e 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -77,6 +77,15 @@ const updateAssetRegistry = async (modules, externalModules) => { // Get base JSON and update const registry = JSON.parse(readFileSync(srcPath, { encoding: 'utf8' })); + // Create a dummy codemirror asset with all dependencies + registry.assets.push({ + type: 'script', + name: 'codemirror', + uri: '', + dependencies: externalModules, + attributes: { type: 'module' }, + }); + // Create asset for each module modules.forEach((module) => { const packageName = module.package; @@ -87,20 +96,9 @@ const updateAssetRegistry = async (modules, externalModules) => { name: module.package, uri: module.uri.replace('.js', '.min.js'), importmap: true, - package: module.package, version: moduleOptions.version, - dependencies: [], }; - // Check for known modules to be used as dependency - if (moduleOptions.dependencies) { - Object.entries(moduleOptions.dependencies).forEach(([key]) => { - if (externalModules.includes(key)) { - asset.dependencies.push(key); - } - }); - } - registry.assets.push(asset); }); diff --git a/build/media_source/plg_editors_codemirror/joomla.asset.json b/build/media_source/plg_editors_codemirror/joomla.asset.json index d6ccccba2c8ed..f8fe71de457fd 100644 --- a/build/media_source/plg_editors_codemirror/joomla.asset.json +++ b/build/media_source/plg_editors_codemirror/joomla.asset.json @@ -11,6 +11,7 @@ "uri": "plg_editors_codemirror/joomla-editor-codemirror.min.js", "dependencies": [ "core", + "codemirror", "wcpolyfill" ], "attributes": { From da7203972b7034b424e18d0864a490dd98b61368 Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 26 Jun 2023 16:22:14 +0300 Subject: [PATCH 08/53] Codemirror plugin --- .../javascript/build-codemirror.es6.js | 12 +- .../plg_editors_codemirror/joomla.asset.json | 11 ++ .../js/codemirror-base.js | 8 ++ plugins/editors/codemirror/codemirror.xml | 3 +- .../layouts/editors/codemirror/element.php | 34 +++--- .../layouts/editors/codemirror/styles.php | 53 --------- .../codemirror/src/Extension/Codemirror.php | 103 +----------------- 7 files changed, 46 insertions(+), 178 deletions(-) create mode 100644 build/media_source/plg_editors_codemirror/js/codemirror-base.js delete mode 100644 plugins/editors/codemirror/layouts/editors/codemirror/styles.php diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 054633451868e..93b10b77a02c3 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -77,13 +77,11 @@ const updateAssetRegistry = async (modules, externalModules) => { // Get base JSON and update const registry = JSON.parse(readFileSync(srcPath, { encoding: 'utf8' })); - // Create a dummy codemirror asset with all dependencies - registry.assets.push({ - type: 'script', - name: 'codemirror', - uri: '', - dependencies: externalModules, - attributes: { type: 'module' }, + // Add dependencies to base codemirror asset + registry.assets.forEach((asset) => { + if (asset.name === 'codemirror' && asset.type === 'script') { + asset.dependencies = externalModules; + } }); // Create asset for each module diff --git a/build/media_source/plg_editors_codemirror/joomla.asset.json b/build/media_source/plg_editors_codemirror/joomla.asset.json index f8fe71de457fd..5047b871befa8 100644 --- a/build/media_source/plg_editors_codemirror/joomla.asset.json +++ b/build/media_source/plg_editors_codemirror/joomla.asset.json @@ -5,6 +5,17 @@ "description": "Joomla CMS", "license": "GPL-2.0-or-later", "assets": [ + { + "name": "plg_editors_codemirror", + "type": "style", + "uri": "plg_editors_codemirror/codemirror.css" + }, + { + "name": "codemirror", + "type": "script", + "uri": "plg_editors_codemirror/codemirror-base.min.js", + "importmap": true + }, { "name": "webcomponent.editor-codemirror", "type": "script", diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.js new file mode 100644 index 0000000000000..8278e25862f71 --- /dev/null +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.js @@ -0,0 +1,8 @@ +/** + * @copyright (C) 2023 Open Source Matters, Inc. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +import { EditorView } from '@codemirror/view'; + +console.log(EditorView); diff --git a/plugins/editors/codemirror/codemirror.xml b/plugins/editors/codemirror/codemirror.xml index d249b1d1067e9..318cab41d53e9 100644 --- a/plugins/editors/codemirror/codemirror.xml +++ b/plugins/editors/codemirror/codemirror.xml @@ -191,7 +191,7 @@ - + diff --git a/plugins/editors/codemirror/layouts/editors/codemirror/element.php b/plugins/editors/codemirror/layouts/editors/codemirror/element.php index a89c0dfb8b332..07e3e45369e7f 100644 --- a/plugins/editors/codemirror/layouts/editors/codemirror/element.php +++ b/plugins/editors/codemirror/layouts/editors/codemirror/element.php @@ -25,35 +25,31 @@ $content = $displayData->content; $extJS = JDEBUG ? '.js' : '.min.js'; $modifier = $params->get('fullScreenMod', []) ? implode(' + ', $params->get('fullScreenMod', [])) . ' + ' : ''; -$basePath = $displayData->basePath; -$modePath = $displayData->modePath; -$modPath = 'mod-path="' . Uri::root() . $modePath . $extJS . '"'; +//$basePath = $displayData->basePath; +//$modePath = $displayData->modePath; +//$modPath = 'mod-path="' . Uri::root() . $modePath . $extJS . '"'; $fskeys = $params->get('fullScreenMod', []); $fskeys[] = $params->get('fullScreen', 'F10'); $fullScreenCombo = implode('-', $fskeys); -$fsCombo = 'fs-combo=' . json_encode($fullScreenCombo); -$option = 'options=\'' . json_encode($options) . '\''; -$mediaVersion = Factory::getDocument()->getMediaVersion(); -$editor = 'editor="' . ltrim(HTMLHelper::_('script', $basePath . 'lib/codemirror' . $extJS, ['version' => 'auto', 'pathOnly' => true]), '/') . '?' . $mediaVersion . '"'; -$addons = 'addons="' . ltrim(HTMLHelper::_('script', $basePath . 'lib/addons' . $extJS, ['version' => 'auto', 'pathOnly' => true]), '/') . '?' . $mediaVersion . '"'; +$fsCombo = ' fs-combo=' . $this->escape($fullScreenCombo); +$option = ' options="' . $this->escape(json_encode($options)) . '"'; +$mediaVersion = Factory::getApplication()->getDocument()->getMediaVersion(); +//$editor = 'editor="' . ltrim(HTMLHelper::_('script', $basePath . 'lib/codemirror' . $extJS, ['version' => 'auto', 'pathOnly' => true]), '/') . '?' . $mediaVersion . '"'; +//$addons = 'addons="' . ltrim(HTMLHelper::_('script', $basePath . 'lib/addons' . $extJS, ['version' => 'auto', 'pathOnly' => true]), '/') . '?' . $mediaVersion . '"'; // Remove the fullscreen message and option if readonly not null. if (isset($options->readOnly)) { $fsCombo = ''; } -Factory::getDocument()->getWebAssetManager() - ->registerAndUseStyle('codemirror.lib.main', $basePath . 'lib/codemirror.css') - ->registerAndUseStyle('codemirror.lib.addons', $basePath . 'lib/addons.css', [], [], ['codemirror.lib.main']) - ->registerAndUseScript( - 'webcomponent.editor-codemirror', - 'plg_editors_codemirror/joomla-editor-codemirror.min.js', - [], - ['type' => 'module'], - ['wcpolyfill'] - ); +/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ +$wa = Factory::getApplication()->getDocument()->getWebAssetManager(); +$wa->getRegistry()->addExtensionRegistryFile('plg_editors_codemirror'); +$wa->useStyle('plg_editors_codemirror') + ->useScript('webcomponent.editor-codemirror'); + ?> -> +> ', $content, ''; ?>

diff --git a/plugins/editors/codemirror/layouts/editors/codemirror/styles.php b/plugins/editors/codemirror/layouts/editors/codemirror/styles.php deleted file mode 100644 index 2f272e2e51f21..0000000000000 --- a/plugins/editors/codemirror/layouts/editors/codemirror/styles.php +++ /dev/null @@ -1,53 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -// No direct access -defined('_JEXEC') or die; - -use Joomla\CMS\Factory; - -$params = $displayData->params; -$fontFamily = $displayData->fontFamily ?? 'monospace'; -$fontSize = $params->get('fontSize', 13) . 'px;'; -$lineHeight = $params->get('lineHeight', 1.2) . 'em;'; - -// Set the active line color. -$color = $params->get('activeLineColor', '#a4c2eb'); -$r = hexdec($color[1] . $color[2]); -$g = hexdec($color[3] . $color[4]); -$b = hexdec($color[5] . $color[6]); -$activeLineColor = 'rgba(' . $r . ', ' . $g . ', ' . $b . ', .5)'; - -// Set the color for matched tags. -$color = $params->get('highlightMatchColor', '#fa542f'); -$r = hexdec($color[1] . $color[2]); -$g = hexdec($color[3] . $color[4]); -$b = hexdec($color[5] . $color[6]); -$highlightMatchColor = 'rgba(' . $r . ', ' . $g . ', ' . $b . ', .5)'; - -/** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ -$wa = Factory::getApplication()->getDocument()->getWebAssetManager(); -$wa->registerAndUseStyle('plg_editors_codemirror', 'plg_editors_codemirror/codemirror.css'); -$wa->addInlineStyle( - <<getApplication()->getDocument(); - - // Codemirror shall have its own group of plugins to modify and extend its behavior - PluginHelper::importPlugin('editors_codemirror'); - - // At this point, params can be modified by a plugin before going to the layout renderer. - $this->getApplication()->triggerEvent('onCodeMirrorBeforeInit', [&$this->params, &$this->basePath, &$this->modePath]); - - $displayData = (object) ['params' => $this->params]; - $font = $this->params->get('fontFamily', '0'); - $fontInfo = $this->getFontInfo($font); - - if (isset($fontInfo)) { - if (isset($fontInfo->url)) { - $doc->addStyleSheet($fontInfo->url); - } - - if (isset($fontInfo->css)) { - $displayData->fontFamily = $fontInfo->css . '!important'; - } - } - - // We need to do output buffering here because layouts may actually 'echo' things which we do not want. - ob_start(); - LayoutHelper::render('editors.codemirror.styles', $displayData, JPATH_PLUGINS . '/editors/codemirror/layouts'); - ob_end_clean(); - - $this->getApplication()->triggerEvent('onCodeMirrorAfterInit', [&$this->params, &$this->basePath, &$this->modePath]); - } - /** * Display the editor area. * @@ -141,15 +61,13 @@ public function onDisplay( // True if a CodeMirror already has autofocus. Prevent multiple autofocuses. static $autofocused; + $this->loadLanguage(); + $id = empty($id) ? $name : $id; // Must pass the field id to the buttons in this editor. $buttons = $this->displayButtons($id, $buttons, $asset, $author); - // Only add "px" to width and height if they are not given as a percentage. - $width .= is_numeric($width) ? 'px' : ''; - $height .= is_numeric($height) ? 'px' : ''; - // Options for the CodeMirror constructor. $options = new stdClass(); $keyMapUrl = ''; @@ -200,7 +118,7 @@ public function onDisplay( ? $params['syntax'] : $this->params->get('syntax', 'html'); $options->mode = $this->modeAlias[$syntax] ?? $syntax; - +/* // Load the theme if specified. if ($theme = $this->params->get('theme')) { $options->theme = $theme; @@ -208,7 +126,7 @@ public function onDisplay( $this->getApplication()->getDocument()->getWebAssetManager() ->registerAndUseStyle('codemirror.theme', $this->basePath . 'theme/' . $theme . '.css'); } - +*/ // Special options for tagged modes (xml/html). if (in_array($options->mode, ['xml', 'html', 'php'])) { // Autogenerate closing tags (html/xml only). @@ -253,20 +171,9 @@ public function onDisplay( 'rows' => $row, 'content' => $content, 'buttons' => $buttons, - 'basePath' => $this->basePath, - 'modePath' => $this->modePath, ]; - // At this point, displayData can be modified by a plugin before going to the layout renderer. - $results = $this->getApplication()->triggerEvent('onCodeMirrorBeforeDisplay', [&$displayData]); - - $results[] = LayoutHelper::render('editors.codemirror.element', $displayData, JPATH_PLUGINS . '/editors/codemirror/layouts'); - - foreach ($this->getApplication()->triggerEvent('onCodeMirrorAfterDisplay', [&$displayData]) as $result) { - $results[] = $result; - } - - return implode("\n", $results); + return LayoutHelper::render('editors.codemirror.element', $displayData, JPATH_PLUGINS . '/editors/codemirror/layouts'); } /** From 28c2a29d09dc5fd7ba58f21d9a145b05c5bf60ae Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 26 Jun 2023 17:36:02 +0300 Subject: [PATCH 09/53] Codemirror plugin --- .../javascript/build-codemirror.es6.js | 251 +++++++----------- .../plg_editors_codemirror/css/codemirror.css | 42 +-- .../js/codemirror-base.es6.js | 81 ++++++ .../js/codemirror-base.js | 8 - .../js/joomla-editor-codemirror.w-c.es6.js | 183 ++++--------- .../layouts/editors/codemirror/element.php | 16 +- .../codemirror/src/Extension/Codemirror.php | 20 +- 7 files changed, 259 insertions(+), 342 deletions(-) create mode 100644 build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js delete mode 100644 build/media_source/plg_editors_codemirror/js/codemirror-base.js diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 93b10b77a02c3..e4625ed48feab 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -1,164 +1,103 @@ /** - * Build codemirror modules + * @copyright (C) 2023 Open Source Matters, Inc. + * @license GNU General Public License version 2 or later; see LICENSE.txt */ -/* eslint-disable import/no-extraneous-dependencies, global-require, import/no-dynamic-require */ -const { - existsSync, readFileSync, writeFile, readdirSync, -} = require('fs-extra'); -const cliProgress = require('cli-progress'); -const rollup = require('rollup'); -const { nodeResolve } = require('@rollup/plugin-node-resolve'); -const replace = require('@rollup/plugin-replace'); -const { minify } = require('terser'); -const { resolvePackageFile } = require('../init/common/resolve-package-file'); - -// Find a list of modules for given scope, eg all sub @codemirror/... -const retrieveListOfChildModules = (scope) => { - const cmModules = []; - - // Get @codemirror module roots - const roots = []; - module.paths.forEach((path) => { - const fullPath = `${path}/${scope}`; - if (existsSync(fullPath)) { - roots.push(fullPath); - } - }); - - // List of modules - roots.forEach((rootPath) => { - readdirSync(rootPath).forEach((subModule) => { - cmModules.push(`${scope}/${subModule}`); - }); - }); - - return cmModules; -}; - -// Build the module -const buildModule = async (module, externalModules, destFile) => { - const build = await rollup.rollup({ - input: module, - external: externalModules || [], - plugins: [ - nodeResolve(), - replace({ - preventAssignment: true, - 'process.env.NODE_ENV': '"production"', - }), - ], - }); - - await build.write({ - format: 'es', - sourcemap: false, - file: destFile, - }); - await build.close(); -}; - -// Minify a js file -const createMinified = async (filePath) => { - const destFile = filePath.replace('.js', '.min.js'); - // Read source - const src = readFileSync(filePath, { encoding: 'utf8' }); - // Minify - const min = await minify(src, { sourceMap: false, format: { comments: false } }); - // Save result - await writeFile(destFile, min.code, { encoding: 'utf8', mode: 0o644 }); -}; - -// Update joomla.asset.json for codemirror -const updateAssetRegistry = async (modules, externalModules) => { - const srcPath = 'build/media_source/plg_editors_codemirror/joomla.asset.json'; - const destPath = 'media/plg_editors_codemirror/joomla.asset.json'; - - // Get base JSON and update - const registry = JSON.parse(readFileSync(srcPath, { encoding: 'utf8' })); - - // Add dependencies to base codemirror asset - registry.assets.forEach((asset) => { - if (asset.name === 'codemirror' && asset.type === 'script') { - asset.dependencies = externalModules; - } - }); - - // Create asset for each module - modules.forEach((module) => { - const packageName = module.package; - const modulePathJson = resolvePackageFile(`${packageName}/package.json`); - const moduleOptions = require(modulePathJson); - const asset = { - type: 'script', - name: module.package, - uri: module.uri.replace('.js', '.min.js'), - importmap: true, - version: moduleOptions.version, - }; - - registry.assets.push(asset); +/** + * Based on https://github.com/codemirror/basic-setup + */ +import { + EditorView, + lineNumbers, + highlightActiveLineGutter, + highlightSpecialChars, + drawSelection, + dropCursor, + rectangularSelection, + crosshairCursor, + highlightActiveLine, + keymap, +} from '@codemirror/view'; +import { EditorState } from '@codemirror/state'; +import { + foldGutter, + indentOnInput, + syntaxHighlighting, + defaultHighlightStyle, + bracketMatching, + foldKeymap, +} from '@codemirror/language'; +import { history, defaultKeymap, historyKeymap } from '@codemirror/commands'; +import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'; +import { + closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap, +} from '@codemirror/autocomplete'; +import { lintKeymap } from '@codemirror/lint'; + +const basicSetup = (() => [ + lineNumbers(), + highlightActiveLineGutter(), + highlightSpecialChars(), + history(), + foldGutter(), + drawSelection(), + dropCursor(), + EditorState.allowMultipleSelections.of(true), + indentOnInput(), + syntaxHighlighting(defaultHighlightStyle, { fallback: true }), + bracketMatching(), + closeBrackets(), + autocompletion(), + rectangularSelection(), + crosshairCursor(), + highlightActiveLine(), + highlightSelectionMatches(), + keymap.of([ + ...closeBracketsKeymap, + ...defaultKeymap, + ...searchKeymap, + ...historyKeymap, + ...foldKeymap, + ...completionKeymap, + ...lintKeymap, + ]), +])(); + +const minimalSetup = (() => [ + highlightSpecialChars(), + history(), + drawSelection(), + syntaxHighlighting(defaultHighlightStyle, { fallback: true }), + keymap.of([ + ...defaultKeymap, + ...historyKeymap, + ]) +])(); + +function createFromTextarea(textarea, options) { + console.log(options); + + const view = new EditorView({ + doc: textarea.value, + extensions: [minimalSetup], }); - - // Write assets registry - await writeFile( - destPath, - JSON.stringify(registry, null, 2), - { encoding: 'utf8', mode: 0o644 }, - ); -}; - -module.exports.compileCodemirror = async () => { - // eslint-disable-next-line no-console - console.log('Building Codemirror Components...'); - - const cmModules = retrieveListOfChildModules('@codemirror'); - const lModules = retrieveListOfChildModules('@lezer'); - const externalModules = [...cmModules, ...lModules]; - const destBasePath = 'media/vendor/codemirror/js'; - const assets = []; - const tasks = []; - - const progressBar = new cliProgress.SingleBar({ - stopOnComplete: true, - format: '{bar} {percentage}% | {value}/{total} files done', - }, cliProgress.Presets.shades_classic); - const totalSteps = (cmModules.length + lModules.length) * 2; - progressBar.start(totalSteps, 0); - - // Prepare @codemirror modules - cmModules.forEach((module) => { - const destFile = `${module.replace('@codemirror/', 'codemirror-')}.js`; - const destPath = `${destBasePath}/${destFile}`; - assets.push({ package: module, uri: destPath }); - - const task = buildModule(module, externalModules, destPath).then(() => { - progressBar.increment(); - return createMinified(destPath).then(() => { - progressBar.increment(); - }); + textarea.parentNode.insertBefore(view.dom, textarea); + textarea.style.display = 'none'; + if (textarea.form) { + textarea.form.addEventListener('submit', () => { + textarea.value = view.state.doc.toString(); }); - tasks.push(task); - }); + } - // Prepare @lezer modules which @codemirror depends on - lModules.forEach((module) => { - const destFile = `${module.replace('@lezer/', 'lezer-')}.js`; - const destPath = `${destBasePath}/${destFile}`; - assets.push({ package: module, uri: destPath }); + // Set up sizing + if (options.width) { + view.dom.style.width = options.width; + } + if (options.height) { + view.dom.style.minHeight = options.height; + } - const task2 = buildModule(module, externalModules, destPath).then(() => { - progressBar.increment(); - return createMinified(destPath).then(() => { - progressBar.increment(); - }); - }); - tasks.push(task2); - }); - // console.log('compileCodemirror', cmModules, lModules, tasks); + return view; +} - return Promise.all(tasks).then(() => { - progressBar.stop(); - return updateAssetRegistry(assets, externalModules); - }); -}; +export { basicSetup, minimalSetup, createFromTextarea }; diff --git a/build/media_source/plg_editors_codemirror/css/codemirror.css b/build/media_source/plg_editors_codemirror/css/codemirror.css index 80be033806a53..8772f94d91b01 100644 --- a/build/media_source/plg_editors_codemirror/css/codemirror.css +++ b/build/media_source/plg_editors_codemirror/css/codemirror.css @@ -3,42 +3,16 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -.CodeMirror { - margin-bottom: 15px; - border: 1px solid #ccc; -} - -/* In order to hide the Joomla menu */ -.CodeMirror-fullscreen { - z-index: 1040; +joomla-editor-codemirror { + display: block; } -/* Make the fold marker a little more visible/nice */ -.CodeMirror-foldmarker { - background: rgb(255,128,0); - background: rgba(255,128,0,.5); - box-shadow: inset 0 0 2px rgba(255,255,255,.5); - font-family: serif; - font-size: 90%; - border-radius: 1em; - padding: 0 1em; - vertical-align: middle; - color: white; - text-shadow: none; +.cm-editor { + margin-bottom: 16px; + border: 1px solid #ccc; } -.CodeMirror-foldgutter, -.CodeMirror-markergutter { - width: 1.2em; - text-align: center; -} -.CodeMirror-markergutter { - cursor: pointer; -} -.CodeMirror-markergutter-mark { - cursor: pointer; - text-align: center; -} -.CodeMirror-markergutter-mark:after { - content: "\25CF"; +.cm-editor .cm-scroller { + min-height: 350px; + overflow: auto; } diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js new file mode 100644 index 0000000000000..2edf36154610a --- /dev/null +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -0,0 +1,81 @@ +/** + * @copyright (C) 2023 Open Source Matters, Inc. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +/** + * Based on https://github.com/codemirror/basic-setup + */ +import { + EditorView, + lineNumbers, + highlightActiveLineGutter, + highlightSpecialChars, + drawSelection, + dropCursor, + rectangularSelection, + crosshairCursor, + highlightActiveLine, + keymap, +} from '@codemirror/view'; +import { EditorState } from '@codemirror/state'; +import { + foldGutter, + indentOnInput, + syntaxHighlighting, + defaultHighlightStyle, + bracketMatching, + foldKeymap, +} from '@codemirror/language'; +import { history, defaultKeymap, historyKeymap } from '@codemirror/commands'; +import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'; +import { + closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap, +} from '@codemirror/autocomplete'; +import { lintKeymap } from '@codemirror/lint'; + +const basicSetup = (() => [ + lineNumbers(), + highlightActiveLineGutter(), + highlightSpecialChars(), + history(), + foldGutter(), + drawSelection(), + dropCursor(), + EditorState.allowMultipleSelections.of(true), + indentOnInput(), + syntaxHighlighting(defaultHighlightStyle, { fallback: true }), + bracketMatching(), + closeBrackets(), + autocompletion(), + rectangularSelection(), + crosshairCursor(), + highlightActiveLine(), + highlightSelectionMatches(), + keymap.of([ + ...closeBracketsKeymap, + ...defaultKeymap, + ...searchKeymap, + ...historyKeymap, + ...foldKeymap, + ...completionKeymap, + ...lintKeymap, + ]), +])(); + +function createFromTextArea(textarea, extensions) { + const view = new EditorView({ + doc: textarea.value, + extensions: [basicSetup, langHtml(), langXml(), langPhp(), langJs()], + }); + textarea.parentNode.insertBefore(view.dom, textarea); + textarea.style.display = 'none'; + if (textarea.form) { + textarea.form.addEventListener('submit', () => { + textarea.value = view.state.doc.toString(); + }); + } + return view; +} + +export { basicSetup, createFromTextArea }; diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.js deleted file mode 100644 index 8278e25862f71..0000000000000 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @copyright (C) 2023 Open Source Matters, Inc. - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -import { EditorView } from '@codemirror/view'; - -console.log(EditorView); diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index 5ca43dc8b9dc4..dde183729da9e 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -1,141 +1,60 @@ -class CodemirrorEditor extends HTMLElement { - constructor() { - super(); - - this.instance = ''; - this.host = window.location.origin; - this.element = this.querySelector('textarea'); - this.refresh = this.refresh.bind(this); - - // Observer instance to refresh the Editor when it become visible, eg after Tab switching - this.intersectionObserver = new IntersectionObserver((entries) => { - if (entries[0].isIntersecting && this.instance) { - this.instance.refresh(); - } - }, { threshold: 0 }); - } +/** + * @copyright (C) 2023 Open Source Matters, Inc. + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ +// eslint-disable-next-line import/no-unresolved +import { createFromTextarea } from 'codemirror'; - static get observedAttributes() { - return ['options']; - } +class CodemirrorEditor extends HTMLElement { + // constructor() { + // super(); + // + // this.instance = null; + // this.host = window.location.origin; + // this.element = this.querySelector('textarea'); + // + // // Observer instance to refresh the Editor when it become visible, eg after Tab switching + // this.intersectionObserver = new IntersectionObserver((entries) => { + // if (entries[0].isIntersecting && this.instance) { + // this.instance.refresh(); + // } + // }, { threshold: 0 }); + // } + + // static get observedAttributes() { + // return ['options']; + // } get options() { return JSON.parse(this.getAttribute('options')); } - set options(value) { this.setAttribute('options', value); } - - attributeChangedCallback(attr, oldValue, newValue) { - switch (attr) { - case 'options': - if (oldValue && newValue !== oldValue) { - this.refresh(this.element); - } - break; - default: - // Do nothing - } - } - - async connectedCallback() { - const cmPath = this.getAttribute('editor'); - const addonsPath = this.getAttribute('addons'); - - await import(`${this.host}/${cmPath}`); - - if (this.options.keyMapUrl) { - await import(`${this.host}/${this.options.keyMapUrl}`); - } - await import(`${this.host}/${addonsPath}`); - - const that = this; - - // For mode autoloading. - window.CodeMirror.modeURL = this.getAttribute('mod-path'); - - // Fire this function any time an editor is created. - window.CodeMirror.defineInitHook((editor) => { - // Try to set up the mode - const mode = window.CodeMirror.findModeByName(editor.options.mode || '') - || window.CodeMirror.findModeByExtension(editor.options.mode || ''); + // set options(value) { this.setAttribute('options', value); } + // + // attributeChangedCallback(attr, oldValue, newValue) { + // switch (attr) { + // case 'options': + // if (oldValue && newValue !== oldValue) { + // this.refresh(this.element); + // } + // break; + // default: + // // Do nothing + // } + // } + + connectedCallback() { - window.CodeMirror.autoLoadMode(editor, typeof mode === 'object' ? mode.mode : editor.options.mode); - - if (mode && mode.mime) { - // Fix the x-php error - if (['text/x-php', 'application/x-httpd-php', 'application/x-httpd-php-open'].includes(mode.mime)) { - editor.setOption('mode', 'php'); - } else if (mode.mime === 'text/html') { - editor.setOption('mode', mode.mode); - } else { - editor.setOption('mode', mode.mime); - } - } - - const toggleFullScreen = () => { - that.instance.setOption('fullScreen', !that.instance.getOption('fullScreen')); - const header = document.getElementById('subhead'); - if (header) { - const header1 = document.getElementById('header'); - header1.classList.toggle('hidden'); - header.classList.toggle('hidden'); - that.instance.display.wrapper.style.top = `${header.getBoundingClientRect().height}px`; - } - }; - - const closeFullScreen = () => { - that.instance.getOption('fullScreen'); - that.instance.setOption('fullScreen', false); - - if (!that.instance.getOption('fullScreen')) { - const header = document.getElementById('subhead'); - if (header) { - const header1 = document.getElementById('header'); - header.classList.toggle('hidden'); - header1.classList.toggle('hidden'); - that.instance.display.wrapper.style.top = `${header.getBoundingClientRect().height}px`; - } - } - }; - - const map = { - 'Ctrl-Q': toggleFullScreen, - [that.getAttribute('fs-combo')]: toggleFullScreen, - Esc: closeFullScreen, - }; - - editor.addKeyMap(map); - - const makeMarker = () => { - const marker = document.createElement('div'); - marker.className = 'CodeMirror-markergutter-mark'; - - return marker; - }; - - // Handle gutter clicks (place or remove a marker). - editor.on('gutterClick', (ed, n, gutter) => { - if (gutter !== 'CodeMirror-markergutter') { - return; - } - - const info = ed.lineInfo(n); - const hasMarker = !!info.gutterMarkers && !!info.gutterMarkers['CodeMirror-markergutter']; - ed.setGutterMarker(n, 'CodeMirror-markergutter', hasMarker ? null : makeMarker()); - }); + // Register Editor + // this.instance = window.CodeMirror.fromTextArea(this.element, this.options); + // this.instance.disable = (disabled) => this.setOption('readOnly', disabled ? 'nocursor' : false); - /* Some browsers do something weird with the fieldset which doesn't - work well with CodeMirror. Fix it. */ - if (that.parentNode.tagName.toLowerCase() === 'fieldset') { - that.parentNode.style.minWidth = 0; - } - }); + const options = this.options; + this.element = this.querySelector('textarea'); + this.instance = createFromTextarea(this.element, this.options); - // Register Editor - this.instance = window.CodeMirror.fromTextArea(this.element, this.options); - this.instance.disable = (disabled) => this.setOption('readOnly', disabled ? 'nocursor' : false); Joomla.editors.instances[this.element.id] = this.instance; // Watch when the element in viewport, and refresh the editor - this.intersectionObserver.observe(this); + // this.intersectionObserver.observe(this); } disconnectedCallback() { @@ -143,12 +62,12 @@ class CodemirrorEditor extends HTMLElement { delete Joomla.editors.instances[this.element.id]; // Remove from observer - this.intersectionObserver.unobserve(this); + // this.intersectionObserver.unobserve(this); } - refresh(element) { - this.instance.fromTextArea(element, this.options); - } + // refresh = (element) => { + // this.instance.fromTextArea(element, this.options); + // } } customElements.define('joomla-editor-codemirror', CodemirrorEditor); diff --git a/plugins/editors/codemirror/layouts/editors/codemirror/element.php b/plugins/editors/codemirror/layouts/editors/codemirror/element.php index 07e3e45369e7f..d80d7551fa671 100644 --- a/plugins/editors/codemirror/layouts/editors/codemirror/element.php +++ b/plugins/editors/codemirror/layouts/editors/codemirror/element.php @@ -36,6 +36,15 @@ $mediaVersion = Factory::getApplication()->getDocument()->getMediaVersion(); //$editor = 'editor="' . ltrim(HTMLHelper::_('script', $basePath . 'lib/codemirror' . $extJS, ['version' => 'auto', 'pathOnly' => true]), '/') . '?' . $mediaVersion . '"'; //$addons = 'addons="' . ltrim(HTMLHelper::_('script', $basePath . 'lib/addons' . $extJS, ['version' => 'auto', 'pathOnly' => true]), '/') . '?' . $mediaVersion . '"'; +$style = ''; + +if ($options->width) { + $style .= 'width:' . $options->width . ';'; +} +if ($options->height) { + $style .= 'height:' . $options->height . ';'; +} + // Remove the fullscreen message and option if readonly not null. if (isset($options->readOnly)) { @@ -47,14 +56,13 @@ $wa->getRegistry()->addExtensionRegistryFile('plg_editors_codemirror'); $wa->useStyle('plg_editors_codemirror') ->useScript('webcomponent.editor-codemirror'); - ?> > -', $content, ''; ?> - +' . $content . ''; ?> +

- +
buttons; ?> diff --git a/plugins/editors/codemirror/src/Extension/Codemirror.php b/plugins/editors/codemirror/src/Extension/Codemirror.php index a637e4bd7edde..8f660b4730627 100644 --- a/plugins/editors/codemirror/src/Extension/Codemirror.php +++ b/plugins/editors/codemirror/src/Extension/Codemirror.php @@ -77,6 +77,10 @@ public function onDisplay( $options->readOnly = 'nocursor'; } + // Only add "px" to width and height if they are not given as a percentage. + $options->width = is_numeric($width) ? $width . 'px' : $width; + $options->height = is_numeric($height) ? $height . 'px' : $height; + // Should we focus on the editor on load? if (!$autofocused) { $options->autofocus = isset($params['autofocus']) ? (bool) $params['autofocus'] : false; @@ -163,14 +167,14 @@ public function onDisplay( $options->keyMapUrl = $keyMapUrl; $displayData = (object) [ - 'options' => $options, - 'params' => $this->params, - 'name' => $name, - 'id' => $id, - 'cols' => $col, - 'rows' => $row, - 'content' => $content, - 'buttons' => $buttons, + 'options' => $options, + 'params' => $this->params, + 'name' => $name, + 'id' => $id, + 'cols' => $col, + 'rows' => $row, + 'content' => $content, + 'buttons' => $buttons, ]; return LayoutHelper::render('editors.codemirror.element', $displayData, JPATH_PLUGINS . '/editors/codemirror/layouts'); From 53a17926d72e451add64a022c0978a8d154dc387 Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 26 Jun 2023 18:25:54 +0300 Subject: [PATCH 10/53] Codemirror plugin --- .../js/codemirror-base.es6.js | 54 +++++++++++++++++-- plugins/editors/codemirror/codemirror.xml | 4 +- .../codemirror/src/Extension/Codemirror.php | 37 +++++-------- 3 files changed, 64 insertions(+), 31 deletions(-) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 2edf36154610a..ffd7b60f0e897 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -61,12 +61,49 @@ const basicSetup = (() => [ ...completionKeymap, ...lintKeymap, ]), -])(); +]); + +const minimalSetup = (() => [ + highlightSpecialChars(), + history(), + drawSelection(), + syntaxHighlighting(defaultHighlightStyle, { fallback: true }), + keymap.of([ + ...defaultKeymap, + ...historyKeymap, + ]) +]); + +const optionsToExtensions = (options) => { + const extensions = []; + + if (options.lineNumbers) { + extensions.push(lineNumbers()); + } + + if (options.lineWrapping) { + extensions.push(EditorView.lineWrapping); + } + + if (options.autoCloseTags) { + // https://discuss.codemirror.net/t/how-to-automatically-close-html-tags-in-codemirror6/3541 + // extensions.push(closeBrackets(), autocompletion()); + } + + if (options.foldGutter) { + extensions.push(foldGutter()); + } + +console.log(extensions); + return extensions; +} + +function createFromTextarea(textarea, options) { + console.log(options); -function createFromTextArea(textarea, extensions) { const view = new EditorView({ doc: textarea.value, - extensions: [basicSetup, langHtml(), langXml(), langPhp(), langJs()], + extensions: [minimalSetup(), optionsToExtensions(options)], }); textarea.parentNode.insertBefore(view.dom, textarea); textarea.style.display = 'none'; @@ -75,7 +112,16 @@ function createFromTextArea(textarea, extensions) { textarea.value = view.state.doc.toString(); }); } + + // Set up sizing + if (options.width) { + view.dom.style.width = options.width; + } + if (options.height) { + view.dom.style.minHeight = options.height; + } + return view; } -export { basicSetup, createFromTextArea }; +export { basicSetup, minimalSetup, createFromTextarea }; diff --git a/plugins/editors/codemirror/codemirror.xml b/plugins/editors/codemirror/codemirror.xml index 318cab41d53e9..9f64430a66276 100644 --- a/plugins/editors/codemirror/codemirror.xml +++ b/plugins/editors/codemirror/codemirror.xml @@ -48,7 +48,7 @@ - + loadLanguage(); $id = empty($id) ? $name : $id; @@ -81,14 +78,9 @@ public function onDisplay( $options->width = is_numeric($width) ? $width . 'px' : $width; $options->height = is_numeric($height) ? $height . 'px' : $height; - // Should we focus on the editor on load? - if (!$autofocused) { - $options->autofocus = isset($params['autofocus']) ? (bool) $params['autofocus'] : false; - $autofocused = $options->autofocus; - } - // Set autorefresh to true - fixes issue when editor is not loaded in a focused tab - $options->autoRefresh = true; - + $options->lineNumbers = (bool) $this->params->get('lineNumbers', 1); + $options->foldGutter = (bool) $this->params->get('codeFolding', 1); + //$options->markerGutter = (bool) $this->params->get('markerGutter', $this->params->get('marker-gutter', 1)); $options->lineWrapping = (bool) $this->params->get('lineWrapping', 1); // Add styling to the active line. @@ -102,20 +94,15 @@ public function onDisplay( ]; } - // Do we use line numbering? - if ($options->lineNumbers = (bool) $this->params->get('lineNumbers', 1)) { - $options->gutters[] = 'CodeMirror-linenumbers'; - } - - // Do we use code folding? - if ($options->foldGutter = (bool) $this->params->get('codeFolding', 1)) { - $options->gutters[] = 'CodeMirror-foldgutter'; - } - - // Do we use a marker gutter? - if ($options->markerGutter = (bool) $this->params->get('markerGutter', $this->params->get('marker-gutter', 1))) { - $options->gutters[] = 'CodeMirror-markergutter'; - } +// if ($options->lineNumbers) { +// $options->gutters[] = 'CodeMirror-linenumbers'; +// } +// if ($options->foldGutter) { +// $options->gutters[] = 'CodeMirror-foldgutter'; +// } +// if ($options->markerGutter) { +// $options->gutters[] = 'CodeMirror-markergutter'; +// } // Load the syntax mode. $syntax = !empty($params['syntax']) From f5ef345c5eba47165f4e342747c74e06855b3fa1 Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 26 Jun 2023 19:39:01 +0300 Subject: [PATCH 11/53] Codemirror plugin --- .../js/codemirror-base.es6.js | 28 ++++++++++---- .../js/joomla-editor-codemirror.w-c.es6.js | 7 ++-- plugins/editors/codemirror/codemirror.xml | 12 +++--- .../codemirror/src/Extension/Codemirror.php | 37 +++++++++---------- 4 files changed, 48 insertions(+), 36 deletions(-) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index ffd7b60f0e897..96834cfc03a5f 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -74,9 +74,17 @@ const minimalSetup = (() => [ ]) ]); -const optionsToExtensions = (options) => { +// Configure extensions depend from given options +const optionsToExtensions = async (options) => { const extensions = []; + let modeMod; + // Load the language for syntax mode + if (options.mode) { + modeMod = await import(`@codemirror/lang-${options.mode}`); + extensions.push(modeMod[options.mode]()) + } +console.log(modeMod); if (options.lineNumbers) { extensions.push(lineNumbers()); } @@ -85,25 +93,31 @@ const optionsToExtensions = (options) => { extensions.push(EditorView.lineWrapping); } - if (options.autoCloseTags) { - // https://discuss.codemirror.net/t/how-to-automatically-close-html-tags-in-codemirror6/3541 - // extensions.push(closeBrackets(), autocompletion()); + if (options.activeLine) { + extensions.push(highlightActiveLineGutter(), highlightActiveLine()); + } + + if (options.highlightSelection) { + extensions.push(highlightSelectionMatches()); + } + + if (options.autoCloseBrackets) { + extensions.push(closeBrackets()); } if (options.foldGutter) { extensions.push(foldGutter()); } -console.log(extensions); return extensions; } -function createFromTextarea(textarea, options) { +async function createFromTextarea(textarea, options) { console.log(options); const view = new EditorView({ doc: textarea.value, - extensions: [minimalSetup(), optionsToExtensions(options)], + extensions: [minimalSetup(), await optionsToExtensions(options)], }); textarea.parentNode.insertBefore(view.dom, textarea); textarea.style.display = 'none'; diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index dde183729da9e..e5ac957d2d0a9 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -41,15 +41,14 @@ class CodemirrorEditor extends HTMLElement { // } // } - connectedCallback() { + async connectedCallback() { // Register Editor // this.instance = window.CodeMirror.fromTextArea(this.element, this.options); // this.instance.disable = (disabled) => this.setOption('readOnly', disabled ? 'nocursor' : false); - const options = this.options; - this.element = this.querySelector('textarea'); - this.instance = createFromTextarea(this.element, this.options); + this.element = this.querySelector('textarea'); + this.instance = await createFromTextarea(this.element, this.options); Joomla.editors.instances[this.element.id] = this.instance; diff --git a/plugins/editors/codemirror/codemirror.xml b/plugins/editors/codemirror/codemirror.xml index 9f64430a66276..e171ac5f96c8d 100644 --- a/plugins/editors/codemirror/codemirror.xml +++ b/plugins/editors/codemirror/codemirror.xml @@ -90,13 +90,13 @@ type="radio" layout="joomla.form.field.radio.switcher" label="PLG_CODEMIRROR_FIELD_SELECTIONMATCHES_LABEL" - default="1" + default="0" filter="integer" > - + + + width = is_numeric($width) ? $width . 'px' : $width; $options->height = is_numeric($height) ? $height . 'px' : $height; - $options->lineNumbers = (bool) $this->params->get('lineNumbers', 1); - $options->foldGutter = (bool) $this->params->get('codeFolding', 1); - //$options->markerGutter = (bool) $this->params->get('markerGutter', $this->params->get('marker-gutter', 1)); - $options->lineWrapping = (bool) $this->params->get('lineWrapping', 1); - - // Add styling to the active line. - $options->styleActiveLine = (bool) $this->params->get('activeLine', 1); + $options->lineNumbers = (bool) $this->params->get('lineNumbers', 1); + $options->foldGutter = (bool) $this->params->get('codeFolding', 1); + //$options->markerGutter = (bool) $this->params->get('markerGutter', $this->params->get('marker-gutter', 1)); + $options->lineWrapping = (bool) $this->params->get('lineWrapping', 1); + $options->activeLine = (bool) $this->params->get('activeLine', 1); + $options->highlightSelection = (bool) $this->params->get('selectionMatches', 0); // Do we highlight selection matches? - if ($this->params->get('selectionMatches', 1)) { - $options->highlightSelectionMatches = [ - 'showToken' => true, - 'annotateScrollbar' => true, - ]; - } - +// if ($this->params->get('selectionMatches', 1)) { +// $options->highlightSelectionMatches = [ +// 'showToken' => true, +// 'annotateScrollbar' => true, +// ]; +// } // if ($options->lineNumbers) { // $options->gutters[] = 'CodeMirror-linenumbers'; // } @@ -105,10 +103,8 @@ public function onDisplay( // } // Load the syntax mode. - $syntax = !empty($params['syntax']) - ? $params['syntax'] - : $this->params->get('syntax', 'html'); - $options->mode = $this->modeAlias[$syntax] ?? $syntax; + $options->mode = !empty($params['syntax']) ? $params['syntax'] : $this->params->get('syntax', 'html'); + //$options->mode = $this->modeAlias[$syntax] ?? $syntax; /* // Load the theme if specified. if ($theme = $this->params->get('theme')) { @@ -118,6 +114,7 @@ public function onDisplay( ->registerAndUseStyle('codemirror.theme', $this->basePath . 'theme/' . $theme . '.css'); } */ +/* // Special options for tagged modes (xml/html). if (in_array($options->mode, ['xml', 'html', 'php'])) { // Autogenerate closing tags (html/xml only). @@ -126,14 +123,14 @@ public function onDisplay( // Highlight the matching tag when the cursor is in a tag (html/xml only). $options->matchTags = (bool) $this->params->get('matchTags', 1); } - +*/ // Special options for non-tagged modes. if (!in_array($options->mode, ['xml', 'html'])) { // Autogenerate closing brackets. $options->autoCloseBrackets = (bool) $this->params->get('autoCloseBrackets', 1); // Highlight the matching bracket. - $options->matchBrackets = (bool) $this->params->get('matchBrackets', 1); + //$options->matchBrackets = (bool) $this->params->get('matchBrackets', 1); } $options->scrollbarStyle = $this->params->get('scrollbarStyle', 'native'); From e4aa390f9aa9810305f5652769c0b06d0284c7bb Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 26 Jun 2023 19:39:53 +0300 Subject: [PATCH 12/53] Codemirror plugin --- .../layouts/editors/codemirror/{element.php => codemirror.php} | 0 plugins/editors/codemirror/src/Extension/Codemirror.php | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename plugins/editors/codemirror/layouts/editors/codemirror/{element.php => codemirror.php} (100%) diff --git a/plugins/editors/codemirror/layouts/editors/codemirror/element.php b/plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php similarity index 100% rename from plugins/editors/codemirror/layouts/editors/codemirror/element.php rename to plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php diff --git a/plugins/editors/codemirror/src/Extension/Codemirror.php b/plugins/editors/codemirror/src/Extension/Codemirror.php index f05743345efe4..aa85bfe689e42 100644 --- a/plugins/editors/codemirror/src/Extension/Codemirror.php +++ b/plugins/editors/codemirror/src/Extension/Codemirror.php @@ -161,7 +161,7 @@ public function onDisplay( 'buttons' => $buttons, ]; - return LayoutHelper::render('editors.codemirror.element', $displayData, JPATH_PLUGINS . '/editors/codemirror/layouts'); + return LayoutHelper::render('editors.codemirror.codemirror', $displayData, JPATH_PLUGINS . '/editors/codemirror/layouts'); } /** From 04da6ab4daa6f0a5a17eb52f8dc9ee010ee514cb Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 26 Jun 2023 19:53:13 +0300 Subject: [PATCH 13/53] Codemirror plugin --- .../codemirror/src/Extension/Codemirror.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/editors/codemirror/src/Extension/Codemirror.php b/plugins/editors/codemirror/src/Extension/Codemirror.php index aa85bfe689e42..54c5485a51e2e 100644 --- a/plugins/editors/codemirror/src/Extension/Codemirror.php +++ b/plugins/editors/codemirror/src/Extension/Codemirror.php @@ -67,7 +67,7 @@ public function onDisplay( // Options for the CodeMirror constructor. $options = new stdClass(); - $keyMapUrl = ''; +// $keyMapUrl = ''; // Is field readonly? if (!empty($params['readonly'])) { @@ -143,12 +143,12 @@ public function onDisplay( $options->keyMap = $this->params->get('vimKeyBinding', 0) ? 'vim' : 'default'; } - if ($options->keyMap !== 'default') { - $keyMapUrl = HTMLHelper::_('script', $this->basePath . 'keymap/' . $options->keyMap . '.min.js', ['relative' => false, 'pathOnly' => true]); - $keyMapUrl .= '?' . $this->getApplication()->getDocument()->getMediaVersion(); - } - - $options->keyMapUrl = $keyMapUrl; +// if ($options->keyMap !== 'default') { +// $keyMapUrl = HTMLHelper::_('script', $this->basePath . 'keymap/' . $options->keyMap . '.min.js', ['relative' => false, 'pathOnly' => true]); +// $keyMapUrl .= '?' . $this->getApplication()->getDocument()->getMediaVersion(); +// } +// +// $options->keyMapUrl = $keyMapUrl; $displayData = (object) [ 'options' => $options, From 5b0b5aa091b2fb89ab12fcbe4373f86000f262b7 Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 26 Jun 2023 20:07:16 +0300 Subject: [PATCH 14/53] Codemirror plugin --- .../editors/codemirror/src/Extension/Codemirror.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/editors/codemirror/src/Extension/Codemirror.php b/plugins/editors/codemirror/src/Extension/Codemirror.php index 54c5485a51e2e..61819827f51a5 100644 --- a/plugins/editors/codemirror/src/Extension/Codemirror.php +++ b/plugins/editors/codemirror/src/Extension/Codemirror.php @@ -133,15 +133,15 @@ public function onDisplay( //$options->matchBrackets = (bool) $this->params->get('matchBrackets', 1); } - $options->scrollbarStyle = $this->params->get('scrollbarStyle', 'native'); +// $options->scrollbarStyle = $this->params->get('scrollbarStyle', 'native'); // KeyMap settings. - $options->keyMap = $this->params->get('keyMap', false); + $options->keyMap = $this->params->get('keyMap', ''); // Support for older settings. - if ($options->keyMap === false) { - $options->keyMap = $this->params->get('vimKeyBinding', 0) ? 'vim' : 'default'; - } +// if ($options->keyMap === false) { +// $options->keyMap = $this->params->get('vimKeyBinding', 0) ? 'vim' : 'default'; +// } // if ($options->keyMap !== 'default') { // $keyMapUrl = HTMLHelper::_('script', $this->basePath . 'keymap/' . $options->keyMap . '.min.js', ['relative' => false, 'pathOnly' => true]); From ca12cf2aae4e79fa93120b3c30ccc50a10eab0f2 Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 11:49:23 +0300 Subject: [PATCH 15/53] Codemirror plugin --- .../js/codemirror-base.es6.js | 34 ++++++++++++------- plugins/editors/codemirror/codemirror.xml | 2 ++ 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 96834cfc03a5f..7d937c5ab8646 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -27,7 +27,9 @@ import { bracketMatching, foldKeymap, } from '@codemirror/language'; -import { history, defaultKeymap, historyKeymap } from '@codemirror/commands'; +import { + history, defaultKeymap, historyKeymap, emacsStyleKeymap, +} from '@codemirror/commands'; import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'; import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap, @@ -68,23 +70,20 @@ const minimalSetup = (() => [ history(), drawSelection(), syntaxHighlighting(defaultHighlightStyle, { fallback: true }), - keymap.of([ - ...defaultKeymap, - ...historyKeymap, - ]) ]); // Configure extensions depend from given options const optionsToExtensions = async (options) => { const extensions = []; - let modeMod; + const q = []; // Load the language for syntax mode if (options.mode) { - modeMod = await import(`@codemirror/lang-${options.mode}`); - extensions.push(modeMod[options.mode]()) + q.push(import(`@codemirror/lang-${options.mode}`).then((modeMod) => { + extensions.push(modeMod[options.mode]()) + })); } -console.log(modeMod); + if (options.lineNumbers) { extensions.push(lineNumbers()); } @@ -109,15 +108,26 @@ console.log(modeMod); extensions.push(foldGutter()); } - return extensions; -} + // Keymaps + switch (options.keyMap) { + case 'emacs': + extensions.push(keymap.of([...emacsStyleKeymap, ...historyKeymap])); + break; + default: + extensions.push(keymap.of([...defaultKeymap, ...searchKeymap, ...historyKeymap])); + break; + } + + return Promise.all(q).then(() => extensions); +}; async function createFromTextarea(textarea, options) { console.log(options); + const extensions = [minimalSetup(), await optionsToExtensions(options)]; const view = new EditorView({ doc: textarea.value, - extensions: [minimalSetup(), await optionsToExtensions(options)], + extensions, }); textarea.parentNode.insertBefore(view.dom, textarea); textarea.style.display = 'none'; diff --git a/plugins/editors/codemirror/codemirror.xml b/plugins/editors/codemirror/codemirror.xml index e171ac5f96c8d..8c197f04b6b30 100644 --- a/plugins/editors/codemirror/codemirror.xml +++ b/plugins/editors/codemirror/codemirror.xml @@ -157,8 +157,10 @@ > + Date: Tue, 27 Jun 2023 11:49:36 +0300 Subject: [PATCH 16/53] Codemirror plugin --- .../plg_editors_codemirror/js/codemirror-base.es6.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 7d937c5ab8646..3fefff4e99eb2 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -80,7 +80,7 @@ const optionsToExtensions = async (options) => { // Load the language for syntax mode if (options.mode) { q.push(import(`@codemirror/lang-${options.mode}`).then((modeMod) => { - extensions.push(modeMod[options.mode]()) + extensions.push(modeMod[options.mode]()); })); } From 2c5c1a8944816b6348d1921dcb043f66c00b4e22 Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 13:31:06 +0300 Subject: [PATCH 17/53] Codemirror plugin --- .../js/codemirror-base.es6.js | 9 ++++- .../js/joomla-editor-codemirror.w-c.es6.js | 39 +++++++++++++++++-- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 3fefff4e99eb2..93b948295a489 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -18,7 +18,7 @@ import { highlightActiveLine, keymap, } from '@codemirror/view'; -import { EditorState } from '@codemirror/state'; +import { EditorState, Compartment } from '@codemirror/state'; import { foldGutter, indentOnInput, @@ -118,6 +118,13 @@ const optionsToExtensions = async (options) => { break; } + // Configurable read only + const readOnly = new Compartment(); + // Set a custom name so later one we can retrieve this Compartment from view.state.config.compartments + // eslint-disable-next-line no-underscore-dangle + readOnly._j_name = 'readOnly'; + extensions.push(readOnly.of(EditorState.readOnly.of(!!options.readOnly))); + return Promise.all(q).then(() => extensions); }; diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index e5ac957d2d0a9..dea22d58071f7 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -4,6 +4,7 @@ */ // eslint-disable-next-line import/no-unresolved import { createFromTextarea } from 'codemirror'; +import { EditorState } from '@codemirror/state'; class CodemirrorEditor extends HTMLElement { // constructor() { @@ -42,15 +43,45 @@ class CodemirrorEditor extends HTMLElement { // } async connectedCallback() { - // Register Editor // this.instance = window.CodeMirror.fromTextArea(this.element, this.options); // this.instance.disable = (disabled) => this.setOption('readOnly', disabled ? 'nocursor' : false); - this.element = this.querySelector('textarea'); - this.instance = await createFromTextarea(this.element, this.options); + this.element = this.querySelector('textarea'); + const editor = await createFromTextarea(this.element, this.options); + this.instance = editor; + +console.log(editor.state); - Joomla.editors.instances[this.element.id] = this.instance; + Joomla.editors.instances[this.element.id] = { + id: () => this.element.id, + element: () => this.element, + getValue: () => editor.state.doc.toString(), + setValue: (text) => { + editor.dispatch({ + changes: { from: 0, to: editor.state.doc.length, insert: text }, + }); + }, + getSelection: () => editor.state.sliceDoc( + editor.state.selection.main.from, + editor.state.selection.main.to, + ), + replaceSelection: (text) => { + const v = editor.state.replaceSelection(text); + editor.dispatch(v); + }, + disable: (disabled) => { + editor.state.config.compartments.forEach((facet, compartment) => { + // eslint-disable-next-line no-underscore-dangle + if (compartment._j_name === 'readOnly') { + editor.dispatch({ + effects: compartment.reconfigure(EditorState.readOnly.of(disabled)), + }); + } + }); + }, + onSave: () => {}, + }; // Watch when the element in viewport, and refresh the editor // this.intersectionObserver.observe(this); From b64eecc5ad03440fbe34219365ad4888b328a4a5 Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 14:11:49 +0300 Subject: [PATCH 18/53] Codemirror plugin --- plugins/editors/codemirror/codemirror.xml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/plugins/editors/codemirror/codemirror.xml b/plugins/editors/codemirror/codemirror.xml index 8c197f04b6b30..736b41d81183a 100644 --- a/plugins/editors/codemirror/codemirror.xml +++ b/plugins/editors/codemirror/codemirror.xml @@ -195,6 +195,27 @@ +
+ +
+ + + + +
+ JOFF - - - + - - diff --git a/plugins/editors/codemirror/fonts.json b/plugins/editors/codemirror/fonts.json deleted file mode 100644 index 45c4c5198ba5e..0000000000000 --- a/plugins/editors/codemirror/fonts.json +++ /dev/null @@ -1,107 +0,0 @@ -{ - "anonymous_pro": { - "name": "Anonymous Pro", - "url": "https://fonts.googleapis.com/css?family=Anonymous+Pro", - "css": "'Anonymous Pro', monospace" - }, - "cousine": { - "name": "Cousine", - "url": "https://fonts.googleapis.com/css?family=Cousine", - "css": "Cousine, monospace" - }, - "cutive_mono": { - "name": "Cutive Mono", - "url": "https://fonts.googleapis.com/css?family=Cutive+Mono", - "css": "'Cutive Mono', monospace" - }, - "droid_sans_mono": { - "name": "Droid Sans Mono", - "url": "https://fonts.googleapis.com/css?family=Droid+Sans+Mono", - "css": "'Droid Sans Mono', monospace" - }, - "fira_mono": { - "name": "Fira Mono", - "url": "https://fonts.googleapis.com/css?family=Fira+Mono", - "css": "'Fira Mono', monospace" - }, - "ibm_plex_mono": { - "name": "IBM Plex Mono", - "url": "https://fonts.googleapis.com/css?family=IBM+Plex+Mono", - "css": "'IBM Plex Mono', monospace;" - }, - "inconsolata": { - "name": "Inconsolata", - "url": "https://fonts.googleapis.com/css?family=Inconsolata", - "css": "Inconsolata, monospace" - }, - "lekton": { - "name": "Lekton", - "url": "https://fonts.googleapis.com/css?family=Lekton", - "css": "Lekton, monospace" - }, - "nanum_gothic_coding": { - "name": "Nanum Gothic Coding", - "url": "https://fonts.googleapis.com/css?family=Nanum+Gothic+Coding", - "css": "'Nanum Gothic Coding', monospace" - }, - "nova_mono": { - "name": "Nova Mono", - "url": "https://fonts.googleapis.com/css?family=Nova+Mono", - "css": "'Nova Mono', monospace" - }, - "overpass_mono": { - "name": "Overpass Mono", - "url": "https://fonts.googleapis.com/css?family=Overpass+Mono", - "css": "'Overpass Mono', monospace" - }, - "oxygen_mono": { - "name": "Oxygen Mono", - "url": "https://fonts.googleapis.com/css?family=Oxygen+Mono", - "css": "'Oxygen Mono', monospace" - }, - "press_start_2p": { - "name": "Press Start 2P", - "url": "https://fonts.googleapis.com/css?family=Press+Start+2P", - "css": "'Press Start 2P', monospace" - }, - "pt_mono": { - "name": "PT Mono", - "url": "https://fonts.googleapis.com/css?family=PT+Mono", - "css": "'PT Mono', monospace" - }, - "roboto_mono": { - "name": "Roboto Mono", - "url": "https://fonts.googleapis.com/css?family=Roboto+Mono", - "css": "'Roboto Mono', monospace" - }, - "rubik_mono_one": { - "name": "Rubik Mono One", - "url": "https://fonts.googleapis.com/css?family=Rubik+Mono+One", - "css": "'Rubik Mono One', monospace" - }, - "share_tech_mono": { - "name": "Share Tech Mono", - "url": "https://fonts.googleapis.com/css?family=Share+Tech+Mono", - "css": "'Share Tech Mono', monospace" - }, - "source_code_pro": { - "name": "Source Code Pro", - "url": "https://fonts.googleapis.com/css?family=Source+Code+Pro", - "css": "'Source Code Pro', monospace" - }, - "space_mono": { - "name": "Space Mono", - "url": "https://fonts.googleapis.com/css?family=Space+Mono", - "css": "'Space Mono', monospace" - }, - "ubuntu_mono": { - "name": "Ubuntu Mono", - "url": "https://fonts.googleapis.com/css?family=Ubuntu+Mono", - "css": "'Ubuntu Mono', monospace" - }, - "vt323": { - "name": "VT323", - "url": "https://fonts.googleapis.com/css?family=VT323", - "css": "'VT323', monospace" - } -} diff --git a/plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php b/plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php index 5ec99a06150a2..6af75e89c1b4a 100644 --- a/plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php +++ b/plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php @@ -12,31 +12,26 @@ defined('_JEXEC') or die; use Joomla\CMS\Factory; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Language\Text; -use Joomla\CMS\Uri\Uri; +use Joomla\Registry\Registry; -$options = $displayData->options; -$params = $displayData->params; -$name = $displayData->name; -$id = $displayData->id; -$cols = $displayData->cols; -$rows = $displayData->rows; -$content = $displayData->content; -$extJS = JDEBUG ? '.js' : '.min.js'; -$modifier = $params->get('fullScreenMod', []) ? implode(' + ', $params->get('fullScreenMod', [])) . ' + ' : ''; -//$basePath = $displayData->basePath; -//$modePath = $displayData->modePath; -//$modPath = 'mod-path="' . Uri::root() . $modePath . $extJS . '"'; -$fskeys = $params->get('fullScreenMod', []); -$fskeys[] = $params->get('fullScreen', 'F10'); -$fullScreenCombo = implode('-', $fskeys); -$fsCombo = ' fs-combo=' . $this->escape($fullScreenCombo); -$option = ' options="' . $this->escape(json_encode($options)) . '"'; -$mediaVersion = Factory::getApplication()->getDocument()->getMediaVersion(); -//$editor = 'editor="' . ltrim(HTMLHelper::_('script', $basePath . 'lib/codemirror' . $extJS, ['version' => 'auto', 'pathOnly' => true]), '/') . '?' . $mediaVersion . '"'; -//$addons = 'addons="' . ltrim(HTMLHelper::_('script', $basePath . 'lib/addons' . $extJS, ['version' => 'auto', 'pathOnly' => true]), '/') . '?' . $mediaVersion . '"'; -$style = ''; +extract($displayData); + +/** + * Layout variables + * + * @var array $options JS options for editor + * @var Registry $params Plugin parameters + * @var string $id The id of the input + * @var string $name The name of the input + * @var integer $cols Textarea cols attribute + * @var integer $rows Textarea rows attribute + * @var string $content The value + * @var string $buttons Editor XTD buttons + */ + +$option = ' options="' . $this->escape(json_encode($options)) . '"'; +$style = ''; if ($options->width) { $style .= 'width:' . $options->width . ';'; @@ -45,9 +40,13 @@ $style .= 'height:' . $options->height . ';'; } -// Remove the fullscreen message and option if readonly not null. -if (isset($options->readOnly)) { - $fsCombo = ''; +// Fullscreen combo +$fsCombo = ''; +if (empty($options->readOnly)) { + $fskeys = $params->get('fullScreenMod', []); + $fskeys[] = $params->get('fullScreen', 'F10'); + $fullScreenCombo = implode('-', $fskeys); + $fsCombo = ' fs-combo=' . $this->escape($fullScreenCombo); } /** @var Joomla\CMS\WebAsset\WebAssetManager $wa */ @@ -63,5 +62,5 @@

-buttons; ?> +
diff --git a/plugins/editors/codemirror/src/Extension/Codemirror.php b/plugins/editors/codemirror/src/Extension/Codemirror.php index cff4352c16fc9..8c9dc6b179274 100644 --- a/plugins/editors/codemirror/src/Extension/Codemirror.php +++ b/plugins/editors/codemirror/src/Extension/Codemirror.php @@ -10,13 +10,10 @@ namespace Joomla\Plugin\Editors\CodeMirror\Extension; -use Joomla\CMS\HTML\HTMLHelper; use Joomla\CMS\Layout\LayoutHelper; use Joomla\CMS\Plugin\CMSPlugin; -use Joomla\CMS\Plugin\PluginHelper; use Joomla\CMS\Uri\Uri; use Joomla\Event\Event; -use stdClass; // phpcs:disable PSR1.Files.SideEffects \defined('_JEXEC') or die; @@ -67,12 +64,11 @@ public function onDisplay( $buttons = $this->displayButtons($id, $buttons, $asset, $author); // Options for the CodeMirror constructor. - $options = new stdClass(); -// $keyMapUrl = ''; + $options = new \stdClass(); // Is field readonly? if (!empty($params['readonly'])) { - $options->readOnly = 'nocursor'; + $options->readOnly = true; } // Only add "px" to width and height if they are not given as a percentage. @@ -81,28 +77,10 @@ public function onDisplay( $options->lineNumbers = (bool) $this->params->get('lineNumbers', 1); $options->foldGutter = (bool) $this->params->get('codeFolding', 1); - //$options->markerGutter = (bool) $this->params->get('markerGutter', $this->params->get('marker-gutter', 1)); $options->lineWrapping = (bool) $this->params->get('lineWrapping', 1); $options->activeLine = (bool) $this->params->get('activeLine', 1); $options->highlightSelection = (bool) $this->params->get('selectionMatches', 0); - // Do we highlight selection matches? -// if ($this->params->get('selectionMatches', 1)) { -// $options->highlightSelectionMatches = [ -// 'showToken' => true, -// 'annotateScrollbar' => true, -// ]; -// } -// if ($options->lineNumbers) { -// $options->gutters[] = 'CodeMirror-linenumbers'; -// } -// if ($options->foldGutter) { -// $options->gutters[] = 'CodeMirror-foldgutter'; -// } -// if ($options->markerGutter) { -// $options->gutters[] = 'CodeMirror-markergutter'; -// } - // Load the syntax mode. $modeAlias = [ 'scss' => 'css', @@ -111,51 +89,16 @@ public function onDisplay( ]; $options->mode = !empty($params['syntax']) ? $params['syntax'] : $this->params->get('syntax', 'html'); $options->mode = $modeAlias[$options->mode] ?? $options->mode; -/* - // Load the theme if specified. - if ($theme = $this->params->get('theme')) { - $options->theme = $theme; - $this->getApplication()->getDocument()->getWebAssetManager() - ->registerAndUseStyle('codemirror.theme', $this->basePath . 'theme/' . $theme . '.css'); - } -*/ -/* - // Special options for tagged modes (xml/html). - if (in_array($options->mode, ['xml', 'html', 'php'])) { - // Autogenerate closing tags (html/xml only). - $options->autoCloseTags = (bool) $this->params->get('autoCloseTags', 1); - - // Highlight the matching tag when the cursor is in a tag (html/xml only). - $options->matchTags = (bool) $this->params->get('matchTags', 1); - } -*/ // Special options for non-tagged modes. if (!in_array($options->mode, ['xml', 'html'])) { // Autogenerate closing brackets. $options->autoCloseBrackets = (bool) $this->params->get('autoCloseBrackets', 1); - - // Highlight the matching bracket. - //$options->matchBrackets = (bool) $this->params->get('matchBrackets', 1); } -// $options->scrollbarStyle = $this->params->get('scrollbarStyle', 'native'); - // KeyMap settings. $options->keyMap = $this->params->get('keyMap', ''); - // Support for older settings. -// if ($options->keyMap === false) { -// $options->keyMap = $this->params->get('vimKeyBinding', 0) ? 'vim' : 'default'; -// } - -// if ($options->keyMap !== 'default') { -// $keyMapUrl = HTMLHelper::_('script', $this->basePath . 'keymap/' . $options->keyMap . '.min.js', ['relative' => false, 'pathOnly' => true]); -// $keyMapUrl .= '?' . $this->getApplication()->getDocument()->getMediaVersion(); -// } -// -// $options->keyMapUrl = $keyMapUrl; - // Check for custom extensions $customExtensions = $this->params->get('customExtensions', []); $options->customExtensions = []; @@ -175,7 +118,7 @@ public function onDisplay( } } - $displayData = (object) [ + $displayData = [ 'options' => $options, 'params' => $this->params, 'name' => $name, @@ -216,22 +159,4 @@ protected function displayButtons($name, $buttons, $asset, $author) return LayoutHelper::render('joomla.editors.buttons', $buttons); } } - - /** - * Gets font info from the json data file - * - * @param string $font A key from the $fonts array. - * - * @return object - */ - protected function getFontInfo($font) - { - static $fonts; - - if (!$fonts) { - $fonts = json_decode(file_get_contents(JPATH_PLUGINS . '/editors/codemirror/fonts.json'), true); - } - - return isset($fonts[$font]) ? (object) $fonts[$font] : null; - } } diff --git a/plugins/editors/codemirror/src/Field/FontsField.php b/plugins/editors/codemirror/src/Field/FontsField.php deleted file mode 100644 index 1f49fd42c2b48..0000000000000 --- a/plugins/editors/codemirror/src/Field/FontsField.php +++ /dev/null @@ -1,56 +0,0 @@ - - * @license GNU General Public License version 2 or later; see LICENSE.txt - */ - -namespace Joomla\Plugin\Editors\CodeMirror\Field; - -use Joomla\CMS\Form\Field\ListField; -use Joomla\CMS\HTML\HTMLHelper; - -// phpcs:disable PSR1.Files.SideEffects -\defined('_JEXEC') or die; -// phpcs:enable PSR1.Files.SideEffects - -/** - * Supports an HTML select list of fonts - * - * @package Joomla.Plugin - * @subpackage Editors.codemirror - * @since 3.4 - */ -class FontsField extends ListField -{ - /** - * The form field type. - * - * @var string - * @since 3.4 - */ - protected $type = 'Fonts'; - - /** - * Method to get the list of fonts field options. - * - * @return array The field option objects. - * - * @since 3.4 - */ - protected function getOptions() - { - $fonts = json_decode(file_get_contents(JPATH_PLUGINS . '/editors/codemirror/fonts.json')); - $options = []; - - foreach ($fonts as $key => $info) { - $options[] = HTMLHelper::_('select.option', $key, $info->name); - } - - // Merge any additional options in the XML definition. - return array_merge(parent::getOptions(), $options); - } -} From 18eaafdec1ad02193f12c5c147ae328a32bb2eae Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 17:37:18 +0300 Subject: [PATCH 29/53] Codemirror plugin cleanup --- .../js/joomla-editor-codemirror.w-c.es6.js | 48 +------------------ 1 file changed, 1 insertion(+), 47 deletions(-) diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index 3061dc7117498..c603b888896ec 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -8,48 +8,12 @@ import { EditorState } from '@codemirror/state'; import { keymap } from "@codemirror/view"; class CodemirrorEditor extends HTMLElement { - // constructor() { - // super(); - // - // this.instance = null; - // this.host = window.location.origin; - // this.element = this.querySelector('textarea'); - // - // // Observer instance to refresh the Editor when it become visible, eg after Tab switching - // this.intersectionObserver = new IntersectionObserver((entries) => { - // if (entries[0].isIntersecting && this.instance) { - // this.instance.refresh(); - // } - // }, { threshold: 0 }); - // } - - // static get observedAttributes() { - // return ['options']; - // } get options() { return JSON.parse(this.getAttribute('options')); } get fsCombo() { return this.getAttribute('fs-combo'); } - // set options(value) { this.setAttribute('options', value); } - // - // attributeChangedCallback(attr, oldValue, newValue) { - // switch (attr) { - // case 'options': - // if (oldValue && newValue !== oldValue) { - // this.refresh(this.element); - // } - // break; - // default: - // // Do nothing - // } - // } - async connectedCallback() { - // Register Editor - // this.instance = window.CodeMirror.fromTextArea(this.element, this.options); - // this.instance.disable = (disabled) => this.setOption('readOnly', disabled ? 'nocursor' : false); - const { options } = this; // Configure full screen feature @@ -63,7 +27,7 @@ class CodemirrorEditor extends HTMLElement { }); } - // Configure editor instance + // Create an editor instance this.element = this.querySelector('textarea'); const editor = await createFromTextarea(this.element, options); this.instance = editor; @@ -98,9 +62,6 @@ class CodemirrorEditor extends HTMLElement { }, onSave: () => {}, }; - - // Watch when the element in viewport, and refresh the editor - // this.intersectionObserver.observe(this); } disconnectedCallback() { @@ -110,9 +71,6 @@ class CodemirrorEditor extends HTMLElement { } // Remove from the Joomla API delete Joomla.editors.instances[this.element.id]; - - // Remove from observer - // this.intersectionObserver.unobserve(this); } toggleFullScreen = () => { @@ -122,10 +80,6 @@ class CodemirrorEditor extends HTMLElement { closeFullScreen = () => { this.classList.remove('fullscreen'); } - - // refresh = (element) => { - // this.instance.fromTextArea(element, this.options); - // } } customElements.define('joomla-editor-codemirror', CodemirrorEditor); From aeb7aa159d8b68d937fbb6910b27bced411f32ba Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 17:42:43 +0300 Subject: [PATCH 30/53] Codemirror plugin cleanup --- .../js/codemirror-base.es6.js | 62 +++++-------------- 1 file changed, 15 insertions(+), 47 deletions(-) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 939acf2482229..681aa0c08872a 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -3,67 +3,26 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ -/** - * Based on https://github.com/codemirror/basic-setup - */ import { EditorView, lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, - dropCursor, - rectangularSelection, - crosshairCursor, highlightActiveLine, keymap, } from '@codemirror/view'; import { EditorState, Compartment } from '@codemirror/state'; import { foldGutter, - indentOnInput, syntaxHighlighting, defaultHighlightStyle, - bracketMatching, - foldKeymap, } from '@codemirror/language'; import { history, defaultKeymap, historyKeymap, emacsStyleKeymap, } from '@codemirror/commands'; import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'; -import { - closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap, -} from '@codemirror/autocomplete'; -import { lintKeymap } from '@codemirror/lint'; - -const basicSetup = (() => [ - lineNumbers(), - highlightActiveLineGutter(), - highlightSpecialChars(), - history(), - foldGutter(), - drawSelection(), - dropCursor(), - EditorState.allowMultipleSelections.of(true), - indentOnInput(), - syntaxHighlighting(defaultHighlightStyle, { fallback: true }), - bracketMatching(), - closeBrackets(), - autocompletion(), - rectangularSelection(), - crosshairCursor(), - highlightActiveLine(), - highlightSelectionMatches(), - keymap.of([ - ...closeBracketsKeymap, - ...defaultKeymap, - ...searchKeymap, - ...historyKeymap, - ...foldKeymap, - ...completionKeymap, - ...lintKeymap, - ]), -]); +import { closeBrackets } from '@codemirror/autocomplete'; const minimalSetup = (() => [ highlightSpecialChars(), @@ -72,7 +31,12 @@ const minimalSetup = (() => [ syntaxHighlighting(defaultHighlightStyle, { fallback: true }), ]); -// Configure extensions depend from given options +/** + * Configure and return list of extensions for given options + * + * @param {Object} options + * @returns {Promise<[]>} + */ const optionsToExtensions = async (options) => { const extensions = []; const q = []; @@ -82,7 +46,6 @@ const optionsToExtensions = async (options) => { q.push(import(`@codemirror/lang-${options.mode}`).then((modeMod) => { extensions.push(modeMod[options.mode]()); }).catch((error) => { - // eslint-disable-next-line no-console console.error(`Cannot creat an extension for "${options.mode}" syntax mode.`, error); })); } @@ -151,9 +114,14 @@ const optionsToExtensions = async (options) => { return Promise.all(q).then(() => extensions); }; +/** + * Create an editor instance for given textarea + * + * @param {HTMLTextAreaElement} textarea + * @param {Object} options + * @returns {Promise} + */ async function createFromTextarea(textarea, options) { - console.log(options); - const extensions = [minimalSetup(), await optionsToExtensions(options)]; const view = new EditorView({ doc: textarea.value, @@ -178,4 +146,4 @@ async function createFromTextarea(textarea, options) { return view; } -export { basicSetup, minimalSetup, createFromTextarea, optionsToExtensions }; +export { minimalSetup, createFromTextarea, optionsToExtensions }; From 7acf2cf5e92cd8241f58b0d875fde413514813a2 Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 17:50:58 +0300 Subject: [PATCH 31/53] Codemirror plugin cleanup lang --- .../language/en-GB/plg_editors_codemirror.ini | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/administrator/language/en-GB/plg_editors_codemirror.ini b/administrator/language/en-GB/plg_editors_codemirror.ini index 97346ce5d42a0..17ef36b6c013a 100644 --- a/administrator/language/en-GB/plg_editors_codemirror.ini +++ b/administrator/language/en-GB/plg_editors_codemirror.ini @@ -3,47 +3,49 @@ ; License GNU General Public License version 2 or later; see LICENSE.txt ; Note : All ini files need to be saved as UTF-8 -PLG_CODEMIRROR_FIELD_ACTIVELINE_COLOR_LABEL="Active Line Colour" -PLG_CODEMIRROR_FIELD_ACTIVELINE_LABEL="Highlight Active Line" PLG_CODEMIRROR_FIELD_AUTOCLOSEBRACKET_LABEL="Bracket Completion" -PLG_CODEMIRROR_FIELD_AUTOCLOSETAGS_LABEL="Tag Completion" PLG_CODEMIRROR_FIELD_CODEFOLDING_LABEL="Code Folding" PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_LABEL="Custom Extensions" PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_METHOD_DESCR="Method name, provided by module for extension initialisation. Or multiple, separated by comma. Eg: bracketMatching (from module @codemirror/language)." PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_METHOD_LABEL="Initialisation method(s)" PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_MODULE_DESCR="Relative path to the module file, eg: media/my-assets/js/my-codemirror-module.js. Or module name, eg: @codemirror/language." PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_MODULE_LABEL="Module file or module name" -PLG_CODEMIRROR_FIELD_FONT_FAMILY_LABEL="Font" -PLG_CODEMIRROR_FIELD_FONT_SIZE_LABEL="Font Size (px)" PLG_CODEMIRROR_FIELD_FULLSCREEN_LABEL="Toggle Fullscreen" PLG_CODEMIRROR_FIELD_FULLSCREEN_MOD_LABEL="Toggle Fullscreen Modifier" -PLG_CODEMIRROR_FIELD_HIGHLIGHT_MATCH_COLOR_LABEL="Matching Tag Colour" PLG_CODEMIRROR_FIELD_KEYMAP_DESC="Make CodeMirror work like other popular editors." PLG_CODEMIRROR_FIELD_KEYMAP_EMACS="Emacs" PLG_CODEMIRROR_FIELD_KEYMAP_LABEL="Key Map" +PLG_CODEMIRROR_FIELD_LINENUMBERS_LABEL="Line Numbers" +PLG_CODEMIRROR_FIELD_LINEWRAPPING_LABEL="Line Wrapping" +PLG_CODEMIRROR_FIELD_SELECTIONMATCHES_LABEL="Highlight Selection Matches" +PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_ALT="Alt" +PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_CMD="Command" +PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_CTRL="Control" +PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_SHIFT="Shift" +PLG_CODEMIRROR_FIELDSET_TOOLBAR_OPTIONS_LABEL="Toolbar Options" +PLG_CODEMIRROR_TOGGLE_FULL_SCREEN="Press %s to toggle Full Screen editing." +PLG_CODEMIRROR_XML_DESCRIPTION="This plugin loads the CodeMirror editor." +PLG_EDITORS_CODEMIRROR="Editor - CodeMirror" + +; Deprecated, will be removed with 6.0 +PLG_CODEMIRROR_FIELDSET_APPEARANCE_OPTIONS_LABEL="Appearance Options" +PLG_CODEMIRROR_FIELD_ACTIVELINE_COLOR_LABEL="Active Line Colour" +PLG_CODEMIRROR_FIELD_ACTIVELINE_LABEL="Highlight Active Line" +PLG_CODEMIRROR_FIELD_AUTOCLOSETAGS_LABEL="Tag Completion" +PLG_CODEMIRROR_FIELD_FONT_FAMILY_LABEL="Font" +PLG_CODEMIRROR_FIELD_FONT_SIZE_LABEL="Font Size (px)" +PLG_CODEMIRROR_FIELD_HIGHLIGHT_MATCH_COLOR_LABEL="Matching Tag Colour" PLG_CODEMIRROR_FIELD_KEYMAP_SUBLIME="Sublime Text" PLG_CODEMIRROR_FIELD_KEYMAP_VIM="Vim" PLG_CODEMIRROR_FIELD_LINE_HEIGHT_LABEL="Line Height (em)" -PLG_CODEMIRROR_FIELD_LINENUMBERS_LABEL="Line Numbers" -PLG_CODEMIRROR_FIELD_LINEWRAPPING_LABEL="Line Wrapping" PLG_CODEMIRROR_FIELD_MARKERGUTTER_LABEL="Gutters" PLG_CODEMIRROR_FIELD_MATCHBRACKETS_LABEL="Match Brackets" PLG_CODEMIRROR_FIELD_MATCHTAGS_LABEL="Match Tags" PLG_CODEMIRROR_FIELD_PREVIEW_LABEL="Preview" -PLG_CODEMIRROR_FIELD_SELECTIONMATCHES_LABEL="Highlight Selection Matches" PLG_CODEMIRROR_FIELD_THEME_LABEL="Theme" PLG_CODEMIRROR_FIELD_VALUE_FONT_FAMILY_DEFAULT="Browser Default" -PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_ALT="Alt" -PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_CMD="Command" -PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_CTRL="Control" -PLG_CODEMIRROR_FIELD_VALUE_FULLSCREEN_MOD_SHIFT="Shift" PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_DEFAULT="Default" PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_LABEL="Scrollbar Style" PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_OVERLAY="Overlay" PLG_CODEMIRROR_FIELD_VALUE_SCROLLBARSTYLE_SIMPLE="Simple" PLG_CODEMIRROR_FIELD_VIM_KEYBINDING_LABEL="Vim Keybinding" -PLG_CODEMIRROR_FIELDSET_APPEARANCE_OPTIONS_LABEL="Appearance Options" -PLG_CODEMIRROR_FIELDSET_TOOLBAR_OPTIONS_LABEL="Toolbar Options" -PLG_CODEMIRROR_TOGGLE_FULL_SCREEN="Press %s to toggle Full Screen editing." -PLG_CODEMIRROR_XML_DESCRIPTION="This plugin loads the CodeMirror editor." -PLG_EDITORS_CODEMIRROR="Editor - CodeMirror" From 9401ad34d13a24db8f97d8d86702d8e3cd4a8f1b Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 18:56:34 +0300 Subject: [PATCH 32/53] Codemirror build --- .../javascript/compile-to-es2017.es6.js | 33 +++++++++++++++++-- .../js/codemirror-base.es6.js | 2 +- .../js/joomla-editor-codemirror.w-c.es6.js | 1 + 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index ca28bb52cccaa..03d9b635c37ba 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -1,4 +1,8 @@ +/* eslint-disable import/no-extraneous-dependencies, global-require, import/no-dynamic-require */ + const { access, writeFile } = require('fs').promises; +const { createReadStream } = require('fs'); +const readline = require('readline'); const { constants } = require('fs'); const Autoprefixer = require('autoprefixer'); const CssNano = require('cssnano'); @@ -50,12 +54,35 @@ const getWcMinifiedCss = async (file) => { module.exports.handleESMFile = async (file) => { const newPath = file.replace(/\.w-c\.es6\.js$/, '').replace(/\.es6\.js$/, '').replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`); const minifiedCss = await getWcMinifiedCss(file); + + // Check the file header for special options + let shouldResolveImports = true; + await new Promise((r) => { + let i = 0; + let closed = false; + const lineReader = readline.createInterface({ input: createReadStream(file) }); + lineReader.on('line', (line) => { + i += 1; + + if (line.indexOf('@build-no-import-resolve') !== -1) { + shouldResolveImports = false; + } + + if (i >= 10 && !closed) { + lineReader.close(); + closed = true; + } + }); + lineReader.on('close', () => { + closed = true; + r(); + }); + }); + const bundle = await rollup.rollup({ input: resolve(file), plugins: [ - nodeResolve({ - preferBuiltins: false, - }), + (shouldResolveImports ? nodeResolve({ preferBuiltins: false }) : null), replace({ preventAssignment: true, CSS_CONTENTS_PLACEHOLDER: minifiedCss, diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 681aa0c08872a..48632f4a1f77e 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -2,7 +2,7 @@ * @copyright (C) 2023 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ - +/* @build-no-import-resolve */ import { EditorView, lineNumbers, diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index c603b888896ec..c8b8f3ff7bcf5 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -2,6 +2,7 @@ * @copyright (C) 2023 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ +/* @build-no-import-resolve */ // eslint-disable-next-line import/no-unresolved import { createFromTextarea } from 'codemirror'; import { EditorState } from '@codemirror/state'; From 1de68ff590f726f5ffa71c4ac72a92cc1fa2e9cb Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 19:10:36 +0300 Subject: [PATCH 33/53] Codemirror build --- .../plg_editors_codemirror/js/codemirror-base.es6.js | 1 + 1 file changed, 1 insertion(+) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 48632f4a1f77e..7756433f32df6 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -46,6 +46,7 @@ const optionsToExtensions = async (options) => { q.push(import(`@codemirror/lang-${options.mode}`).then((modeMod) => { extensions.push(modeMod[options.mode]()); }).catch((error) => { + // eslint-disable-next-line no-console console.error(`Cannot creat an extension for "${options.mode}" syntax mode.`, error); })); } From 597c79c6e3517509184f73a88e3a8f32a148b8a8 Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 19:57:22 +0300 Subject: [PATCH 34/53] Codemirror build --- .../init/exemptions/codemirror.es6.js | 72 ------------------- 1 file changed, 72 deletions(-) delete mode 100644 build/build-modules-js/init/exemptions/codemirror.es6.js diff --git a/build/build-modules-js/init/exemptions/codemirror.es6.js b/build/build-modules-js/init/exemptions/codemirror.es6.js deleted file mode 100644 index 1040c51a51a64..0000000000000 --- a/build/build-modules-js/init/exemptions/codemirror.es6.js +++ /dev/null @@ -1,72 +0,0 @@ -const { - existsSync, readFile, writeFile, mkdir, -} = require('fs-extra'); -const { join } = require('path'); - -const { concatFiles } = require('../common/concat-files.es6.js'); -const { copyAllFiles } = require('../common/copy-all-files.es6.js'); - -const RootPath = process.cwd(); -const xmlVersionStr = /()(.+)(<\/version>)/; - -/** - * Codemirror needs special treatment - */ -module.exports.codeMirror = async (packageName, version) => { - const itemvendorPath = join(RootPath, `media/vendor/${packageName}`); - if (!await existsSync(itemvendorPath)) { - await mkdir(itemvendorPath, { recursive: true, mode: 0o755 }); - await mkdir(join(itemvendorPath, 'addon'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'lib'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'mode'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'keymap'), { mode: 0o755 }); - await mkdir(join(itemvendorPath, 'theme'), { mode: 0o755 }); - } - - await copyAllFiles('addon', 'codemirror', 'addon'); - await copyAllFiles('lib', 'codemirror', 'lib'); - await copyAllFiles('mode', 'codemirror', 'mode'); - await copyAllFiles('keymap', 'codemirror', 'keymap'); - await copyAllFiles('theme', 'codemirror', 'theme'); - - await concatFiles( - [ - 'media/vendor/codemirror/addon/display/fullscreen.js', - 'media/vendor/codemirror/addon/display/panel.js', - 'media/vendor/codemirror/addon/edit/closebrackets.js', - 'media/vendor/codemirror/addon/edit/closetag.js', - 'media/vendor/codemirror/addon/edit/matchbrackets.js', - 'media/vendor/codemirror/addon/edit/matchtags.js', - 'media/vendor/codemirror/addon/fold/brace-fold.js', - 'media/vendor/codemirror/addon/fold/foldcode.js', - 'media/vendor/codemirror/addon/fold/foldgutter.js', - 'media/vendor/codemirror/addon/fold/xml-fold.js', - 'media/vendor/codemirror/addon/mode/loadmode.js', - 'media/vendor/codemirror/addon/mode/multiplex.js', - 'media/vendor/codemirror/addon/scroll/annotatescrollbar.js', - 'media/vendor/codemirror/addon/scroll/simplescrollbars.js', - 'media/vendor/codemirror/addon/search/match-highlighter.js', - 'media/vendor/codemirror/addon/search/matchesonscrollbar.js', - 'media/vendor/codemirror/addon/search/search.js', - 'media/vendor/codemirror/addon/search/searchcursor.js', - 'media/vendor/codemirror/addon/selection/active-line.js', - 'media/vendor/codemirror/mode/meta.js', - ], - 'media/vendor/codemirror/lib/addons.js', - ); - - await concatFiles( - [ - 'media/vendor/codemirror/addon/display/fullscreen.css', - 'media/vendor/codemirror/addon/fold/foldgutter.css', - 'media/vendor/codemirror/addon/scroll/simplescrollbars.css', - 'media/vendor/codemirror/addon/search/matchesonscrollbar.css', - ], - 'media/vendor/codemirror/lib/addons.css', - ); - - // Update the XML file for Codemirror - let codemirrorXml = await readFile(`${RootPath}/plugins/editors/codemirror/codemirror.xml`, { encoding: 'utf8' }); - codemirrorXml = codemirrorXml.replace(xmlVersionStr, `$1${version}$3`); - await writeFile(`${RootPath}/plugins/editors/codemirror/codemirror.xml`, codemirrorXml, { encoding: 'utf8', mode: 0o644 }); -}; From fedb5371f9cc3dd5d5d21d45c72a86a141abb997 Mon Sep 17 00:00:00 2001 From: Fedik Date: Tue, 27 Jun 2023 20:16:20 +0300 Subject: [PATCH 35/53] Codemirror clean --- .../javascript/build-codemirror.es6.js | 1 - .../js/joomla-editor-codemirror.w-c.es6.js | 31 ++++++++++--------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 93b10b77a02c3..0fa355a3fbffa 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -155,7 +155,6 @@ module.exports.compileCodemirror = async () => { }); tasks.push(task2); }); - // console.log('compileCodemirror', cmModules, lModules, tasks); return Promise.all(tasks).then(() => { progressBar.stop(); diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index c8b8f3ff7bcf5..3dce478c8f78b 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -6,9 +6,20 @@ // eslint-disable-next-line import/no-unresolved import { createFromTextarea } from 'codemirror'; import { EditorState } from '@codemirror/state'; -import { keymap } from "@codemirror/view"; +import { keymap } from '@codemirror/view'; class CodemirrorEditor extends HTMLElement { + constructor() { + super(); + + this.toggleFullScreen = () => { + this.classList.toggle('fullscreen'); + }; + + this.closeFullScreen = () => { + this.classList.remove('fullscreen'); + }; + } get options() { return JSON.parse(this.getAttribute('options')); } @@ -20,12 +31,10 @@ class CodemirrorEditor extends HTMLElement { // Configure full screen feature if (this.fsCombo) { options.customExtensions = options.customExtensions || []; - options.customExtensions.push(() => { - return keymap.of([ - {key: this.fsCombo, run: this.toggleFullScreen}, - {key: 'Escape', run: this.closeFullScreen}, - ]); - }); + options.customExtensions.push(() => keymap.of([ + { key: this.fsCombo, run: this.toggleFullScreen }, + { key: 'Escape', run: this.closeFullScreen }, + ])); } // Create an editor instance @@ -73,14 +82,6 @@ class CodemirrorEditor extends HTMLElement { // Remove from the Joomla API delete Joomla.editors.instances[this.element.id]; } - - toggleFullScreen = () => { - this.classList.toggle('fullscreen'); - } - - closeFullScreen = () => { - this.classList.remove('fullscreen'); - } } customElements.define('joomla-editor-codemirror', CodemirrorEditor); From 879af0480806c8e91768920e27910d6739196c94 Mon Sep 17 00:00:00 2001 From: Fedir Zinchuk Date: Tue, 27 Jun 2023 20:16:49 +0300 Subject: [PATCH 36/53] Update build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js Co-authored-by: Brian Teeman --- .../plg_editors_codemirror/js/codemirror-base.es6.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 7756433f32df6..e385c8098b432 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -87,7 +87,7 @@ const optionsToExtensions = async (options) => { // Configurable read only const readOnly = new Compartment(); - // Set a custom name so later one we can retrieve this Compartment from view.state.config.compartments + // Set a custom name so later on we can retrieve this Compartment from view.state.config.compartments // eslint-disable-next-line no-underscore-dangle readOnly._j_name = 'readOnly'; extensions.push(readOnly.of(EditorState.readOnly.of(!!options.readOnly))); From cda4252d14d6f6d30ff38c5ccb1ad0c803008a86 Mon Sep 17 00:00:00 2001 From: Fedir Zinchuk Date: Tue, 27 Jun 2023 20:23:29 +0300 Subject: [PATCH 37/53] Update plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php Co-authored-by: Brian Teeman --- .../codemirror/layouts/editors/codemirror/codemirror.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php b/plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php index 6af75e89c1b4a..2cb2f34430067 100644 --- a/plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php +++ b/plugins/editors/codemirror/layouts/editors/codemirror/codemirror.php @@ -4,7 +4,7 @@ * @package Joomla.Plugin * @subpackage Editors.codemirror * - * @copyright (C) 2015 Open Source Matters, Inc. + * @copyright (C) 2023 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ From e7baf8c8cadd7c31327acb43a5be8ea38c496cce Mon Sep 17 00:00:00 2001 From: Fedik Date: Wed, 28 Jun 2023 11:27:40 +0300 Subject: [PATCH 38/53] Restore default --- plugins/editors/codemirror/codemirror.xml | 2 +- plugins/editors/codemirror/src/Extension/Codemirror.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/editors/codemirror/codemirror.xml b/plugins/editors/codemirror/codemirror.xml index 3d5d1826f4e3a..69214bac8f946 100644 --- a/plugins/editors/codemirror/codemirror.xml +++ b/plugins/editors/codemirror/codemirror.xml @@ -77,7 +77,7 @@ type="radio" layout="joomla.form.field.radio.switcher" label="PLG_CODEMIRROR_FIELD_SELECTIONMATCHES_LABEL" - default="0" + default="1" filter="integer" > diff --git a/plugins/editors/codemirror/src/Extension/Codemirror.php b/plugins/editors/codemirror/src/Extension/Codemirror.php index 8c9dc6b179274..42f5f31e68ddb 100644 --- a/plugins/editors/codemirror/src/Extension/Codemirror.php +++ b/plugins/editors/codemirror/src/Extension/Codemirror.php @@ -79,7 +79,7 @@ public function onDisplay( $options->foldGutter = (bool) $this->params->get('codeFolding', 1); $options->lineWrapping = (bool) $this->params->get('lineWrapping', 1); $options->activeLine = (bool) $this->params->get('activeLine', 1); - $options->highlightSelection = (bool) $this->params->get('selectionMatches', 0); + $options->highlightSelection = (bool) $this->params->get('selectionMatches', 1); // Load the syntax mode. $modeAlias = [ From 44721ad241e53ac91ebde07a659886f4eff06cc5 Mon Sep 17 00:00:00 2001 From: Fedik Date: Wed, 28 Jun 2023 12:00:48 +0300 Subject: [PATCH 39/53] Fullscreen fixes --- .../javascript/compile-to-es2017.es6.js | 2 +- .../js/codemirror-base.es6.js | 2 +- .../js/joomla-editor-codemirror.w-c.es6.js | 11 +++++++++-- .../atum/scss/vendor/_codemirror.scss | 16 +++++++++++++++- 4 files changed, 26 insertions(+), 5 deletions(-) diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index 03d9b635c37ba..dde8b7fa7a87a 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -64,7 +64,7 @@ module.exports.handleESMFile = async (file) => { lineReader.on('line', (line) => { i += 1; - if (line.indexOf('@build-no-import-resolve') !== -1) { + if (line.indexOf('@build-disable-import-resolve') !== -1) { shouldResolveImports = false; } diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index e385c8098b432..1199541a5cbcb 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -2,7 +2,7 @@ * @copyright (C) 2023 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ -/* @build-no-import-resolve */ +/* @build-disable-import-resolve */ import { EditorView, lineNumbers, diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index 3dce478c8f78b..d7fc3108bc624 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -2,7 +2,7 @@ * @copyright (C) 2023 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ -/* @build-no-import-resolve */ +/* @build-disable-import-resolve */ // eslint-disable-next-line import/no-unresolved import { createFromTextarea } from 'codemirror'; import { EditorState } from '@codemirror/state'; @@ -13,11 +13,18 @@ class CodemirrorEditor extends HTMLElement { super(); this.toggleFullScreen = () => { - this.classList.toggle('fullscreen'); + if (!this.classList.contains('fullscreen')) { + this.classList.add('fullscreen'); + document.documentElement.scrollTop = 0; + document.documentElement.style.overflow = 'hidden'; + } else { + this.closeFullScreen(); + } }; this.closeFullScreen = () => { this.classList.remove('fullscreen'); + document.documentElement.style.overflow = ''; }; } diff --git a/build/media_source/templates/administrator/atum/scss/vendor/_codemirror.scss b/build/media_source/templates/administrator/atum/scss/vendor/_codemirror.scss index ca4b3da34d16a..d4e29274c3a86 100644 --- a/build/media_source/templates/administrator/atum/scss/vendor/_codemirror.scss +++ b/build/media_source/templates/administrator/atum/scss/vendor/_codemirror.scss @@ -1,5 +1,19 @@ // Codemirror -.CodeMirror-fullscreen { +joomla-editor-codemirror.fullscreen { top: 133px; + + .cm-editor { + height: calc(90vh - 133px) !important; + } + + @include media-breakpoint-down(sm) { + top: 54px; + z-index: 890; + + .cm-editor { + height: 100vh !important; + } + } } + From 06e28d47a9a7dd47eb943b6186f46b5c37ebf8b0 Mon Sep 17 00:00:00 2001 From: Fedik Date: Thu, 29 Jun 2023 20:04:39 +0300 Subject: [PATCH 40/53] Build: External checker --- .../javascript/compile-to-es2017.es6.js | 44 ++++++++----------- .../js/codemirror-base.es6.js | 13 +++--- .../js/joomla-editor-codemirror.w-c.es6.js | 7 ++- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index dde8b7fa7a87a..bd1a1622808af 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -46,6 +46,22 @@ const getWcMinifiedCss = async (file) => { return ''; }; +// Check for imports with prefix external: +const externalImportChecker = () => { + const prefix = 'external:'; + + return { + name: 'external-import-checker', + resolveId(source) { + if (source.startsWith(prefix)) { + return { id: source.substring(prefix.length), external: true }; + } + + return null; + }, + }; +}; + /** * Compiles es6 files to es5. * @@ -54,35 +70,11 @@ const getWcMinifiedCss = async (file) => { module.exports.handleESMFile = async (file) => { const newPath = file.replace(/\.w-c\.es6\.js$/, '').replace(/\.es6\.js$/, '').replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`); const minifiedCss = await getWcMinifiedCss(file); - - // Check the file header for special options - let shouldResolveImports = true; - await new Promise((r) => { - let i = 0; - let closed = false; - const lineReader = readline.createInterface({ input: createReadStream(file) }); - lineReader.on('line', (line) => { - i += 1; - - if (line.indexOf('@build-disable-import-resolve') !== -1) { - shouldResolveImports = false; - } - - if (i >= 10 && !closed) { - lineReader.close(); - closed = true; - } - }); - lineReader.on('close', () => { - closed = true; - r(); - }); - }); - const bundle = await rollup.rollup({ input: resolve(file), plugins: [ - (shouldResolveImports ? nodeResolve({ preferBuiltins: false }) : null), + externalImportChecker(), + nodeResolve({ preferBuiltins: false }), replace({ preventAssignment: true, CSS_CONTENTS_PLACEHOLDER: minifiedCss, diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 1199541a5cbcb..133fe5b472c47 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -2,7 +2,6 @@ * @copyright (C) 2023 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ -/* @build-disable-import-resolve */ import { EditorView, lineNumbers, @@ -11,18 +10,18 @@ import { drawSelection, highlightActiveLine, keymap, -} from '@codemirror/view'; -import { EditorState, Compartment } from '@codemirror/state'; +} from 'external:@codemirror/view'; +import { EditorState, Compartment } from 'external:@codemirror/state'; import { foldGutter, syntaxHighlighting, defaultHighlightStyle, -} from '@codemirror/language'; +} from 'external:@codemirror/language'; import { history, defaultKeymap, historyKeymap, emacsStyleKeymap, -} from '@codemirror/commands'; -import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'; -import { closeBrackets } from '@codemirror/autocomplete'; +} from 'external:@codemirror/commands'; +import { highlightSelectionMatches, searchKeymap } from 'external:@codemirror/search'; +import { closeBrackets } from 'external:@codemirror/autocomplete'; const minimalSetup = (() => [ highlightSpecialChars(), diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index d7fc3108bc624..81597e80ce478 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -2,11 +2,10 @@ * @copyright (C) 2023 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ -/* @build-disable-import-resolve */ // eslint-disable-next-line import/no-unresolved -import { createFromTextarea } from 'codemirror'; -import { EditorState } from '@codemirror/state'; -import { keymap } from '@codemirror/view'; +import { createFromTextarea } from 'external:codemirror'; +import { EditorState } from 'external:@codemirror/state'; +import { keymap } from 'external:@codemirror/view'; class CodemirrorEditor extends HTMLElement { constructor() { From 96b3a715aff3a5ae2f777eeca42ddd31b294a85c Mon Sep 17 00:00:00 2001 From: Fedik Date: Thu, 29 Jun 2023 20:21:26 +0300 Subject: [PATCH 41/53] Build: External checker 2 --- .../javascript/compile-to-es2017.es6.js | 14 ++++++++++---- .../js/codemirror-base.es6.js | 12 ++++++------ .../js/joomla-editor-codemirror.w-c.es6.js | 6 +++--- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index bd1a1622808af..cf651aac1381a 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -46,15 +46,21 @@ const getWcMinifiedCss = async (file) => { return ''; }; -// Check for imports with prefix external: +// Check for external imports with by specific prefixes const externalImportChecker = () => { - const prefix = 'external:'; + // Module with these scopes works natively, and therefore they should be ignored by resolver + const prefixes = [ + 'codemirror', + '@codemirror/', + '@lezer/', + ]; + const regexp = new RegExp(`^${prefixes.join('|^')}`); return { name: 'external-import-checker', resolveId(source) { - if (source.startsWith(prefix)) { - return { id: source.substring(prefix.length), external: true }; + if (regexp.test(source)) { + return { id: source, external: true }; } return null; diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js index 133fe5b472c47..8e3aa97f66804 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js @@ -10,18 +10,18 @@ import { drawSelection, highlightActiveLine, keymap, -} from 'external:@codemirror/view'; -import { EditorState, Compartment } from 'external:@codemirror/state'; +} from '@codemirror/view'; +import { EditorState, Compartment } from '@codemirror/state'; import { foldGutter, syntaxHighlighting, defaultHighlightStyle, -} from 'external:@codemirror/language'; +} from '@codemirror/language'; import { history, defaultKeymap, historyKeymap, emacsStyleKeymap, -} from 'external:@codemirror/commands'; -import { highlightSelectionMatches, searchKeymap } from 'external:@codemirror/search'; -import { closeBrackets } from 'external:@codemirror/autocomplete'; +} from '@codemirror/commands'; +import { highlightSelectionMatches, searchKeymap } from '@codemirror/search'; +import { closeBrackets } from '@codemirror/autocomplete'; const minimalSetup = (() => [ highlightSpecialChars(), diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index 81597e80ce478..7cd25c4a376cd 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -3,9 +3,9 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ // eslint-disable-next-line import/no-unresolved -import { createFromTextarea } from 'external:codemirror'; -import { EditorState } from 'external:@codemirror/state'; -import { keymap } from 'external:@codemirror/view'; +import { createFromTextarea } from 'codemirror'; +import { EditorState } from '@codemirror/state'; +import { keymap } from '@codemirror/view'; class CodemirrorEditor extends HTMLElement { constructor() { From ffecaa4c26ba19025079cd3f0e66d627dcc173e9 Mon Sep 17 00:00:00 2001 From: Fedik Date: Thu, 29 Jun 2023 20:27:22 +0300 Subject: [PATCH 42/53] Build: External checker 2 --- build/build-modules-js/javascript/compile-to-es2017.es6.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index cf651aac1381a..22cc6d2b738a0 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -46,7 +46,7 @@ const getWcMinifiedCss = async (file) => { return ''; }; -// Check for external imports with by specific prefixes +// Check for external imports by specific prefixes const externalImportChecker = () => { // Module with these scopes works natively, and therefore they should be ignored by resolver const prefixes = [ From 3df5ccfab366ff484027149c94399746e951537f Mon Sep 17 00:00:00 2001 From: Fedik Date: Fri, 30 Jun 2023 11:43:24 +0300 Subject: [PATCH 43/53] jscs --- build/build-modules-js/javascript/compile-to-es2017.es6.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index 22cc6d2b738a0..3a51f03bb98e1 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -1,8 +1,6 @@ /* eslint-disable import/no-extraneous-dependencies, global-require, import/no-dynamic-require */ const { access, writeFile } = require('fs').promises; -const { createReadStream } = require('fs'); -const readline = require('readline'); const { constants } = require('fs'); const Autoprefixer = require('autoprefixer'); const CssNano = require('cssnano'); From 7f4b5ec95d11868ba29157e2899a531ebdfad907 Mon Sep 17 00:00:00 2001 From: Fedik Date: Sat, 1 Jul 2023 10:56:33 +0300 Subject: [PATCH 44/53] Build collectExternals --- .../init/common/resolve-package-file.js | 19 ------- .../init/common/resolve-package.es6.js | 49 +++++++++++++++++++ .../init/localise-packages.es6.js | 2 +- .../javascript/build-codemirror.es6.js | 29 ++--------- .../javascript/compile-to-es2017.es6.js | 44 +++++++++-------- .../plg_editors_codemirror/joomla.asset.json | 2 +- ...demirror-base.es6.js => codemirror.es6.js} | 0 7 files changed, 77 insertions(+), 68 deletions(-) delete mode 100644 build/build-modules-js/init/common/resolve-package-file.js create mode 100644 build/build-modules-js/init/common/resolve-package.es6.js rename build/media_source/plg_editors_codemirror/js/{codemirror-base.es6.js => codemirror.es6.js} (100%) diff --git a/build/build-modules-js/init/common/resolve-package-file.js b/build/build-modules-js/init/common/resolve-package-file.js deleted file mode 100644 index 07449b87ebf2b..0000000000000 --- a/build/build-modules-js/init/common/resolve-package-file.js +++ /dev/null @@ -1,19 +0,0 @@ -const { existsSync } = require('fs-extra'); -/** - * Find full path for package file. - * Replacement for require.resolve(), as it is broken for packages with "exports" property. - * - * @param {string} relativePath Relative path to the file to resolve, in format packageName/file-name.js - * @returns {string|boolean} - */ -module.exports.resolvePackageFile = (relativePath) => { - for (let i = 0, l = module.paths.length; i < l; i += 1) { - const path = module.paths[i]; - const fullPath = `${path}/${relativePath}`; - if (existsSync(fullPath)) { - return fullPath; - } - } - - return false; -}; diff --git a/build/build-modules-js/init/common/resolve-package.es6.js b/build/build-modules-js/init/common/resolve-package.es6.js new file mode 100644 index 0000000000000..949841960ca96 --- /dev/null +++ b/build/build-modules-js/init/common/resolve-package.es6.js @@ -0,0 +1,49 @@ +const { existsSync, readdirSync } = require('fs-extra'); + +/** + * Find full path for package file. + * Replacement for require.resolve(), as it is broken for packages with "exports" property. + * + * @param {string} relativePath Relative path to the file to resolve, in format packageName/file-name.js + * @returns {string|boolean} + */ +module.exports.resolvePackageFile = (relativePath) => { + for (let i = 0, l = module.paths.length; i < l; i += 1) { + const path = module.paths[i]; + const fullPath = `${path}/${relativePath}`; + if (existsSync(fullPath)) { + return fullPath; + } + } + + return false; +}; + +/** + * Find a list of modules under given scope, + * eg: @foobar will look for all submodules @foobar/foo, @foobar/bar + * + * @param scope + * @returns {[]} + */ +module.exports.getPackagesUnderScope = (scope) => { + const cmModules = []; + + // Get @codemirror module roots + const roots = []; + module.paths.forEach((path) => { + const fullPath = `${path}/${scope}`; + if (existsSync(fullPath)) { + roots.push(fullPath); + } + }); + + // List of modules + roots.forEach((rootPath) => { + readdirSync(rootPath).forEach((subModule) => { + cmModules.push(`${scope}/${subModule}`); + }); + }); + + return cmModules; +}; diff --git a/build/build-modules-js/init/localise-packages.es6.js b/build/build-modules-js/init/localise-packages.es6.js index b26bf6d7901fb..e72229a3a52e1 100644 --- a/build/build-modules-js/init/localise-packages.es6.js +++ b/build/build-modules-js/init/localise-packages.es6.js @@ -3,7 +3,7 @@ const { } = require('fs-extra'); const { dirname, join } = require('path'); const { tinyMCE } = require('./exemptions/tinymce.es6.js'); -const { resolvePackageFile } = require('./common/resolve-package-file'); +const { resolvePackageFile } = require('./common/resolve-package.es6.js'); const RootPath = process.cwd(); diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 0fa355a3fbffa..4c0e2eaf6177c 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -11,30 +11,7 @@ const rollup = require('rollup'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); const replace = require('@rollup/plugin-replace'); const { minify } = require('terser'); -const { resolvePackageFile } = require('../init/common/resolve-package-file'); - -// Find a list of modules for given scope, eg all sub @codemirror/... -const retrieveListOfChildModules = (scope) => { - const cmModules = []; - - // Get @codemirror module roots - const roots = []; - module.paths.forEach((path) => { - const fullPath = `${path}/${scope}`; - if (existsSync(fullPath)) { - roots.push(fullPath); - } - }); - - // List of modules - roots.forEach((rootPath) => { - readdirSync(rootPath).forEach((subModule) => { - cmModules.push(`${scope}/${subModule}`); - }); - }); - - return cmModules; -}; +const { resolvePackageFile, getPackagesUnderScope } = require('../init/common/resolve-package.es6.js'); // Build the module const buildModule = async (module, externalModules, destFile) => { @@ -112,8 +89,8 @@ module.exports.compileCodemirror = async () => { // eslint-disable-next-line no-console console.log('Building Codemirror Components...'); - const cmModules = retrieveListOfChildModules('@codemirror'); - const lModules = retrieveListOfChildModules('@lezer'); + const cmModules = getPackagesUnderScope('@codemirror'); + const lModules = getPackagesUnderScope('@lezer'); const externalModules = [...cmModules, ...lModules]; const destBasePath = 'media/vendor/codemirror/js'; const assets = []; diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index 3a51f03bb98e1..53af9fc17c86e 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -12,6 +12,7 @@ const { babel } = require('@rollup/plugin-babel'); const Postcss = require('postcss'); const { renderSync } = require('sass-embedded'); const { minifyJsCode } = require('./minify.es6.js'); +const { getPackagesUnderScope } = require('../init/common/resolve-package.es6.js'); const getWcMinifiedCss = async (file) => { let scssFileExists = false; @@ -44,26 +45,24 @@ const getWcMinifiedCss = async (file) => { return ''; }; -// Check for external imports by specific prefixes -const externalImportChecker = () => { - // Module with these scopes works natively, and therefore they should be ignored by resolver - const prefixes = [ - 'codemirror', - '@codemirror/', - '@lezer/', - ]; - const regexp = new RegExp(`^${prefixes.join('|^')}`); - - return { - name: 'external-import-checker', - resolveId(source) { - if (regexp.test(source)) { - return { id: source, external: true }; - } +// List of external modules that should not be resolved be rollup +const externalModules = []; +const collectExternals = () => { + if (externalModules.length) { + return; + } + // Joomla modules + externalModules.push('cropper-module', 'codemirror'); - return null; - }, - }; + // COdemirror modules + const cmModules = getPackagesUnderScope('@codemirror'); + if (cmModules) { + externalModules.push(...cmModules); + } + const lezerModules = getPackagesUnderScope('@lezer'); + if (lezerModules) { + externalModules.push(...lezerModules); + } }; /** @@ -74,10 +73,13 @@ const externalImportChecker = () => { module.exports.handleESMFile = async (file) => { const newPath = file.replace(/\.w-c\.es6\.js$/, '').replace(/\.es6\.js$/, '').replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`); const minifiedCss = await getWcMinifiedCss(file); + + // Make sure externals is collected + collectExternals(); + const bundle = await rollup.rollup({ input: resolve(file), plugins: [ - externalImportChecker(), nodeResolve({ preferBuiltins: false }), replace({ preventAssignment: true, @@ -110,7 +112,7 @@ module.exports.handleESMFile = async (file) => { ], }), ], - external: [], + external: externalModules, }); bundle.write({ diff --git a/build/media_source/plg_editors_codemirror/joomla.asset.json b/build/media_source/plg_editors_codemirror/joomla.asset.json index 5047b871befa8..141661091216f 100644 --- a/build/media_source/plg_editors_codemirror/joomla.asset.json +++ b/build/media_source/plg_editors_codemirror/joomla.asset.json @@ -13,7 +13,7 @@ { "name": "codemirror", "type": "script", - "uri": "plg_editors_codemirror/codemirror-base.min.js", + "uri": "plg_editors_codemirror/codemirror.min.js", "importmap": true }, { diff --git a/build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror.es6.js similarity index 100% rename from build/media_source/plg_editors_codemirror/js/codemirror-base.es6.js rename to build/media_source/plg_editors_codemirror/js/codemirror.es6.js From 92d2c8866f37c8be1b15d0a76b7500068e8cef6a Mon Sep 17 00:00:00 2001 From: Fedik Date: Sat, 1 Jul 2023 11:00:55 +0300 Subject: [PATCH 45/53] Imports --- .../plg_editors_codemirror/js/codemirror.es6.js | 9 ++++++++- .../js/joomla-editor-codemirror.w-c.es6.js | 4 +--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror.es6.js index 8e3aa97f66804..35d5372e90053 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror.es6.js @@ -146,4 +146,11 @@ async function createFromTextarea(textarea, options) { return view; } -export { minimalSetup, createFromTextarea, optionsToExtensions }; +export { + minimalSetup, + createFromTextarea, + optionsToExtensions, + EditorState, + EditorView, + keymap, +}; diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index 7cd25c4a376cd..666713c35da56 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -3,9 +3,7 @@ * @license GNU General Public License version 2 or later; see LICENSE.txt */ // eslint-disable-next-line import/no-unresolved -import { createFromTextarea } from 'codemirror'; -import { EditorState } from '@codemirror/state'; -import { keymap } from '@codemirror/view'; +import { createFromTextarea, EditorState, keymap } from 'codemirror'; class CodemirrorEditor extends HTMLElement { constructor() { From 829fa0fae6ff4470d3a102041010aef7092fa4c4 Mon Sep 17 00:00:00 2001 From: Fedik Date: Sat, 1 Jul 2023 11:04:54 +0300 Subject: [PATCH 46/53] Imports --- .../build-modules-js/javascript/compile-to-es2017.es6.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index 53af9fc17c86e..b1d78fb714bb1 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -51,10 +51,14 @@ const collectExternals = () => { if (externalModules.length) { return; } + // Joomla modules - externalModules.push('cropper-module', 'codemirror'); + externalModules.push( + 'cropper-module', + 'codemirror', + ); - // COdemirror modules + // Codemirror modules const cmModules = getPackagesUnderScope('@codemirror'); if (cmModules) { externalModules.push(...cmModules); From ab4a5fdf7014ab20c02fffa326342e6cf0a9a182 Mon Sep 17 00:00:00 2001 From: Fedik Date: Sat, 1 Jul 2023 11:19:57 +0300 Subject: [PATCH 47/53] Imports --- build/build-modules-js/javascript/build-codemirror.es6.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/build/build-modules-js/javascript/build-codemirror.es6.js b/build/build-modules-js/javascript/build-codemirror.es6.js index 4c0e2eaf6177c..dc1d72466a25d 100644 --- a/build/build-modules-js/javascript/build-codemirror.es6.js +++ b/build/build-modules-js/javascript/build-codemirror.es6.js @@ -3,9 +3,7 @@ */ /* eslint-disable import/no-extraneous-dependencies, global-require, import/no-dynamic-require */ -const { - existsSync, readFileSync, writeFile, readdirSync, -} = require('fs-extra'); +const { readFileSync, writeFile } = require('fs-extra'); const cliProgress = require('cli-progress'); const rollup = require('rollup'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); From e8b37e2f361176293da32425c61b0ca3c2b24fe4 Mon Sep 17 00:00:00 2001 From: Fedik Date: Sat, 15 Jul 2023 12:28:24 +0300 Subject: [PATCH 48/53] Fix code folding --- .../init/common/resolve-package.es6.js | 2 +- .../plg_editors_codemirror/js/codemirror.es6.js | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/build/build-modules-js/init/common/resolve-package.es6.js b/build/build-modules-js/init/common/resolve-package.es6.js index 949841960ca96..c69e25e5cef3e 100644 --- a/build/build-modules-js/init/common/resolve-package.es6.js +++ b/build/build-modules-js/init/common/resolve-package.es6.js @@ -29,7 +29,7 @@ module.exports.resolvePackageFile = (relativePath) => { module.exports.getPackagesUnderScope = (scope) => { const cmModules = []; - // Get @codemirror module roots + // Get the scope roots const roots = []; module.paths.forEach((path) => { const fullPath = `${path}/${scope}`; diff --git a/build/media_source/plg_editors_codemirror/js/codemirror.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror.es6.js index 35d5372e90053..e2b8e85f424d6 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror.es6.js @@ -42,8 +42,22 @@ const optionsToExtensions = async (options) => { // Load the language for syntax mode if (options.mode) { + const { mode } = options; + const modeOptions = options[mode] || {}; + + // eslint-disable-next-line consistent-return q.push(import(`@codemirror/lang-${options.mode}`).then((modeMod) => { - extensions.push(modeMod[options.mode]()); + // For html and php we need to configure selfClosingTags, to make code folding work correctly with + if (mode === 'php') { + return import('@codemirror/lang-html').then(({ html }) => { + const htmlOptions = options.html || { selfClosingTags: true }; + extensions.push(modeMod.php({ baseLanguage: html(htmlOptions).language })); + }); + } + if (mode === 'html') { + modeOptions.selfClosingTags = true; + } + extensions.push(modeMod[options.mode](modeOptions)); }).catch((error) => { // eslint-disable-next-line no-console console.error(`Cannot creat an extension for "${options.mode}" syntax mode.`, error); From 9e2e6f0bcb04d39b7706c449ac713d42add738ce Mon Sep 17 00:00:00 2001 From: Fedik Date: Sat, 15 Jul 2023 12:31:31 +0300 Subject: [PATCH 49/53] No underscore --- build/media_source/plg_editors_codemirror/js/codemirror.es6.js | 3 +-- .../js/joomla-editor-codemirror.w-c.es6.js | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/build/media_source/plg_editors_codemirror/js/codemirror.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror.es6.js index e2b8e85f424d6..78332f10b9173 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror.es6.js @@ -101,8 +101,7 @@ const optionsToExtensions = async (options) => { // Configurable read only const readOnly = new Compartment(); // Set a custom name so later on we can retrieve this Compartment from view.state.config.compartments - // eslint-disable-next-line no-underscore-dangle - readOnly._j_name = 'readOnly'; + readOnly.$j_name = 'readOnly'; extensions.push(readOnly.of(EditorState.readOnly.of(!!options.readOnly))); // Check for custom extensions, diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index 666713c35da56..b3580500b11cf 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -66,8 +66,7 @@ class CodemirrorEditor extends HTMLElement { }, disable: (disabled) => { editor.state.config.compartments.forEach((facet, compartment) => { - // eslint-disable-next-line no-underscore-dangle - if (compartment._j_name === 'readOnly') { + if (compartment.$j_name === 'readOnly') { editor.dispatch({ effects: compartment.reconfigure(EditorState.readOnly.of(disabled)), }); From 98f0ba241072f51d5693f6a50acb76bcb98f2a3b Mon Sep 17 00:00:00 2001 From: Fedir Zinchuk Date: Mon, 17 Jul 2023 14:05:52 +0300 Subject: [PATCH 50/53] Apply suggestions from code review Co-authored-by: Brian Teeman --- administrator/language/en-GB/plg_editors_codemirror.ini | 4 ++-- build/build-modules-js/javascript/compile-to-es2017.es6.js | 4 ++-- build/build.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/administrator/language/en-GB/plg_editors_codemirror.ini b/administrator/language/en-GB/plg_editors_codemirror.ini index 17ef36b6c013a..d3028b388d99f 100644 --- a/administrator/language/en-GB/plg_editors_codemirror.ini +++ b/administrator/language/en-GB/plg_editors_codemirror.ini @@ -7,9 +7,9 @@ PLG_CODEMIRROR_FIELD_AUTOCLOSEBRACKET_LABEL="Bracket Completion" PLG_CODEMIRROR_FIELD_CODEFOLDING_LABEL="Code Folding" PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_LABEL="Custom Extensions" PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_METHOD_DESCR="Method name, provided by module for extension initialisation. Or multiple, separated by comma. Eg: bracketMatching (from module @codemirror/language)." -PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_METHOD_LABEL="Initialisation method(s)" +PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_METHOD_LABEL="Initialisation Method(s)" PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_MODULE_DESCR="Relative path to the module file, eg: media/my-assets/js/my-codemirror-module.js. Or module name, eg: @codemirror/language." -PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_MODULE_LABEL="Module file or module name" +PLG_CODEMIRROR_FIELD_CUSTOM_EXTENSIONS_MODULE_LABEL="Module File or Module Name" PLG_CODEMIRROR_FIELD_FULLSCREEN_LABEL="Toggle Fullscreen" PLG_CODEMIRROR_FIELD_FULLSCREEN_MOD_LABEL="Toggle Fullscreen Modifier" PLG_CODEMIRROR_FIELD_KEYMAP_DESC="Make CodeMirror work like other popular editors." diff --git a/build/build-modules-js/javascript/compile-to-es2017.es6.js b/build/build-modules-js/javascript/compile-to-es2017.es6.js index b1d78fb714bb1..3549141e57888 100644 --- a/build/build-modules-js/javascript/compile-to-es2017.es6.js +++ b/build/build-modules-js/javascript/compile-to-es2017.es6.js @@ -45,7 +45,7 @@ const getWcMinifiedCss = async (file) => { return ''; }; -// List of external modules that should not be resolved be rollup +// List of external modules that should not be resolved by rollup const externalModules = []; const collectExternals = () => { if (externalModules.length) { @@ -78,7 +78,7 @@ module.exports.handleESMFile = async (file) => { const newPath = file.replace(/\.w-c\.es6\.js$/, '').replace(/\.es6\.js$/, '').replace(`${sep}build${sep}media_source${sep}`, `${sep}media${sep}`); const minifiedCss = await getWcMinifiedCss(file); - // Make sure externals is collected + // Make sure externals are collected collectExternals(); const bundle = await rollup.rollup({ diff --git a/build/build.js b/build/build.js index b4f7dd66c57ef..637514ef8f28b 100644 --- a/build/build.js +++ b/build/build.js @@ -69,7 +69,7 @@ Program .option('--compile-js, --compile-js path', 'Handles ES6, ES5 and web component scripts') .option('--compile-css, --compile-css path', 'Compiles all the scss files to css') .option('--compile-bs', 'Compiles all the Bootstrap component scripts.') - .option('--compile-codemirror', 'Compiles all the codemirror component.') + .option('--compile-codemirror', 'Compiles all the codemirror modules.') .option('--watch', 'Watch file changes and re-compile (ATM only works for the js in the media_source).') .option('--com-media', 'Compile the Media Manager client side App.') .option('--watch-com-media', 'Watch and Compile the Media Manager client side App.') From 39fd73de04da4ae5be7e51eff99a618a4822af4a Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 17 Jul 2023 14:19:03 +0300 Subject: [PATCH 51/53] fix refresh --- .../com_templates/js/admin-template-toggle-switch.es6.js | 4 ---- .../js/joomla-editor-codemirror.w-c.es6.js | 1 + 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/build/media_source/com_templates/js/admin-template-toggle-switch.es6.js b/build/media_source/com_templates/js/admin-template-toggle-switch.es6.js index 564f8080abbe3..d1cde8cab63ed 100644 --- a/build/media_source/com_templates/js/admin-template-toggle-switch.es6.js +++ b/build/media_source/com_templates/js/admin-template-toggle-switch.es6.js @@ -61,10 +61,6 @@ fieldset.classList.add('options-grid-form-half'); } - if (Joomla.editors.instances.jform_core) { - Joomla.editors.instances.jform_core.refresh(); - } - if (typeof Storage !== 'undefined') { localStorage.setItem('coreSwitchState', 'checked'); } diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index b3580500b11cf..0d6fcaae6d202 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -74,6 +74,7 @@ class CodemirrorEditor extends HTMLElement { }); }, onSave: () => {}, + refresh: () => {}, }; } From 742120965456d086109cdea425193f0dd8396e2c Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 17 Jul 2023 14:41:51 +0300 Subject: [PATCH 52/53] z-index --- build/media_source/plg_editors_codemirror/css/codemirror.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/media_source/plg_editors_codemirror/css/codemirror.css b/build/media_source/plg_editors_codemirror/css/codemirror.css index a7c4c85ffddea..113451d5f0f58 100644 --- a/build/media_source/plg_editors_codemirror/css/codemirror.css +++ b/build/media_source/plg_editors_codemirror/css/codemirror.css @@ -23,7 +23,7 @@ joomla-editor-codemirror.fullscreen { right: 0; bottom: 0; left: 0; - z-index: 1040; + z-index: 1045; } joomla-editor-codemirror.fullscreen .cm-editor { width: auto !important; From 34b30367864083f96f3960441201495b81de0bfe Mon Sep 17 00:00:00 2001 From: Fedik Date: Mon, 17 Jul 2023 15:05:55 +0300 Subject: [PATCH 53/53] BS modal workaround --- .../plg_editors_codemirror/css/codemirror.css | 2 +- .../js/joomla-editor-codemirror.w-c.es6.js | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/build/media_source/plg_editors_codemirror/css/codemirror.css b/build/media_source/plg_editors_codemirror/css/codemirror.css index 113451d5f0f58..0b0c2b53db1d1 100644 --- a/build/media_source/plg_editors_codemirror/css/codemirror.css +++ b/build/media_source/plg_editors_codemirror/css/codemirror.css @@ -23,7 +23,7 @@ joomla-editor-codemirror.fullscreen { right: 0; bottom: 0; left: 0; - z-index: 1045; + z-index: 1038; } joomla-editor-codemirror.fullscreen .cm-editor { width: auto !important; diff --git a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js index 0d6fcaae6d202..a6fc0fa6d6b09 100644 --- a/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js +++ b/build/media_source/plg_editors_codemirror/js/joomla-editor-codemirror.w-c.es6.js @@ -39,6 +39,12 @@ class CodemirrorEditor extends HTMLElement { { key: this.fsCombo, run: this.toggleFullScreen }, { key: 'Escape', run: this.closeFullScreen }, ])); + + // Relocate BS modals, to resolve z-index issue in full screen + this.bsModals = this.querySelectorAll('.joomla-modal.modal'); + this.bsModals.forEach((modal) => { + document.body.appendChild(modal); + }); } // Create an editor instance @@ -85,6 +91,13 @@ class CodemirrorEditor extends HTMLElement { } // Remove from the Joomla API delete Joomla.editors.instances[this.element.id]; + + // Restore modals + if (this.bsModals && this.bsModals.length) { + this.bsModals.forEach((modal) => { + this.appendChild(modal); + }); + } } }