Added rollup config.
0
src/bin/buildDebian.sh
Executable file → Normal file
0
src/bin/buildForWindows.sh
Executable file → Normal file
0
src/bin/cleanRun.sh
Executable file → Normal file
0
src/bin/createRelease.sh
Executable file → Normal file
0
src/bin/deb-src/DEBIAN/postinst
Executable file → Normal file
0
src/bin/deb-src/DEBIAN/preinst
Executable file → Normal file
0
src/bin/deb-src/DEBIAN/prerm
Executable file → Normal file
0
src/bin/debugRun.sh
Executable file → Normal file
0
src/bin/etherpad-healthcheck
Executable file → Normal file
0
src/bin/fastRun.sh
Executable file → Normal file
0
src/bin/installDeps.sh
Executable file → Normal file
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 0 B |
0
src/bin/plugins/README.md
Executable file → Normal file
0
src/bin/plugins/checkPlugin.js
Executable file → Normal file
0
src/bin/plugins/getCorePlugins.sh
Executable file → Normal file
0
src/bin/plugins/lib/README.md
Executable file → Normal file
0
src/bin/plugins/lib/gitignore
Executable file → Normal file
0
src/bin/plugins/listOfficialPlugins
Executable file → Normal file
0
src/bin/plugins/reTestAllPlugins.sh
Executable file → Normal file
0
src/bin/plugins/updateAllPluginsScript.sh
Executable file → Normal file
0
src/bin/plugins/updateCorePlugins.sh
Executable file → Normal file
0
src/bin/run.sh
Executable file → Normal file
0
src/bin/safeRun.sh
Executable file → Normal file
0
src/bin/updatePlugins.sh
Executable file → Normal file
|
@ -21,7 +21,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import ueberDB from 'ueberdb2';
|
||||
import {Database} from 'ueberdb2';
|
||||
import {dbSettings, dbType} from '../utils/Settings';
|
||||
import log4js from 'log4js';
|
||||
import {shutdown as statsShutdown,createCollection} from '../stats';
|
||||
|
@ -37,7 +37,7 @@ let db = null;
|
|||
* Initializes the database with the settings provided by the settings module
|
||||
*/
|
||||
const init = async () => {
|
||||
db = new ueberDB.Database(dbType, dbSettings, null, logger);
|
||||
db = new Database(dbType, dbSettings, null, logger);
|
||||
await db.init();
|
||||
if (db.metrics != null) {
|
||||
for (const [metric, value] of Object.entries(db.metrics)) {
|
||||
|
|
|
@ -34,6 +34,12 @@ import {checkDeprecationStatus, enforceMinNodeVersion} from './utils/NodeVersion
|
|||
import {Gate} from './utils/promises';
|
||||
import * as UpdateCheck from "./utils/UpdateCheck";
|
||||
import {Plugin} from "./models/Plugin";
|
||||
import {db} from './db/DB'
|
||||
import {createServer, server} from './hooks/express';
|
||||
import {aCallAll} from '../static/js/pluginfw/hooks'
|
||||
import * as pluginDefs from '../static/js/pluginfw/plugin_defs'
|
||||
import * as plugins from "../static/js/pluginfw/plugins";
|
||||
import {createCollection} from "./stats";
|
||||
|
||||
let wtfnode;
|
||||
if (settings.dumpOnUncleanExit) {
|
||||
|
@ -45,13 +51,6 @@ if (settings.dumpOnUncleanExit) {
|
|||
enforceMinNodeVersion('12.17.0');
|
||||
checkDeprecationStatus('12.17.0', '1.9.0');
|
||||
|
||||
import db = require('./db/DB');
|
||||
import {} from './db/DB'
|
||||
import {createServer, server} from './hooks/express';
|
||||
import hooks = require('../static/js/pluginfw/hooks');
|
||||
import pluginDefs = require('../static/js/pluginfw/plugin_defs');
|
||||
import plugins = require('../static/js/pluginfw/plugins');
|
||||
import {createCollection} from "./stats";
|
||||
const logger = log4js.getLogger('server');
|
||||
console.log = logger.info.bind(logger); // do the same for others - console.debug, etc.
|
||||
|
||||
|
@ -149,8 +148,8 @@ export const start = async () => {
|
|||
logger.info(`Installed plugins: ${installedPlugins}`);
|
||||
logger.debug(`Installed parts:\n${plugins.formatParts()}`);
|
||||
logger.debug(`Installed server-side hooks:\n${plugins.formatHooks('hooks', false)}`);
|
||||
await hooks.aCallAll('loadSettings', {settings});
|
||||
await hooks.aCallAll(createServer());
|
||||
await aCallAll('loadSettings', {settings});
|
||||
await aCallAll(createServer());
|
||||
} catch (err) {
|
||||
logger.error('Error occurred while starting Etherpad');
|
||||
state = State.STATE_TRANSITION_FAILED;
|
||||
|
@ -191,7 +190,7 @@ export const stop = async () => {
|
|||
try {
|
||||
let timeout = null;
|
||||
await Promise.race([
|
||||
hooks.aCallAll('shutdown'),
|
||||
aCallAll('shutdown'),
|
||||
new Promise((resolve, reject) => {
|
||||
timeout = setTimeout(() => reject(new Error('Timed out waiting for shutdown tasks')), 3000);
|
||||
}),
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
import exp from "constants";
|
||||
// FIXME Is there a better way to enter dynamic package.json path
|
||||
// @ts-ignore
|
||||
import packageJSON from '../../../package.json'
|
||||
import packageJSON from '../../package.json'
|
||||
import {findEtherpadRoot, makeAbsolute, isSubdir} from './AbsolutePaths';
|
||||
import deepEqual from 'fast-deep-equal/es6';
|
||||
import fs from 'fs';
|
||||
|
|
|
@ -145,7 +145,9 @@ const run_cmd = (args, opts:RunOpts = {
|
|||
|
||||
let px;
|
||||
const p = new Promise<string>((resolve, reject) => { px = {resolve, reject}; });
|
||||
// @ts-ignore
|
||||
[, p.stdout, p.stderr] = streams;
|
||||
// @ts-ignore
|
||||
p.child = proc;
|
||||
|
||||
const stdioStringPromises = [undefined, Promise.resolve(), Promise.resolve()];
|
||||
|
|
21460
src/package-lock.json
generated
|
@ -30,6 +30,7 @@
|
|||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@rollup/plugin-json": "^6.0.0",
|
||||
"async": "^3.2.2",
|
||||
"cjstoesm": "^2.1.2",
|
||||
"clean-css": "^5.3.2",
|
||||
|
@ -104,7 +105,9 @@
|
|||
"sinon": "^13.0.2",
|
||||
"split-grid": "^1.0.11",
|
||||
"supertest": "^6.3.3",
|
||||
"typescript": "^4.9.5"
|
||||
"typescript": "^4.9.5",
|
||||
"rollup-plugin-typescript2": "^0.35.0",
|
||||
"rollup-plugin-copy": "^3.4.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.15.0",
|
||||
|
@ -118,7 +121,8 @@
|
|||
"lint": "eslint .",
|
||||
"test": "mocha --require @babel/register --timeout 120000 --recursive tests/backend/specs ../node_modules/ep_*/static/tests/backend/specs",
|
||||
"test-container": "mocha --timeout 5000 tests/container/specs/api",
|
||||
"dev": "concurrently \"npx tsc --watch\" \"nodemon -q dist/server.js\""
|
||||
"dev": "concurrently \"npx tsc --watch\" \"nodemon -q dist/server.js\"",
|
||||
"build": "npx rollup -c rollup.config.js"
|
||||
},
|
||||
"version": "1.9.0",
|
||||
"license": "Apache-2.0"
|
||||
|
|
28
src/rollup.config.js
Normal file
|
@ -0,0 +1,28 @@
|
|||
const typescript = require('rollup-plugin-typescript2');
|
||||
const copy = require('rollup-plugin-copy');
|
||||
const glob = require('glob');
|
||||
const json = require('@rollup/plugin-json')
|
||||
module.exports = {
|
||||
input: glob.sync('./node/**/*.ts'), // Matches all TypeScript files in the 'src' directory and its subdirectories
|
||||
output: {
|
||||
preserveModules: true,
|
||||
dir: './dist',
|
||||
format: 'cjs',
|
||||
},
|
||||
plugins: [
|
||||
json(),
|
||||
typescript({
|
||||
tsconfig: 'tsconfig.json',
|
||||
}),
|
||||
copy({
|
||||
targets: [
|
||||
{src:'./package.json', dest:'./dist'},
|
||||
{ src: './LICENSE', dest: './dist' },
|
||||
{ src: './src/locales/*', dest: './dist/locales' },
|
||||
{ src: './src/static/css/*', dest: './dist/static/css' },
|
||||
{ src: './src/templates', dest: './dist/templates' },
|
||||
{src:'./ep.json', dest:'./dist'},
|
||||
]
|
||||
})
|
||||
],
|
||||
};
|
Before Width: | Height: | Size: 660 B After Width: | Height: | Size: 0 B |
0
src/static/img/brand.svg
Executable file → Normal file
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
|
@ -1,139 +1,139 @@
|
|||
// Autosize 1.13 - jQuery plugin for textareas
|
||||
// (c) 2012 Jack Moore - jacklmoore.com
|
||||
// license: www.opensource.org/licenses/mit-license.php
|
||||
(function ($) {
|
||||
var defaults = {
|
||||
className: 'autosizejs',
|
||||
append: "",
|
||||
callback: false
|
||||
}, hidden = 'hidden', borderBox = 'border-box', lineHeight = 'lineHeight', copy = '<textarea tabindex="-1" style="position:absolute; top:-9999px; left:-9999px; right:auto; bottom:auto; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden;"/>',
|
||||
// line-height is omitted because IE7/IE8 doesn't return the correct value.
|
||||
copyStyle = [
|
||||
'fontFamily',
|
||||
'fontSize',
|
||||
'fontWeight',
|
||||
'fontStyle',
|
||||
'letterSpacing',
|
||||
'textTransform',
|
||||
'wordSpacing',
|
||||
'textIndent'
|
||||
], oninput = 'oninput', onpropertychange = 'onpropertychange', test = $(copy)[0];
|
||||
// For testing support in old FireFox
|
||||
test.setAttribute(oninput, "return");
|
||||
if ($.isFunction(test[oninput]) || onpropertychange in test) {
|
||||
// test that line-height can be accurately copied to avoid
|
||||
// incorrect value reporting in old IE and old Opera
|
||||
$(test).css(lineHeight, '99px');
|
||||
if ($(test).css(lineHeight) === '99px') {
|
||||
copyStyle.push(lineHeight);
|
||||
}
|
||||
$.fn.autosize = function (options) {
|
||||
options = $.extend({}, defaults, options || {});
|
||||
return this.each(function () {
|
||||
var ta = this, $ta = $(ta), mirror, minHeight = $ta.height(), maxHeight = parseInt($ta.css('maxHeight'), 10), active, i = copyStyle.length, resize, boxOffset = 0, value = ta.value, callback = $.isFunction(options.callback);
|
||||
if ($ta.css('box-sizing') === borderBox || $ta.css('-moz-box-sizing') === borderBox || $ta.css('-webkit-box-sizing') === borderBox) {
|
||||
boxOffset = $ta.outerHeight() - $ta.height();
|
||||
}
|
||||
if ($ta.data('mirror') || $ta.data('ismirror')) {
|
||||
// if autosize has already been applied, exit.
|
||||
// if autosize is being applied to a mirror element, exit.
|
||||
return;
|
||||
}
|
||||
else {
|
||||
mirror = $(copy).data('ismirror', true).addClass(options.className)[0];
|
||||
resize = $ta.css('resize') === 'none' ? 'none' : 'horizontal';
|
||||
$ta.data('mirror', $(mirror)).css({
|
||||
overflow: hidden,
|
||||
overflowY: hidden,
|
||||
wordWrap: 'break-word',
|
||||
resize: resize
|
||||
});
|
||||
}
|
||||
// Opera returns '-1px' when max-height is set to 'none'.
|
||||
maxHeight = maxHeight && maxHeight > 0 ? maxHeight : 9e4;
|
||||
// Using mainly bare JS in this function because it is going
|
||||
// to fire very often while typing, and needs to very efficient.
|
||||
function adjust() {
|
||||
var height, overflow, original;
|
||||
// the active flag keeps IE from tripping all over itself. Otherwise
|
||||
// actions in the adjust function will cause IE to call adjust again.
|
||||
if (!active) {
|
||||
active = true;
|
||||
mirror.value = ta.value + options.append;
|
||||
mirror.style.overflowY = ta.style.overflowY;
|
||||
original = parseInt(ta.style.height, 10);
|
||||
// Update the width in case the original textarea width has changed
|
||||
mirror.style.width = $ta.css('width');
|
||||
// Needed for IE to reliably return the correct scrollHeight
|
||||
mirror.scrollTop = 0;
|
||||
// Set a very high value for scrollTop to be sure the
|
||||
// mirror is scrolled all the way to the bottom.
|
||||
mirror.scrollTop = 9e4;
|
||||
height = mirror.scrollTop;
|
||||
overflow = hidden;
|
||||
if (height > maxHeight) {
|
||||
height = maxHeight;
|
||||
overflow = 'scroll';
|
||||
}
|
||||
else if (height < minHeight) {
|
||||
height = minHeight;
|
||||
}
|
||||
height += boxOffset;
|
||||
ta.style.overflowY = overflow;
|
||||
if (original !== height) {
|
||||
ta.style.height = height + 'px';
|
||||
if (callback) {
|
||||
options.callback.call(ta);
|
||||
}
|
||||
}
|
||||
// This small timeout gives IE a chance to draw it's scrollbar
|
||||
// before adjust can be run again (prevents an infinite loop).
|
||||
setTimeout(function () {
|
||||
active = false;
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
// mirror is a duplicate textarea located off-screen that
|
||||
// is automatically updated to contain the same text as the
|
||||
// original textarea. mirror always has a height of 0.
|
||||
// This gives a cross-browser supported way getting the actual
|
||||
// height of the text, through the scrollTop property.
|
||||
while (i--) {
|
||||
mirror.style[copyStyle[i]] = $ta.css(copyStyle[i]);
|
||||
}
|
||||
$('body').append(mirror);
|
||||
if (onpropertychange in ta) {
|
||||
if (oninput in ta) {
|
||||
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
|
||||
// so binding to onkeyup to catch most of those occassions. There is no way that I
|
||||
// know of to detect something like 'cut' in IE9.
|
||||
ta[oninput] = ta.onkeyup = adjust;
|
||||
}
|
||||
else {
|
||||
// IE7 / IE8
|
||||
ta[onpropertychange] = adjust;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Modern Browsers
|
||||
ta[oninput] = adjust;
|
||||
// The textarea overflow is now hidden. But Chrome doesn't reflow the text after the scrollbars are removed.
|
||||
// This is a hack to get Chrome to reflow it's text.
|
||||
ta.value = '';
|
||||
ta.value = value;
|
||||
}
|
||||
$(window).resize(adjust);
|
||||
// Allow for manual triggering if needed.
|
||||
$ta.bind('autosize', adjust);
|
||||
// Call adjust in case the textarea already contains text.
|
||||
adjust();
|
||||
});
|
||||
};
|
||||
}
|
||||
else {
|
||||
// Makes no changes for older browsers (FireFox3- and Safari4-)
|
||||
$.fn.autosize = function (callback) {
|
||||
return this;
|
||||
};
|
||||
}
|
||||
}(jQuery));
|
||||
// Autosize 1.13 - jQuery plugin for textareas
|
||||
// (c) 2012 Jack Moore - jacklmoore.com
|
||||
// license: www.opensource.org/licenses/mit-license.php
|
||||
(function ($) {
|
||||
var defaults = {
|
||||
className: 'autosizejs',
|
||||
append: "",
|
||||
callback: false
|
||||
}, hidden = 'hidden', borderBox = 'border-box', lineHeight = 'lineHeight', copy = '<textarea tabindex="-1" style="position:absolute; top:-9999px; left:-9999px; right:auto; bottom:auto; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden;"/>',
|
||||
// line-height is omitted because IE7/IE8 doesn't return the correct value.
|
||||
copyStyle = [
|
||||
'fontFamily',
|
||||
'fontSize',
|
||||
'fontWeight',
|
||||
'fontStyle',
|
||||
'letterSpacing',
|
||||
'textTransform',
|
||||
'wordSpacing',
|
||||
'textIndent'
|
||||
], oninput = 'oninput', onpropertychange = 'onpropertychange', test = $(copy)[0];
|
||||
// For testing support in old FireFox
|
||||
test.setAttribute(oninput, "return");
|
||||
if ($.isFunction(test[oninput]) || onpropertychange in test) {
|
||||
// test that line-height can be accurately copied to avoid
|
||||
// incorrect value reporting in old IE and old Opera
|
||||
$(test).css(lineHeight, '99px');
|
||||
if ($(test).css(lineHeight) === '99px') {
|
||||
copyStyle.push(lineHeight);
|
||||
}
|
||||
$.fn.autosize = function (options) {
|
||||
options = $.extend({}, defaults, options || {});
|
||||
return this.each(function () {
|
||||
var ta = this, $ta = $(ta), mirror, minHeight = $ta.height(), maxHeight = parseInt($ta.css('maxHeight'), 10), active, i = copyStyle.length, resize, boxOffset = 0, value = ta.value, callback = $.isFunction(options.callback);
|
||||
if ($ta.css('box-sizing') === borderBox || $ta.css('-moz-box-sizing') === borderBox || $ta.css('-webkit-box-sizing') === borderBox) {
|
||||
boxOffset = $ta.outerHeight() - $ta.height();
|
||||
}
|
||||
if ($ta.data('mirror') || $ta.data('ismirror')) {
|
||||
// if autosize has already been applied, exit.
|
||||
// if autosize is being applied to a mirror element, exit.
|
||||
return;
|
||||
}
|
||||
else {
|
||||
mirror = $(copy).data('ismirror', true).addClass(options.className)[0];
|
||||
resize = $ta.css('resize') === 'none' ? 'none' : 'horizontal';
|
||||
$ta.data('mirror', $(mirror)).css({
|
||||
overflow: hidden,
|
||||
overflowY: hidden,
|
||||
wordWrap: 'break-word',
|
||||
resize: resize
|
||||
});
|
||||
}
|
||||
// Opera returns '-1px' when max-height is set to 'none'.
|
||||
maxHeight = maxHeight && maxHeight > 0 ? maxHeight : 9e4;
|
||||
// Using mainly bare JS in this function because it is going
|
||||
// to fire very often while typing, and needs to very efficient.
|
||||
function adjust() {
|
||||
var height, overflow, original;
|
||||
// the active flag keeps IE from tripping all over itself. Otherwise
|
||||
// actions in the adjust function will cause IE to call adjust again.
|
||||
if (!active) {
|
||||
active = true;
|
||||
mirror.value = ta.value + options.append;
|
||||
mirror.style.overflowY = ta.style.overflowY;
|
||||
original = parseInt(ta.style.height, 10);
|
||||
// Update the width in case the original textarea width has changed
|
||||
mirror.style.width = $ta.css('width');
|
||||
// Needed for IE to reliably return the correct scrollHeight
|
||||
mirror.scrollTop = 0;
|
||||
// Set a very high value for scrollTop to be sure the
|
||||
// mirror is scrolled all the way to the bottom.
|
||||
mirror.scrollTop = 9e4;
|
||||
height = mirror.scrollTop;
|
||||
overflow = hidden;
|
||||
if (height > maxHeight) {
|
||||
height = maxHeight;
|
||||
overflow = 'scroll';
|
||||
}
|
||||
else if (height < minHeight) {
|
||||
height = minHeight;
|
||||
}
|
||||
height += boxOffset;
|
||||
ta.style.overflowY = overflow;
|
||||
if (original !== height) {
|
||||
ta.style.height = height + 'px';
|
||||
if (callback) {
|
||||
options.callback.call(ta);
|
||||
}
|
||||
}
|
||||
// This small timeout gives IE a chance to draw it's scrollbar
|
||||
// before adjust can be run again (prevents an infinite loop).
|
||||
setTimeout(function () {
|
||||
active = false;
|
||||
}, 1);
|
||||
}
|
||||
}
|
||||
// mirror is a duplicate textarea located off-screen that
|
||||
// is automatically updated to contain the same text as the
|
||||
// original textarea. mirror always has a height of 0.
|
||||
// This gives a cross-browser supported way getting the actual
|
||||
// height of the text, through the scrollTop property.
|
||||
while (i--) {
|
||||
mirror.style[copyStyle[i]] = $ta.css(copyStyle[i]);
|
||||
}
|
||||
$('body').append(mirror);
|
||||
if (onpropertychange in ta) {
|
||||
if (oninput in ta) {
|
||||
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
|
||||
// so binding to onkeyup to catch most of those occassions. There is no way that I
|
||||
// know of to detect something like 'cut' in IE9.
|
||||
ta[oninput] = ta.onkeyup = adjust;
|
||||
}
|
||||
else {
|
||||
// IE7 / IE8
|
||||
ta[onpropertychange] = adjust;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Modern Browsers
|
||||
ta[oninput] = adjust;
|
||||
// The textarea overflow is now hidden. But Chrome doesn't reflow the text after the scrollbars are removed.
|
||||
// This is a hack to get Chrome to reflow it's text.
|
||||
ta.value = '';
|
||||
ta.value = value;
|
||||
}
|
||||
$(window).resize(adjust);
|
||||
// Allow for manual triggering if needed.
|
||||
$ta.bind('autosize', adjust);
|
||||
// Call adjust in case the textarea already contains text.
|
||||
adjust();
|
||||
});
|
||||
};
|
||||
}
|
||||
else {
|
||||
// Makes no changes for older browsers (FireFox3- and Safari4-)
|
||||
$.fn.autosize = function (callback) {
|
||||
return this;
|
||||
};
|
||||
}
|
||||
}(jQuery));
|
||||
|
|
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 95 KiB After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 355 KiB After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 635 B After Width: | Height: | Size: 0 B |
Before Width: | Height: | Size: 419 B After Width: | Height: | Size: 0 B |
0
src/tests/frontend/specs/admintroubleshooting.js
Executable file → Normal file
0
src/tests/frontend/specs/adminupdateplugins.js
Executable file → Normal file
0
src/tests/frontend/specs/multiple_authors_clear_authorship_colors.js
Executable file → Normal file
0
src/tests/frontend/specs/scrollTo.js
Executable file → Normal file
0
src/tests/frontend/travis/adminrunner.sh
Executable file → Normal file
0
src/tests/frontend/travis/runner.sh
Executable file → Normal file
0
src/tests/frontend/travis/runnerBackend.sh
Executable file → Normal file
0
src/tests/frontend/travis/runnerLoadTest.sh
Executable file → Normal file
0
src/tests/ratelimit/testlimits.sh
Executable file → Normal file
|
@ -4,12 +4,13 @@
|
|||
"allowJs": true,
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"types": ["node", "jquery"],
|
||||
"module": "commonjs",
|
||||
"module": "esnext",
|
||||
"esModuleInterop": true,
|
||||
"moduleResolution": "node",
|
||||
"sourceMap": true,
|
||||
"target": "ES2015",
|
||||
"outDir": "dist"
|
||||
},
|
||||
"exclude": ["node_modules"],
|
||||
"lib": ["es2015"]
|
||||
}
|
||||
|
|
22
start.bat
|
@ -1,11 +1,11 @@
|
|||
@echo off
|
||||
REM Windows and symlinks do not get along with each other, so on Windows
|
||||
REM `node_modules\ep_etherpad-lite` is sometimes a full copy of `src` not a
|
||||
REM symlink to `src`. If it is a copy, Node.js sees `src\foo.js` and
|
||||
REM `node_modules\ep_etherpad-lite\foo.js` as two independent modules with
|
||||
REM independent state, when they should be treated as the same file. To work
|
||||
REM around this, everything must consistently use either `src` or
|
||||
REM `node_modules\ep_etherpad-lite` on Windows. Because some plugins access
|
||||
REM Etherpad internals via `require('ep_etherpad-lite/foo')`,
|
||||
REM `node_modules\ep_etherpad-lite` is used here.
|
||||
node node_modules\ep_etherpad-lite\node\server.js
|
||||
@echo off
|
||||
REM Windows and symlinks do not get along with each other, so on Windows
|
||||
REM `node_modules\ep_etherpad-lite` is sometimes a full copy of `src` not a
|
||||
REM symlink to `src`. If it is a copy, Node.js sees `src\foo.js` and
|
||||
REM `node_modules\ep_etherpad-lite\foo.js` as two independent modules with
|
||||
REM independent state, when they should be treated as the same file. To work
|
||||
REM around this, everything must consistently use either `src` or
|
||||
REM `node_modules\ep_etherpad-lite` on Windows. Because some plugins access
|
||||
REM Etherpad internals via `require('ep_etherpad-lite/foo')`,
|
||||
REM `node_modules\ep_etherpad-lite` is used here.
|
||||
node node_modules\ep_etherpad-lite\node\server.js
|
||||
|
|