how did it conflict on that?

This commit is contained in:
John McLear 2021-01-14 10:25:34 +00:00
commit 183b765df0
12 changed files with 1324 additions and 1314 deletions

View file

@ -1,3 +1,7 @@
# Changes for the next release
### Notable new features
* Database performance is significantly improved.
# 1.8.7 # 1.8.7
### Compatibility-breaking changes ### Compatibility-breaking changes
* **IMPORTANT:** It is no longer possible to protect a group pad with a * **IMPORTANT:** It is no longer possible to protect a group pad with a
@ -40,7 +44,7 @@
content in `.etherpad` exports content in `.etherpad` exports
* New `expressCloseServer` hook to close Express when required * New `expressCloseServer` hook to close Express when required
* The `padUpdate` hook context now includes `revs` and `changeset` * The `padUpdate` hook context now includes `revs` and `changeset`
* `checkPlugins.js` has various improvements to help plugin developers * `checkPlugin.js` has various improvements to help plugin developers
* The HTTP request object (and therefore the express-session state) is now * The HTTP request object (and therefore the express-session state) is now
accessible from within most `eejsBlock_*` hooks accessible from within most `eejsBlock_*` hooks
* Users without a `password` or `hash` property in `settings.json` are no longer * Users without a `password` or `hash` property in `settings.json` are no longer

View file

@ -57,7 +57,7 @@ require('ep_etherpad-lite/node_modules/npm').load({}, (er, npm) => {
process.stdout.write('\n'); process.stdout.write('\n');
process.stdout.write('done. waiting for db to finish transaction. depended on dbms this may take some time...\n'); process.stdout.write('done. waiting for db to finish transaction. depended on dbms this may take some time...\n');
db.doShutdown(() => { db.close(() => {
log(`finished, imported ${keyNo} keys.`); log(`finished, imported ${keyNo} keys.`);
process.exit(0); process.exit(0);
}); });

View file

@ -2,28 +2,33 @@ The files in this folder are for Plugin developers.
# Get suggestions to improve your Plugin # Get suggestions to improve your Plugin
This code will check your plugin for known usual issues and some suggestions for improvements. No changes will be made to your project. This code will check your plugin for known usual issues and some suggestions for
improvements. No changes will be made to your project.
``` ```
node bin/plugins/checkPlugin.js $PLUGIN_NAME$ node bin/plugins/checkPlugin.js $PLUGIN_NAME$
``` ```
# Basic Example: # Basic Example:
``` ```
node bin/plugins/checkPlugin.js ep_webrtc node bin/plugins/checkPlugin.js ep_webrtc
``` ```
## Autofixing - will autofix any issues it can ## Autofixing - will autofix any issues it can
``` ```
node bin/plugins/checkPlugins.js ep_whatever autofix node bin/plugins/checkPlugin.js ep_whatever autofix
``` ```
## Autocommitting, push, npm minor patch and npm publish (highly dangerous) ## Autocommitting, push, npm minor patch and npm publish (highly dangerous)
``` ```
node bin/plugins/checkPlugins.js ep_whatever autofix autocommit node bin/plugins/checkPlugin.js ep_whatever autocommit
``` ```
# All the plugins # All the plugins
Replace johnmclear with your github username Replace johnmclear with your github username
``` ```
@ -33,19 +38,15 @@ GHUSER=johnmclear; curl "https://api.github.com/users/$GHUSER/repos?per_page=100
cd .. cd ..
# autofixes and autocommits /pushes & npm publishes # autofixes and autocommits /pushes & npm publishes
for dir in `ls node_modules`; for dir in node_modules/ep_*; do
do dir=${dir#node_modules/}
# echo $0 [ "$dir" != ep_etherpad-lite ] || continue
if [[ $dir == *"ep_"* ]]; then node bin/plugins/checkPlugin.js "$dir" autocommit
if [[ $dir != "ep_etherpad-lite" ]]; then
node bin/plugins/checkPlugin.js $dir autofix autocommit
fi
fi
# echo $dir
done done
``` ```
# Automating update of ether organization plugins # Automating update of ether organization plugins
``` ```
getCorePlugins.sh getCorePlugins.sh
updateCorePlugins.sh updateCorePlugins.sh

View file

@ -1,16 +1,16 @@
/* 'use strict';
*
* Usage -- see README.md
*
* Normal usage: node bin/plugins/checkPlugins.js ep_whatever
* Auto fix the things it can: node bin/plugins/checkPlugins.js ep_whatever autofix
* Auto commit, push and publish(to npm) * highly dangerous:
node bin/plugins/checkPlugins.js ep_whatever autofix autocommit
*/ /*
* Usage -- see README.md
*
* Normal usage: node bin/plugins/checkPlugin.js ep_whatever
* Auto fix the things it can: node bin/plugins/checkPlugin.js ep_whatever autofix
* Auto commit, push and publish to npm (highly dangerous):
* node bin/plugins/checkPlugin.js ep_whatever autocommit
*/
const fs = require('fs'); const fs = require('fs');
const {exec} = require('child_process'); const childProcess = require('child_process');
// get plugin name & path from user input // get plugin name & path from user input
const pluginName = process.argv[2]; const pluginName = process.argv[2];
@ -24,15 +24,66 @@ const pluginPath = `node_modules/${pluginName}`;
console.log(`Checking the plugin: ${pluginName}`); console.log(`Checking the plugin: ${pluginName}`);
// Should we autofix? const optArgs = process.argv.slice(3);
if (process.argv[3] && process.argv[3] === 'autofix') var autoFix = true; const autoCommit = optArgs.indexOf('autocommit') !== -1;
const autoFix = autoCommit || optArgs.indexOf('autofix') !== -1;
// Should we update files where possible? const execSync = (cmd, opts = {}) => (childProcess.execSync(cmd, {
if (process.argv[5] && process.argv[5] === 'autoupdate') var autoUpdate = true; cwd: `${pluginPath}/`,
...opts,
}) || '').toString().replace(/\n+$/, '');
// Should we automcommit and npm publish?! const writePackageJson = (obj) => {
if (process.argv[4] && process.argv[4] === 'autocommit') var autoCommit = true; let s = JSON.stringify(obj, null, 2);
if (s.length && s.slice(s.length - 1) !== '\n') s += '\n';
return fs.writeFileSync(`${pluginPath}/package.json`, s);
};
const updateDeps = (parsedPackageJson, key, wantDeps) => {
const {[key]: deps = {}} = parsedPackageJson;
let changed = false;
for (const [pkg, verInfo] of Object.entries(wantDeps)) {
const {ver, overwrite = true} = typeof verInfo === 'string' ? {ver: verInfo} : verInfo;
if (deps[pkg] === ver) continue;
if (deps[pkg] == null) {
console.warn(`Missing dependency in ${key}: '${pkg}': '${ver}'`);
} else {
if (!overwrite) continue;
console.warn(`Dependency mismatch in ${key}: '${pkg}': '${ver}' (current: ${deps[pkg]})`);
}
if (autoFix) {
deps[pkg] = ver;
changed = true;
}
}
if (changed) {
parsedPackageJson[key] = deps;
writePackageJson(parsedPackageJson);
}
};
const prepareRepo = () => {
let branch = execSync('git symbolic-ref HEAD');
if (branch !== 'refs/heads/master' && branch !== 'refs/heads/main') {
throw new Error('master/main must be checked out');
}
branch = branch.replace(/^refs\/heads\//, '');
execSync('git rev-parse --verify -q HEAD^0 || ' +
`{ echo "Error: no commits on ${branch}" >&2; exit 1; }`);
execSync('git rev-parse --verify @{u}'); // Make sure there's a remote tracking branch.
const modified = execSync('git diff-files --name-status');
if (modified !== '') throw new Error(`working directory has modifications:\n${modified}`);
const untracked = execSync('git ls-files -o --exclude-standard');
if (untracked !== '') throw new Error(`working directory has untracked files:\n${untracked}`);
const indexStatus = execSync('git diff-index --cached --name-status HEAD');
if (indexStatus !== '') throw new Error(`uncommitted staged changes to files:\n${indexStatus}`);
execSync('git pull --ff-only', {stdio: 'inherit'});
if (execSync('git rev-list @{u}...') !== '') throw new Error('repo contains unpushed commits');
if (autoCommit) {
execSync('git config --get user.name');
execSync('git config --get user.email');
}
};
if (autoCommit) { if (autoCommit) {
console.warn('Auto commit is enabled, I hope you know what you are doing...'); console.warn('Auto commit is enabled, I hope you know what you are doing...');
@ -50,7 +101,6 @@ fs.readdir(pluginPath, (err, rootFiles) => {
// some files we need to know the actual file name. Not compulsory but might help in the future. // some files we need to know the actual file name. Not compulsory but might help in the future.
let readMeFileName; let readMeFileName;
let repository; let repository;
let hasAutoFixed = false;
for (let i = 0; i < rootFiles.length; i++) { for (let i = 0; i < rootFiles.length; i++) {
if (rootFiles[i].toLowerCase().indexOf('readme') !== -1) readMeFileName = rootFiles[i]; if (rootFiles[i].toLowerCase().indexOf('readme') !== -1) readMeFileName = rootFiles[i];
@ -61,25 +111,18 @@ fs.readdir(pluginPath, (err, rootFiles) => {
console.error('No .git folder, aborting'); console.error('No .git folder, aborting');
process.exit(1); process.exit(1);
} }
prepareRepo();
// do a git pull...
var child_process = require('child_process');
try {
child_process.execSync('git pull ', {cwd: `${pluginPath}/`});
} catch (e) {
console.error('Error git pull', e);
}
try { try {
const path = `${pluginPath}/.github/workflows/npmpublish.yml`; const path = `${pluginPath}/.github/workflows/npmpublish.yml`;
if (!fs.existsSync(path)) { if (!fs.existsSync(path)) {
console.log('no .github/workflows/npmpublish.yml, create one and set npm secret to auto publish to npm on commit'); console.log('no .github/workflows/npmpublish.yml');
console.log('create one and set npm secret to auto publish to npm on commit');
if (autoFix) { if (autoFix) {
const npmpublish = const npmpublish =
fs.readFileSync('bin/plugins/lib/npmpublish.yml', {encoding: 'utf8', flag: 'r'}); fs.readFileSync('bin/plugins/lib/npmpublish.yml', {encoding: 'utf8', flag: 'r'});
fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true}); fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true});
fs.writeFileSync(path, npmpublish); fs.writeFileSync(path, npmpublish);
hasAutoFixed = true;
console.log("If you haven't already, setup autopublish for this plugin https://github.com/ether/etherpad-lite/wiki/Plugins:-Automatically-publishing-to-npm-on-commit-to-Github-Repo"); console.log("If you haven't already, setup autopublish for this plugin https://github.com/ether/etherpad-lite/wiki/Plugins:-Automatically-publishing-to-npm-on-commit-to-Github-Repo");
} else { } else {
console.log('Setup autopublish for this plugin https://github.com/ether/etherpad-lite/wiki/Plugins:-Automatically-publishing-to-npm-on-commit-to-Github-Repo'); console.log('Setup autopublish for this plugin https://github.com/ether/etherpad-lite/wiki/Plugins:-Automatically-publishing-to-npm-on-commit-to-Github-Repo');
@ -89,18 +132,20 @@ fs.readdir(pluginPath, (err, rootFiles) => {
// checkVersion takes two file paths and checks for a version string in them. // checkVersion takes two file paths and checks for a version string in them.
const currVersionFile = fs.readFileSync(path, {encoding: 'utf8', flag: 'r'}); const currVersionFile = fs.readFileSync(path, {encoding: 'utf8', flag: 'r'});
const existingConfigLocation = currVersionFile.indexOf('##ETHERPAD_NPM_V='); const existingConfigLocation = currVersionFile.indexOf('##ETHERPAD_NPM_V=');
const existingValue = parseInt(currVersionFile.substr(existingConfigLocation + 17, existingConfigLocation.length)); const existingValue = parseInt(
currVersionFile.substr(existingConfigLocation + 17, existingConfigLocation.length));
const reqVersionFile = fs.readFileSync('bin/plugins/lib/npmpublish.yml', {encoding: 'utf8', flag: 'r'}); const reqVersionFile =
fs.readFileSync('bin/plugins/lib/npmpublish.yml', {encoding: 'utf8', flag: 'r'});
const reqConfigLocation = reqVersionFile.indexOf('##ETHERPAD_NPM_V='); const reqConfigLocation = reqVersionFile.indexOf('##ETHERPAD_NPM_V=');
const reqValue = parseInt(reqVersionFile.substr(reqConfigLocation + 17, reqConfigLocation.length)); const reqValue =
parseInt(reqVersionFile.substr(reqConfigLocation + 17, reqConfigLocation.length));
if (!existingValue || (reqValue > existingValue)) { if (!existingValue || (reqValue > existingValue)) {
const npmpublish = const npmpublish =
fs.readFileSync('bin/plugins/lib/npmpublish.yml', {encoding: 'utf8', flag: 'r'}); fs.readFileSync('bin/plugins/lib/npmpublish.yml', {encoding: 'utf8', flag: 'r'});
fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true}); fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true});
fs.writeFileSync(path, npmpublish); fs.writeFileSync(path, npmpublish);
hasAutoFixed = true;
} }
} }
} catch (err) { } catch (err) {
@ -111,31 +156,33 @@ fs.readdir(pluginPath, (err, rootFiles) => {
try { try {
const path = `${pluginPath}/.github/workflows/backend-tests.yml`; const path = `${pluginPath}/.github/workflows/backend-tests.yml`;
if (!fs.existsSync(path)) { if (!fs.existsSync(path)) {
console.log('no .github/workflows/backend-tests.yml, create one and set npm secret to auto publish to npm on commit'); console.log('no .github/workflows/backend-tests.yml');
console.log('create one and set npm secret to auto publish to npm on commit');
if (autoFix) { if (autoFix) {
const backendTests = const backendTests =
fs.readFileSync('bin/plugins/lib/backend-tests.yml', {encoding: 'utf8', flag: 'r'}); fs.readFileSync('bin/plugins/lib/backend-tests.yml', {encoding: 'utf8', flag: 'r'});
fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true}); fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true});
fs.writeFileSync(path, backendTests); fs.writeFileSync(path, backendTests);
hasAutoFixed = true;
} }
} else { } else {
// autopublish exists, we should check the version.. // autopublish exists, we should check the version..
// checkVersion takes two file paths and checks for a version string in them. // checkVersion takes two file paths and checks for a version string in them.
const currVersionFile = fs.readFileSync(path, {encoding: 'utf8', flag: 'r'}); const currVersionFile = fs.readFileSync(path, {encoding: 'utf8', flag: 'r'});
const existingConfigLocation = currVersionFile.indexOf('##ETHERPAD_NPM_V='); const existingConfigLocation = currVersionFile.indexOf('##ETHERPAD_NPM_V=');
const existingValue = parseInt(currVersionFile.substr(existingConfigLocation + 17, existingConfigLocation.length)); const existingValue = parseInt(
currVersionFile.substr(existingConfigLocation + 17, existingConfigLocation.length));
const reqVersionFile = fs.readFileSync('bin/plugins/lib/backend-tests.yml', {encoding: 'utf8', flag: 'r'}); const reqVersionFile =
fs.readFileSync('bin/plugins/lib/backend-tests.yml', {encoding: 'utf8', flag: 'r'});
const reqConfigLocation = reqVersionFile.indexOf('##ETHERPAD_NPM_V='); const reqConfigLocation = reqVersionFile.indexOf('##ETHERPAD_NPM_V=');
const reqValue = parseInt(reqVersionFile.substr(reqConfigLocation + 17, reqConfigLocation.length)); const reqValue =
parseInt(reqVersionFile.substr(reqConfigLocation + 17, reqConfigLocation.length));
if (!existingValue || (reqValue > existingValue)) { if (!existingValue || (reqValue > existingValue)) {
const backendTests = const backendTests =
fs.readFileSync('bin/plugins/lib/backend-tests.yml', {encoding: 'utf8', flag: 'r'}); fs.readFileSync('bin/plugins/lib/backend-tests.yml', {encoding: 'utf8', flag: 'r'});
fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true}); fs.mkdirSync(`${pluginPath}/.github/workflows`, {recursive: true});
fs.writeFileSync(path, backendTests); fs.writeFileSync(path, backendTests);
hasAutoFixed = true;
} }
} }
} catch (err) { } catch (err) {
@ -147,7 +194,8 @@ fs.readdir(pluginPath, (err, rootFiles) => {
} }
if (files.indexOf('package.json') !== -1) { if (files.indexOf('package.json') !== -1) {
const packageJSON = fs.readFileSync(`${pluginPath}/package.json`, {encoding: 'utf8', flag: 'r'}); const packageJSON =
fs.readFileSync(`${pluginPath}/package.json`, {encoding: 'utf8', flag: 'r'});
const parsedPackageJSON = JSON.parse(packageJSON); const parsedPackageJSON = JSON.parse(packageJSON);
if (autoFix) { if (autoFix) {
let updatedPackageJSON = false; let updatedPackageJSON = false;
@ -159,66 +207,35 @@ fs.readdir(pluginPath, (err, rootFiles) => {
}; };
} }
if (updatedPackageJSON) { if (updatedPackageJSON) {
hasAutoFixed = true; writePackageJson(parsedPackageJSON);
fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2));
} }
} }
if (packageJSON.toLowerCase().indexOf('repository') === -1) { if (packageJSON.toLowerCase().indexOf('repository') === -1) {
console.warn('No repository in package.json'); console.warn('No repository in package.json');
if (autoFix) { if (autoFix) {
console.warn('Repository not detected in package.json. Please add repository section manually.'); console.warn('Repository not detected in package.json. Add repository section.');
} }
} else { } else {
// useful for creating README later. // useful for creating README later.
repository = parsedPackageJSON.repository.url; repository = parsedPackageJSON.repository.url;
} }
// include lint config updateDeps(parsedPackageJSON, 'devDependencies', {
if (packageJSON.toLowerCase().indexOf('devdependencies') === -1 || !parsedPackageJSON.devDependencies.eslint) { 'eslint': '^7.17.0',
console.warn('Missing eslint reference in devDependencies'); 'eslint-config-etherpad': '^1.0.22',
if (autoFix) { 'eslint-plugin-eslint-comments': '^3.2.0',
const devDependencies = { 'eslint-plugin-mocha': '^8.0.0',
'eslint': '^7.14.0', 'eslint-plugin-node': '^11.1.0',
'eslint-config-etherpad': '^1.0.13', 'eslint-plugin-prefer-arrow': '^1.2.2',
'eslint-plugin-mocha': '^8.0.0', 'eslint-plugin-promise': '^4.2.1',
'eslint-plugin-node': '^11.1.0', 'eslint-plugin-you-dont-need-lodash-underscore': '^6.10.0',
'eslint-plugin-prefer-arrow': '^1.2.2', });
'eslint-plugin-promise': '^4.2.1',
};
hasAutoFixed = true;
parsedPackageJSON.devDependencies = devDependencies;
fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2));
const child_process = require('child_process'); updateDeps(parsedPackageJSON, 'peerDependencies', {
try { // Some plugins require a newer version of Etherpad so don't overwrite if already set.
child_process.execSync('npm install', {cwd: `${pluginPath}/`}); 'ep_etherpad-lite': {ver: '>=1.8.6', overwrite: false},
hasAutoFixed = true; });
} catch (e) {
console.error('Failed to create package-lock.json');
}
}
}
// include peer deps config
if (packageJSON.toLowerCase().indexOf('peerdependencies') === -1 || !parsedPackageJSON.peerDependencies) {
console.warn('Missing peer deps reference in package.json');
if (autoFix) {
const peerDependencies = {
'ep_etherpad-lite': '>=1.8.6',
};
hasAutoFixed = true;
parsedPackageJSON.peerDependencies = peerDependencies;
fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2));
const child_process = require('child_process');
try {
child_process.execSync('npm install --no-save ep_etherpad-lite@file:../../src', {cwd: `${pluginPath}/`});
hasAutoFixed = true;
} catch (e) {
console.error('Failed to create package-lock.json');
}
}
}
if (packageJSON.toLowerCase().indexOf('eslintconfig') === -1) { if (packageJSON.toLowerCase().indexOf('eslintconfig') === -1) {
console.warn('No esLintConfig in package.json'); console.warn('No esLintConfig in package.json');
@ -227,9 +244,8 @@ fs.readdir(pluginPath, (err, rootFiles) => {
root: true, root: true,
extends: 'etherpad/plugin', extends: 'etherpad/plugin',
}; };
hasAutoFixed = true;
parsedPackageJSON.eslintConfig = eslintConfig; parsedPackageJSON.eslintConfig = eslintConfig;
fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2)); writePackageJson(parsedPackageJSON);
} }
} }
@ -240,9 +256,8 @@ fs.readdir(pluginPath, (err, rootFiles) => {
'lint': 'eslint .', 'lint': 'eslint .',
'lint:fix': 'eslint --fix .', 'lint:fix': 'eslint --fix .',
}; };
hasAutoFixed = true;
parsedPackageJSON.scripts = scripts; parsedPackageJSON.scripts = scripts;
fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2)); writePackageJson(parsedPackageJSON);
} }
} }
@ -252,31 +267,24 @@ fs.readdir(pluginPath, (err, rootFiles) => {
const engines = { const engines = {
node: '>=10.13.0', node: '>=10.13.0',
}; };
hasAutoFixed = true;
parsedPackageJSON.engines = engines; parsedPackageJSON.engines = engines;
fs.writeFileSync(`${pluginPath}/package.json`, JSON.stringify(parsedPackageJSON, null, 2)); writePackageJson(parsedPackageJSON);
} }
} }
} }
if (files.indexOf('package-lock.json') === -1) { if (files.indexOf('package-lock.json') === -1) {
console.warn('package-lock.json file not found. Please run npm install in the plugin folder and commit the package-lock.json file.'); console.warn('package-lock.json not found');
if (autoFix) { if (!autoFix) {
var child_process = require('child_process'); console.warn('Run npm install in the plugin folder and commit the package-lock.json file.');
try {
child_process.execSync('npm install', {cwd: `${pluginPath}/`});
console.log('Making package-lock.json');
hasAutoFixed = true;
} catch (e) {
console.error('Failed to create package-lock.json');
}
} }
} }
if (files.indexOf('readme') === -1 && files.indexOf('readme.md') === -1) { if (files.indexOf('readme') === -1 && files.indexOf('readme.md') === -1) {
console.warn('README.md file not found, please create'); console.warn('README.md file not found, please create');
if (autoFix) { if (autoFix) {
console.log('Autofixing missing README.md file, please edit the README.md file further to include plugin specific details.'); console.log('Autofixing missing README.md file');
console.log('please edit the README.md file further to include plugin specific details.');
let readme = fs.readFileSync('bin/plugins/lib/README.md', {encoding: 'utf8', flag: 'r'}); let readme = fs.readFileSync('bin/plugins/lib/README.md', {encoding: 'utf8', flag: 'r'});
readme = readme.replace(/\[plugin_name\]/g, pluginName); readme = readme.replace(/\[plugin_name\]/g, pluginName);
if (repository) { if (repository) {
@ -315,22 +323,11 @@ fs.readdir(pluginPath, (err, rootFiles) => {
if (files.indexOf('license') === -1 && files.indexOf('license.md') === -1) { if (files.indexOf('license') === -1 && files.indexOf('license.md') === -1) {
console.warn('LICENSE.md file not found, please create'); console.warn('LICENSE.md file not found, please create');
if (autoFix) { if (autoFix) {
hasAutoFixed = true;
console.log('Autofixing missing LICENSE.md file, including Apache 2 license.'); console.log('Autofixing missing LICENSE.md file, including Apache 2 license.');
exec('git config user.name', (error, name, stderr) => { let license = fs.readFileSync('bin/plugins/lib/LICENSE.md', {encoding: 'utf8', flag: 'r'});
if (error) { license = license.replace('[yyyy]', new Date().getFullYear());
console.log(`error: ${error.message}`); license = license.replace('[name of copyright owner]', execSync('git config user.name'));
return; fs.writeFileSync(`${pluginPath}/LICENSE.md`, license);
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
let license = fs.readFileSync('bin/plugins/lib/LICENSE.md', {encoding: 'utf8', flag: 'r'});
license = license.replace('[yyyy]', new Date().getFullYear());
license = license.replace('[name of copyright owner]', name);
fs.writeFileSync(`${pluginPath}/LICENSE.md`, license);
});
} }
} }
@ -341,13 +338,12 @@ fs.readdir(pluginPath, (err, rootFiles) => {
console.warn('.travis.yml file not found, please create. .travis.yml is used for automatically CI testing Etherpad. It is useful to know if your plugin breaks another feature for example.'); console.warn('.travis.yml file not found, please create. .travis.yml is used for automatically CI testing Etherpad. It is useful to know if your plugin breaks another feature for example.');
// TODO: Make it check version of the .travis file to see if it needs an update. // TODO: Make it check version of the .travis file to see if it needs an update.
if (autoFix) { if (autoFix) {
hasAutoFixed = true;
console.log('Autofixing missing .travis.yml file'); console.log('Autofixing missing .travis.yml file');
fs.writeFileSync(`${pluginPath}/.travis.yml`, travisConfig); fs.writeFileSync(`${pluginPath}/.travis.yml`, travisConfig);
console.log('Travis file created, please sign into travis and enable this repository'); console.log('Travis file created, please sign into travis and enable this repository');
} }
} }
if (autoFix && autoUpdate) { if (autoFix) {
// checks the file versioning of .travis and updates it to the latest. // checks the file versioning of .travis and updates it to the latest.
const existingConfig = fs.readFileSync(`${pluginPath}/.travis.yml`, {encoding: 'utf8', flag: 'r'}); const existingConfig = fs.readFileSync(`${pluginPath}/.travis.yml`, {encoding: 'utf8', flag: 'r'});
const existingConfigLocation = existingConfig.indexOf('##ETHERPAD_TRAVIS_V='); const existingConfigLocation = existingConfig.indexOf('##ETHERPAD_TRAVIS_V=');
@ -362,14 +358,12 @@ fs.readdir(pluginPath, (err, rootFiles) => {
} else if (newValue > existingValue) { } else if (newValue > existingValue) {
console.log('updating .travis.yml'); console.log('updating .travis.yml');
fs.writeFileSync(`${pluginPath}/.travis.yml`, travisConfig); fs.writeFileSync(`${pluginPath}/.travis.yml`, travisConfig);
hasAutoFixed = true;
}// }//
} }
if (files.indexOf('.gitignore') === -1) { if (files.indexOf('.gitignore') === -1) {
console.warn(".gitignore file not found, please create. .gitignore files are useful to ensure files aren't incorrectly commited to a repository."); console.warn(".gitignore file not found, please create. .gitignore files are useful to ensure files aren't incorrectly commited to a repository.");
if (autoFix) { if (autoFix) {
hasAutoFixed = true;
console.log('Autofixing missing .gitignore file'); console.log('Autofixing missing .gitignore file');
const gitignore = fs.readFileSync('bin/plugins/lib/gitignore', {encoding: 'utf8', flag: 'r'}); const gitignore = fs.readFileSync('bin/plugins/lib/gitignore', {encoding: 'utf8', flag: 'r'});
fs.writeFileSync(`${pluginPath}/.gitignore`, gitignore); fs.writeFileSync(`${pluginPath}/.gitignore`, gitignore);
@ -382,7 +376,6 @@ fs.readdir(pluginPath, (err, rootFiles) => {
if (autoFix) { if (autoFix) {
gitignore += 'node_modules/'; gitignore += 'node_modules/';
fs.writeFileSync(`${pluginPath}/.gitignore`, gitignore); fs.writeFileSync(`${pluginPath}/.gitignore`, gitignore);
hasAutoFixed = true;
} }
} }
} }
@ -396,7 +389,6 @@ fs.readdir(pluginPath, (err, rootFiles) => {
if (files.indexOf('.ep_initialized') !== -1) { if (files.indexOf('.ep_initialized') !== -1) {
console.warn('.ep_initialized found, please remove. .ep_initialized should never be commited to git and should only exist once the plugin has been executed one time.'); console.warn('.ep_initialized found, please remove. .ep_initialized should never be commited to git and should only exist once the plugin has been executed one time.');
if (autoFix) { if (autoFix) {
hasAutoFixed = true;
console.log('Autofixing incorrectly existing .ep_initialized file'); console.log('Autofixing incorrectly existing .ep_initialized file');
fs.unlinkSync(`${pluginPath}/.ep_initialized`); fs.unlinkSync(`${pluginPath}/.ep_initialized`);
} }
@ -405,7 +397,6 @@ fs.readdir(pluginPath, (err, rootFiles) => {
if (files.indexOf('npm-debug.log') !== -1) { if (files.indexOf('npm-debug.log') !== -1) {
console.warn('npm-debug.log found, please remove. npm-debug.log should never be commited to your repository.'); console.warn('npm-debug.log found, please remove. npm-debug.log should never be commited to your repository.');
if (autoFix) { if (autoFix) {
hasAutoFixed = true;
console.log('Autofixing incorrectly existing npm-debug.log file'); console.log('Autofixing incorrectly existing npm-debug.log file');
fs.unlinkSync(`${pluginPath}/npm-debug.log`); fs.unlinkSync(`${pluginPath}/npm-debug.log`);
} }
@ -421,47 +412,53 @@ fs.readdir(pluginPath, (err, rootFiles) => {
console.warn('Test files not found, please create tests. https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin#writing-and-running-front-end-tests-for-your-plugin'); console.warn('Test files not found, please create tests. https://github.com/ether/etherpad-lite/wiki/Creating-a-plugin#writing-and-running-front-end-tests-for-your-plugin');
} }
// linting begins // Install dependencies so we can run ESLint. This should also create or update package-lock.json
if (autoFix) { // if autoFix is enabled.
var lintCmd = 'npm run lint:fix'; const npmInstall = `npm install${autoFix ? '' : ' --no-package-lock'}`;
} else { execSync(npmInstall, {stdio: 'inherit'});
var lintCmd = 'npm run lint'; // The ep_etherpad-lite peer dep must be installed last otherwise `npm install` will nuke it. An
} // absolute path to etherpad-lite/src is used here so that pluginPath can be a symlink.
execSync(
`${npmInstall} --no-save ep_etherpad-lite@file:${__dirname}/../../src`, {stdio: 'inherit'});
// linting begins
try { try {
child_process.execSync(lintCmd, {cwd: `${pluginPath}/`});
console.log('Linting...'); console.log('Linting...');
if (autoFix) { const lintCmd = autoFix ? 'npx eslint --fix .' : 'npx eslint';
// todo: if npm run lint doesn't do anything no need for... execSync(lintCmd, {stdio: 'inherit'});
hasAutoFixed = true;
}
} catch (e) { } catch (e) {
// it is gonna throw an error anyway // it is gonna throw an error anyway
console.log('Manual linting probably required, check with: npm run lint'); console.log('Manual linting probably required, check with: npm run lint');
} }
// linting ends. // linting ends.
if (hasAutoFixed) { if (autoFix) {
console.log('Fixes applied, please check git diff then run the following command:\n\n'); const unchanged = JSON.parse(execSync(
// bump npm Version 'untracked=$(git ls-files -o --exclude-standard) || exit 1; ' +
if (autoCommit) { 'git diff-files --quiet && [ -z "$untracked" ] && echo true || echo false'));
// holy shit you brave. if (!unchanged) {
console.log('Attempting autocommit and auto publish to npm'); // Display a diff of changes. Git doesn't diff untracked files, so they must be added to the
// github should push to npm for us :) // index. Use a temporary index file to avoid modifying Git's default index file.
exec(`cd node_modules/${pluginName} && git rm -rf node_modules --ignore-unmatch && git add -A && git commit --allow-empty -m 'autofixes from Etherpad checkPlugins.js' && git push && cd ../..`, (error, name, stderr) => { execSync('git read-tree HEAD; git add -A && git diff-index -p --cached HEAD && echo ""', {
if (error) { env: {...process.env, GIT_INDEX_FILE: '.git/checkPlugin.index'},
console.log(`error: ${error.message}`); stdio: 'inherit',
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log("I think she's got it! By George she's got it!");
process.exit(0);
}); });
fs.unlinkSync(`${pluginPath}/.git/checkPlugin.index`);
const cmd = [
'git add -A',
'git commit -m "autofixes from Etherpad checkPlugin.js"',
'git push',
].join(' && ');
if (autoCommit) {
console.log('Attempting autocommit and auto publish to npm');
execSync(cmd, {stdio: 'inherit'});
} else {
console.log('Fixes applied. Check the above git diff then run the following command:');
console.log(`(cd node_modules/${pluginName} && ${cmd})`);
}
} else { } else {
console.log(`cd node_modules/${pluginName} && git add -A && git commit --allow-empty -m 'autofixes from Etherpad checkPlugins.js' && npm version patch && git add package.json && git commit --allow-empty -m 'bump version' && git push && npm publish && cd ../..`); console.log('No changes.');
} }
} }

View file

@ -49,7 +49,7 @@ exports.init = async () => await new Promise((resolve, reject) => {
} }
// everything ok, set up Promise-based methods // everything ok, set up Promise-based methods
['get', 'set', 'findKeys', 'getSub', 'setSub', 'remove', 'doShutdown'].forEach((fn) => { ['get', 'set', 'findKeys', 'getSub', 'setSub', 'remove'].forEach((fn) => {
exports[fn] = util.promisify(db[fn].bind(db)); exports[fn] = util.promisify(db[fn].bind(db));
}); });
@ -73,6 +73,6 @@ exports.init = async () => await new Promise((resolve, reject) => {
}); });
exports.shutdown = async (hookName, context) => { exports.shutdown = async (hookName, context) => {
await exports.doShutdown(); await util.promisify(db.close.bind(db))();
console.log('Database closed'); console.log('Database closed');
}; };

28
src/package-lock.json generated
View file

@ -4179,9 +4179,9 @@
"dev": true "dev": true
}, },
"needle": { "needle": {
"version": "2.5.2", "version": "2.6.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz", "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz",
"integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==", "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==",
"optional": true, "optional": true,
"requires": { "requires": {
"debug": "^3.2.6", "debug": "^3.2.6",
@ -4236,9 +4236,9 @@
} }
}, },
"node-addon-api": { "node-addon-api": {
"version": "2.0.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.1.0.tgz",
"integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA==", "integrity": "sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==",
"optional": true "optional": true
}, },
"node-environment-flags": { "node-environment-flags": {
@ -8858,12 +8858,12 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
}, },
"sqlite3": { "sqlite3": {
"version": "5.0.0", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.0.tgz", "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.1.tgz",
"integrity": "sha512-rjvqHFUaSGnzxDy2AHCwhHy6Zp6MNJzCPGYju4kD8yi6bze4d1/zMTg6C7JI49b7/EM7jKMTvyfN/4ylBKdwfw==", "integrity": "sha512-kh2lTIcYNfmVcvhVJihsYuPj9U0xzBbh6bmqILO2hkryWSC9RRhzYmkIDtJkJ+d8Kg4wZRJ0T1reyHUEspICfg==",
"optional": true, "optional": true,
"requires": { "requires": {
"node-addon-api": "2.0.0", "node-addon-api": "^3.0.0",
"node-gyp": "3.x", "node-gyp": "3.x",
"node-pre-gyp": "^0.11.0" "node-pre-gyp": "^0.11.0"
} }
@ -9358,9 +9358,9 @@
} }
}, },
"ueberdb2": { "ueberdb2": {
"version": "1.1.7", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/ueberdb2/-/ueberdb2-1.1.7.tgz", "resolved": "https://registry.npmjs.org/ueberdb2/-/ueberdb2-1.2.1.tgz",
"integrity": "sha512-Fxvpei4MVYOlCWZ67I5iibYyaHIb40ZLwN0OsjPEuMpcWYBXuwkl+svFyA2nYgk9/1Nk9eL/zdsXbwm7BLMKsg==", "integrity": "sha512-b1WeG5KinxddpFAkHcFJW5tDuoGMonI3AyZgqmmHKnvF7CJTprPX17n0AOi3iQcu97uoxz9nb56KEQ4gHQOCJQ==",
"requires": { "requires": {
"async": "^3.2.0", "async": "^3.2.0",
"cassandra-driver": "^4.5.1", "cassandra-driver": "^4.5.1",
@ -9371,7 +9371,7 @@
"elasticsearch": "^16.7.1", "elasticsearch": "^16.7.1",
"mocha": "^7.1.2", "mocha": "^7.1.2",
"mongodb": "^3.6.3", "mongodb": "^3.6.3",
"mssql": "7.0.0-alpha.4", "mssql": "^7.0.0-alpha.4",
"mysql": "2.18.1", "mysql": "2.18.1",
"nano": "^8.2.2", "nano": "^8.2.2",
"pg": "^8.0.3", "pg": "^8.0.3",

View file

@ -70,7 +70,7 @@
"threads": "^1.4.0", "threads": "^1.4.0",
"tiny-worker": "^2.3.0", "tiny-worker": "^2.3.0",
"tinycon": "0.0.1", "tinycon": "0.0.1",
"ueberdb2": "^1.1.7", "ueberdb2": "^1.2.1",
"underscore": "1.8.3", "underscore": "1.8.3",
"unorm": "1.4.1" "unorm": "1.4.1"
}, },

File diff suppressed because it is too large Load diff

View file

@ -1,3 +1,4 @@
'use strict';
/** /**
* This code is mostly from the old Etherpad. Please help us to comment this code. * This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it. * This helps other people to understand this code better and helps them to improve it.

View file

@ -1,8 +1,4 @@
/** 'use strict';
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
// THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.domline // THIS FILE IS ALSO AN APPJET MODULE: etherpad.collab.ace.domline
// %APPJET%: import("etherpad.admin.plugins"); // %APPJET%: import("etherpad.admin.plugins");
@ -166,7 +162,7 @@ domline.createDomLine = function (nonEmpty, doesWrap, optBrowser, optDocument) {
lineClass = domline.addToLineClass(lineClass, cls); lineClass = domline.addToLineClass(lineClass, cls);
} else if (txt) { } else if (txt) {
if (href) { if (href) {
urn_schemes = new RegExp('^(about|geo|mailto|tel):'); const urn_schemes = new RegExp('^(about|geo|mailto|tel):');
if (!~href.indexOf('://') && !urn_schemes.test(href)) // if the url doesn't include a protocol prefix, assume http if (!~href.indexOf('://') && !urn_schemes.test(href)) // if the url doesn't include a protocol prefix, assume http
{ {
href = `http://${href}`; href = `http://${href}`;

View file

@ -1,3 +1,5 @@
'use strict';
// Farbtastic 2.0 alpha // Farbtastic 2.0 alpha
// edited by Sebastian Castro <sebastian.castro@protonmail.com> on 2020-04-06 // edited by Sebastian Castro <sebastian.castro@protonmail.com> on 2020-04-06
(function ($) { (function ($) {
@ -158,12 +160,12 @@ $._farbtastic = function (container, options) {
m.lineWidth = w / r; m.lineWidth = w / r;
m.scale(r, r); m.scale(r, r);
// Each segment goes from angle1 to angle2. // Each segment goes from angle1 to angle2.
for (var i = 0; i <= n; ++i) { for (let i = 0; i <= n; ++i) {
var d2 = i / n, var d2 = i / n,
angle2 = d2 * Math.PI * 2, angle2 = d2 * Math.PI * 2,
// Endpoints // Endpoints
x1 = Math.sin(angle1), y1 = -Math.cos(angle1); x1 = Math.sin(angle1), y1 = -Math.cos(angle1);
x2 = Math.sin(angle2), y2 = -Math.cos(angle2), const x2 = Math.sin(angle2), y2 = -Math.cos(angle2),
// Midpoint chosen so that the endpoints are tangent to the circle. // Midpoint chosen so that the endpoints are tangent to the circle.
am = (angle1 + angle2) / 2, am = (angle1 + angle2) / 2,
tan = 1 / Math.cos((angle2 - angle1) / 2), tan = 1 / Math.cos((angle2 - angle1) / 2),
@ -171,37 +173,16 @@ $._farbtastic = function (container, options) {
// New color // New color
color2 = fb.pack(fb.HSLToRGB([d2, 1, 0.5])); color2 = fb.pack(fb.HSLToRGB([d2, 1, 0.5]));
if (i > 0) { if (i > 0) {
if (browser.msie) { // Create gradient fill between the endpoints.
// IE's gradient calculations mess up the colors. Correct along the diagonals. var grad = m.createLinearGradient(x1, y1, x2, y2);
var corr = (1 + Math.min(Math.abs(Math.tan(angle1)), Math.abs(Math.tan(Math.PI / 2 - angle1)))) / n; grad.addColorStop(0, color1);
color1 = fb.pack(fb.HSLToRGB([d1 - 0.15 * corr, 1, 0.5])); grad.addColorStop(1, color2);
color2 = fb.pack(fb.HSLToRGB([d2 + 0.15 * corr, 1, 0.5])); m.strokeStyle = grad;
// Create gradient fill between the endpoints. // Draw quadratic curve segment.
var grad = m.createLinearGradient(x1, y1, x2, y2); m.beginPath();
grad.addColorStop(0, color1); m.moveTo(x1, y1);
grad.addColorStop(1, color2); m.quadraticCurveTo(xm, ym, x2, y2);
m.fillStyle = grad; m.stroke();
// Draw quadratic curve segment as a fill.
var r1 = (r + w / 2) / r, r2 = (r - w / 2) / r; // inner/outer radius.
m.beginPath();
m.moveTo(x1 * r1, y1 * r1);
m.quadraticCurveTo(xm * r1, ym * r1, x2 * r1, y2 * r1);
m.lineTo(x2 * r2, y2 * r2);
m.quadraticCurveTo(xm * r2, ym * r2, x1 * r2, y1 * r2);
m.fill();
}
else {
// Create gradient fill between the endpoints.
var grad = m.createLinearGradient(x1, y1, x2, y2);
grad.addColorStop(0, color1);
grad.addColorStop(1, color2);
m.strokeStyle = grad;
// Draw quadratic curve segment.
m.beginPath();
m.moveTo(x1, y1);
m.quadraticCurveTo(xm, ym, x2, y2);
m.stroke();
}
} }
// Prevent seams where curves join. // Prevent seams where curves join.
angle1 = angle2 - nudge; color1 = color2; d1 = d2; angle1 = angle2 - nudge; color1 = color2; d1 = d2;
@ -245,7 +226,7 @@ $._farbtastic = function (container, options) {
var ctx = buffer.getContext('2d'); var ctx = buffer.getContext('2d');
var frame = ctx.getImageData(0, 0, sz + 1, sz + 1); var frame = ctx.getImageData(0, 0, sz + 1, sz + 1);
var i = 0; let i = 0;
calculateMask(sz, sz, function (x, y, c, a) { calculateMask(sz, sz, function (x, y, c, a) {
frame.data[i++] = frame.data[i++] = frame.data[i++] = c * 255; frame.data[i++] = frame.data[i++] = frame.data[i++] = c * 255;
frame.data[i++] = a * 255; frame.data[i++] = a * 255;
@ -320,7 +301,7 @@ $._farbtastic = function (container, options) {
// Update the overlay canvas. // Update the overlay canvas.
fb.ctxOverlay.clearRect(-fb.mid, -fb.mid, sz, sz); fb.ctxOverlay.clearRect(-fb.mid, -fb.mid, sz, sz);
for (i in circles) { for (let i in circles) {
var c = circles[i]; var c = circles[i];
fb.ctxOverlay.lineWidth = c.lw; fb.ctxOverlay.lineWidth = c.lw;
fb.ctxOverlay.strokeStyle = c.c; fb.ctxOverlay.strokeStyle = c.c;

View file

@ -1,11 +1,5 @@
'use strict'; 'use strict';
/**
* This code is mostly from the old Etherpad. Please help us to comment this code.
* This helps other people to understand this code better and helps them to improve it.
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
*/
/** /**
* Copyright 2009 Google Inc. * Copyright 2009 Google Inc.
* *
@ -546,7 +540,6 @@ const paduserlist = (function () {
} }
$('#myswatch').css({'background-color': myUserInfo.colorId}); $('#myswatch').css({'background-color': myUserInfo.colorId});
$('li[data-key=showusers] > a').css({'box-shadow': `inset 0 0 30px ${myUserInfo.colorId}`}); $('li[data-key=showusers] > a').css({'box-shadow': `inset 0 0 30px ${myUserInfo.colorId}`});
}, },
}; };