Skip to content

Commit

Permalink
[5.0] Update Codemirror to 6-th version (#41070)
Browse files Browse the repository at this point in the history
Co-authored-by: Brian Teeman <[email protected]>
  • Loading branch information
Fedik and brianteeman authored Jul 17, 2023
1 parent 094f544 commit eac7fd7
Show file tree
Hide file tree
Showing 23 changed files with 1,235 additions and 959 deletions.
43 changes: 25 additions & 18 deletions administrator/language/en-GB/plg_editors_codemirror.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +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_FONT_FAMILY_LABEL="Font"
PLG_CODEMIRROR_FIELD_FONT_SIZE_LABEL="Font Size (px)"
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_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"
49 changes: 49 additions & 0 deletions build/build-modules-js/init/common/resolve-package.es6.js
Original file line number Diff line number Diff line change
@@ -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 the scope 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;
};
72 changes: 0 additions & 72 deletions build/build-modules-js/init/exemptions/codemirror.es6.js

This file was deleted.

25 changes: 2 additions & 23 deletions build/build-modules-js/init/localise-packages.es6.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,11 @@ 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 { resolvePackageFile } = require('./common/resolve-package.es6.js');

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"}
Expand Down Expand Up @@ -65,9 +46,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));
Expand Down
138 changes: 138 additions & 0 deletions build/build-modules-js/javascript/build-codemirror.es6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/**
* Build codemirror modules
*/
/* eslint-disable import/no-extraneous-dependencies, global-require, import/no-dynamic-require */

const { readFileSync, writeFile } = 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, getPackagesUnderScope } = require('../init/common/resolve-package.es6.js');

// 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);
});

// 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 = getPackagesUnderScope('@codemirror');
const lModules = getPackagesUnderScope('@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();
});
});
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 });

const task2 = buildModule(module, externalModules, destPath).then(() => {
progressBar.increment();
return createMinified(destPath).then(() => {
progressBar.increment();
});
});
tasks.push(task2);
});

return Promise.all(tasks).then(() => {
progressBar.stop();
return updateAssetRegistry(assets, externalModules);
});
};
Loading

0 comments on commit eac7fd7

Please sign in to comment.