client/js: format code to ESLint

This commit is contained in:
Shyam Sunder 2020-06-04 14:09:35 -04:00
parent 48c9001194
commit 4329b1620f
67 changed files with 1150 additions and 533 deletions

293
client/.eslintrc.yml Normal file
View file

@ -0,0 +1,293 @@
env:
browser: true
commonjs: true
es6: true
extends: 'eslint:recommended'
globals:
Atomics: readonly
SharedArrayBuffer: readonly
ignorePatterns:
- build.js
parserOptions:
ecmaVersion: 11
rules:
accessor-pairs: error
array-bracket-newline: error
array-bracket-spacing:
- error
- never
array-callback-return: error
array-element-newline: 'off'
arrow-body-style: 'off'
arrow-parens:
- error
- as-needed
arrow-spacing:
- error
- after: true
before: true
block-scoped-var: error
block-spacing: error
brace-style:
- error
- 1tbs
callback-return: 'off'
camelcase: error
class-methods-use-this: 'off'
comma-dangle: 'off'
comma-spacing:
- error
- after: true
before: false
comma-style:
- error
- last
complexity: 'off'
computed-property-spacing:
- error
- never
consistent-return: 'off'
consistent-this: 'off'
curly: error
default-case: error
default-case-last: error
default-param-last: error
dot-location:
- error
- property
dot-notation:
- error
- allowKeywords: true
eol-last: error
eqeqeq: error
func-call-spacing: error
func-name-matching: error
func-names: error
func-style:
- error
- declaration
- allowArrowFunctions: true
function-call-argument-newline:
- error
- consistent
function-paren-newline: 'off'
generator-star-spacing: error
global-require: 'off'
grouped-accessor-pairs: 'off'
guard-for-in: error
handle-callback-err: error
id-blacklist: error
id-length: 'off'
id-match: error
implicit-arrow-linebreak:
- error
- beside
indent:
- error
- 4
indent-legacy: 'off'
init-declarations: error
jsx-quotes: error
key-spacing: error
keyword-spacing:
- error
- after: true
before: true
line-comment-position: 'off'
linebreak-style:
- error
- unix
lines-around-comment: error
lines-around-directive: error
lines-between-class-members:
- error
- always
max-classes-per-file: 'off'
max-depth: error
max-len: 'off'
max-lines: 'off'
max-lines-per-function: 'off'
max-nested-callbacks: error
max-params: 'off'
max-statements: 'off'
max-statements-per-line: error
multiline-comment-style:
- error
- separate-lines
multiline-ternary: 'off'
new-cap: error
new-parens: error
newline-after-var: 'off'
newline-before-return: 'off'
newline-per-chained-call: 'off'
no-alert: 'off'
no-array-constructor: error
no-await-in-loop: error
no-bitwise: 'off'
no-buffer-constructor: 'off'
no-caller: error
no-catch-shadow: error
no-confusing-arrow: error
no-console: error
no-constructor-return: error
no-continue: 'off'
no-div-regex: 'off'
no-duplicate-imports: error
no-else-return: 'off'
no-empty-function: 'off'
no-eq-null: error
no-eval: error
no-extend-native: error
no-extra-bind: error
no-extra-label: error
no-extra-parens: 'off'
no-floating-decimal: error
no-implicit-globals: error
no-implied-eval: error
no-inline-comments: 'off'
no-invalid-this: error
no-iterator: error
no-label-var: error
no-labels: error
no-lone-blocks: error
no-lonely-if: error
no-loop-func: 'off'
no-loss-of-precision: error
no-magic-numbers: 'off'
no-mixed-operators: error
no-mixed-requires: error
no-multi-assign: error
no-multi-spaces:
- error
- ignoreEOLComments: true
no-multi-str: error
no-multiple-empty-lines: error
no-native-reassign: error
no-negated-condition: 'off'
no-negated-in-lhs: error
no-nested-ternary: error
no-new: 'off'
no-new-func: error
no-new-object: error
no-new-require: error
no-new-wrappers: error
no-octal-escape: error
no-param-reassign: 'off'
no-path-concat: error
no-plusplus: 'off'
no-process-env: error
no-process-exit: error
no-proto: error
no-restricted-exports: error
no-restricted-globals: error
no-restricted-imports: error
no-restricted-modules: error
no-restricted-properties: error
no-restricted-syntax: error
no-return-assign: error
no-return-await: error
no-script-url: error
no-self-compare: error
no-sequences: error
no-shadow: 'off'
no-spaced-func: error
no-sync: error
no-tabs: error
no-template-curly-in-string: error
no-ternary: 'off'
no-throw-literal: 'off'
no-trailing-spaces: error
no-undef-init: error
no-undefined: 'off'
no-underscore-dangle: 'off'
no-unmodified-loop-condition: error
no-unneeded-ternary: error
no-unused-expressions: error
no-unused-vars: 'off'
no-use-before-define: 'off'
no-useless-backreference: error
no-useless-call: error
no-useless-computed-key: error
no-useless-concat: error
no-useless-constructor: error
no-useless-escape: 'off'
no-useless-rename: error
no-useless-return: error
no-var: 'off'
no-void: error
no-warning-comments: warn
no-whitespace-before-property: error
nonblock-statement-body-position: error
object-curly-newline: error
object-curly-spacing:
- error
- never
object-shorthand: 'off'
one-var: 'off'
one-var-declaration-per-line: error
operator-assignment:
- error
- always
operator-linebreak: 'off'
padded-blocks: 'off'
padding-line-between-statements: error
prefer-arrow-callback: error
prefer-const: 'off'
prefer-destructuring: 'off'
prefer-exponentiation-operator: 'off'
prefer-named-capture-group: 'off'
prefer-numeric-literals: error
prefer-object-spread: 'off'
prefer-promise-reject-errors: 'off'
prefer-reflect: 'off'
prefer-regex-literals: warn
prefer-rest-params: 'off'
prefer-spread: 'off'
prefer-template: 'off'
quote-props: 'off'
quotes: 'off'
radix:
- error
- as-needed
require-atomic-updates: error
require-await: error
require-jsdoc: 'off'
require-unicode-regexp: 'off'
rest-spread-spacing: error
semi: 'off'
semi-spacing:
- error
- after: true
before: false
semi-style:
- error
- last
sort-imports: error
sort-keys: 'off'
sort-vars: error
space-before-blocks: error
space-before-function-paren: 'off'
space-in-parens:
- error
- never
space-infix-ops: error
space-unary-ops: error
spaced-comment:
- error
- always
strict: error
switch-colon-spacing: error
symbol-description: error
template-curly-spacing:
- error
- never
template-tag-spacing: error
unicode-bom:
- error
- never
valid-jsdoc: error
vars-on-top: error
wrap-iife: error
wrap-regex: error
yield-star-spacing: error
yoda: 'off'

View file

@ -377,8 +377,9 @@ class Api extends events.EventTarget {
try {
if (this.userName && this.token) {
req.auth = null;
req.set('Authorization', 'Token '
+ new Buffer(this.userName + ":" + this.token).toString('base64'))
// eslint-disable-next-line no-undef
req.set('Authorization', 'Token ' + new Buffer(
this.userName + ":" + this.token).toString('base64'))
} else if (this.userName && this.userPassword) {
req.auth(
this.userName,

View file

@ -34,7 +34,9 @@ class CommentsController {
requestPage: (offset, limit) => {
return PostList.search(
'sort:comment-date comment-count-min:1',
offset, limit, fields);
offset,
limit,
fields);
},
pageRenderer: pageCtx => {
Object.assign(pageCtx, {
@ -68,9 +70,10 @@ class CommentsController {
e.detail.comment.delete()
.catch(error => window.alert(error.message));
}
};
}
module.exports = router => {
router.enter(['comments'],
(ctx, next) => { new CommentsController(ctx); });
};
router.enter(['comments'], (ctx, next) => {
new CommentsController(ctx);
});
}

View file

@ -41,10 +41,10 @@ class HomeController {
showError(message) {
this._homeView.showError(message);
}
};
}
module.exports = router => {
router.enter([], (ctx, next) => {
ctx.controller = new HomeController();
});
};
}

View file

@ -9,10 +9,10 @@ class NotFoundController {
topNavigation.setTitle('Not found');
this._notFoundView = new NotFoundView(path);
}
};
}
module.exports = router => {
router.enter(null, (ctx, next) => {
ctx.controller = new NotFoundController(ctx.canonicalPath);
});
};
}

View file

@ -57,7 +57,8 @@ class PostDetailController extends BasePostController {
if (this._id !== e.detail.post.id) {
router.replace(
uri.formatClientLink('post', e.detail.post.id, section),
null, false);
null,
false);
}
}
@ -71,7 +72,8 @@ class PostDetailController extends BasePostController {
router.replace(
uri.formatClientLink(
'post', e.detail.targetPost.id, 'merge'),
null, false);
null,
false);
}, error => {
this._view.showError(error.message);
this._view.enableForm();

View file

@ -13,7 +13,8 @@ const EmptyView = require('../views/empty_view.js');
const fields = [
'id', 'thumbnailUrl', 'type', 'safety',
'score', 'favoriteCount', 'commentCount', 'tags', 'version'];
'score', 'favoriteCount', 'commentCount', 'tags', 'version'
];
class PostListController {
constructor(ctx) {
@ -62,8 +63,7 @@ class PostListController {
_evtTag(e) {
Promise.all(
this._bulkEditTags.map(tag =>
e.detail.post.tags.addByName(tag)))
this._bulkEditTags.map(tag => e.detail.post.tags.addByName(tag)))
.then(e.detail.post.save())
.catch(error => window.alert(error.message));
}
@ -117,5 +117,7 @@ class PostListController {
module.exports = router => {
router.enter(
['posts'],
(ctx, next) => { ctx.controller = new PostListController(ctx); });
(ctx, next) => {
ctx.controller = new PostListController(ctx);
});
};

View file

@ -57,8 +57,7 @@ class PostUploadController {
this._view.clearMessages();
e.detail.uploadables.reduce(
(promise, uploadable) =>
promise.then(() => this._uploadSinglePost(
(promise, uploadable) => promise.then(() => this._uploadSinglePost(
uploadable, e.detail.skipDuplicates)),
Promise.resolve())
.then(() => {
@ -153,7 +152,9 @@ class PostUploadController {
post.newContent = uploadable.url || uploadable.file;
// if uploadable.source is ever going to be a valid field (e.g when setting source directly in the upload window)
// you'll need to change the line below to `post.source = uploadable.source || uploadable.url;`
if (uploadable.url) post.source = uploadable.url;
if (uploadable.url) {
post.source = uploadable.url;
}
return post;
}
}

View file

@ -19,7 +19,7 @@ class SettingsController {
settings.save(e.detail);
this._view.showSuccess('Settings saved.');
}
};
}
module.exports = router => {
router.enter(['settings'], (ctx, next) => {

View file

@ -45,5 +45,7 @@ class SnapshotsController {
module.exports = router => {
router.enter(['history'],
(ctx, next) => { ctx.controller = new SnapshotsController(ctx); });
(ctx, next) => {
ctx.controller = new SnapshotsController(ctx);
});
};

View file

@ -69,7 +69,8 @@ class TagController {
if (this._name !== e.detail.tag.names[0]) {
router.replace(
uri.formatClientLink('tag', e.detail.tag.names[0], section),
null, false);
null,
false);
}
}
@ -105,7 +106,8 @@ class TagController {
router.replace(
uri.formatClientLink(
'tag', e.detail.targetTagName, 'merge'),
null, false);
null,
false);
}, error => {
this._view.showError(error.message);
this._view.enableForm();

View file

@ -16,7 +16,8 @@ const fields = [
'implications',
'creationTime',
'usages',
'category'];
'category'
];
class TagListController {
constructor(ctx) {
@ -81,5 +82,7 @@ class TagListController {
module.exports = router => {
router.enter(
['tags'],
(ctx, next) => { ctx.controller = new TagListController(ctx); });
(ctx, next) => {
ctx.controller = new TagListController(ctx);
});
};

View file

@ -133,7 +133,8 @@ class UserController {
if (this._name !== e.detail.user.name) {
router.replace(
uri.formatClientLink('user', e.detail.user.name, section),
null, false);
null,
false);
}
}

View file

@ -51,7 +51,7 @@ class UserListController {
defaultLimit: 30,
getClientUrlForPage: (offset, limit) => {
const parameters = Object.assign(
{}, this._ctx.parameters, {offset, offset, limit: limit});
{}, this._ctx.parameters, {offset: offset, limit: limit});
return uri.formatClientLink('users', parameters);
},
requestPage: (offset, limit) => {
@ -71,5 +71,7 @@ class UserListController {
module.exports = router => {
router.enter(
['users'],
(ctx, next) => { ctx.controller = new UserListController(ctx); });
(ctx, next) => {
ctx.controller = new UserListController(ctx);
});
};

View file

@ -121,7 +121,9 @@ class AutoCompleteControl {
document.body.appendChild(this._suggestionDiv);
views.monitorNodeRemoval(
this._sourceInputNode, () => { this._uninstall(); });
this._sourceInputNode, () => {
this._uninstall();
});
}
_uninstall() {
@ -137,13 +139,21 @@ class AutoCompleteControl {
if (key === KEY_ESCAPE) {
func = this.hide;
} else if (key === KEY_TAB && shift) {
func = () => { this._selectPrevious(); };
func = () => {
this._selectPrevious();
};
} else if (key === KEY_TAB && !shift) {
func = () => { this._selectNext(); };
func = () => {
this._selectNext();
};
} else if (key === KEY_UP) {
func = () => { this._selectPrevious(); };
func = () => {
this._selectPrevious();
};
} else if (key === KEY_DOWN) {
func = () => { this._selectNext(); };
func = () => {
this._selectNext();
};
} else if (key === KEY_RETURN && this._activeResult >= 0) {
func = () => {
this._confirm(this._getActiveSuggestion());
@ -165,13 +175,17 @@ class AutoCompleteControl {
} else {
window.clearTimeout(this._showTimeout);
this._showTimeout = window.setTimeout(
() => { this._showOrHide(); }, 250);
() => {
this._showOrHide();
}, 250);
}
}
_evtBlur(e) {
window.clearTimeout(this._showTimeout);
window.setTimeout(() => { this.hide(); }, 50);
window.setTimeout(() => {
this.hide();
}, 50);
}
_getActiveSuggestion() {
@ -261,10 +275,10 @@ class AutoCompleteControl {
// choose where to view the suggestions: if there's more space above
// the input - draw the suggestions above it, otherwise below
const direction =
inputRect.top + inputRect.height / 2 < viewPortHeight / 2 ? 1 : -1;
inputRect.top + (inputRect.height / 2) < viewPortHeight / 2 ? 1 : -1;
let x = inputRect.left - bodyRect.left;
let y = direction == 1 ?
let y = direction === 1 ?
inputRect.bottom - bodyRect.top - verticalShift :
inputRect.top - bodyRect.top - listRect.height + verticalShift;
@ -276,7 +290,7 @@ class AutoCompleteControl {
const prevHeight = listRect.height;
listRect = this._suggestionDiv.getBoundingClientRect();
const heightDelta = prevHeight - listRect.height;
if (direction == -1) {
if (direction === -1) {
y += heightDelta;
}
}
@ -296,6 +310,6 @@ class AutoCompleteControl {
activeItem.classList.add('active');
}
}
};
}
module.exports = AutoCompleteControl;

View file

@ -212,11 +212,6 @@ class CommentControl extends events.EventTarget {
this._selectTab('preview');
}
_evtEditClick(e) {
e.preventDefault();
this.enterEditMode();
}
_evtSaveChangesClick(e) {
e.preventDefault();
this.dispatchEvent(new CustomEvent('submit', {
@ -260,6 +255,6 @@ class CommentControl extends events.EventTarget {
_forgetHeight() {
this._heightKeeperNode.style.minHeight = null;
}
};
}
module.exports = CommentControl;

View file

@ -54,6 +54,6 @@ class CommentListControl extends events.EventTarget {
_evtRemove(e) {
this._uninstallCommentNode(e.detail.comment);
}
};
}
module.exports = CommentListControl;

View file

@ -39,6 +39,7 @@ class ExpanderControl {
this._syncIcon();
}
// eslint-disable-next-line accessor-pairs
set title(newTitle) {
if (this._expanderNode) {
this._expanderNode

View file

@ -107,7 +107,9 @@ class PostContentControl {
this._reinstall();
optimizedResize.add(() => this._refreshSize());
views.monitorNodeRemoval(
this._hostNode, () => { this._uninstall(); });
this._hostNode, () => {
this._uninstall();
});
}
_reinstall() {

View file

@ -37,7 +37,6 @@ class PostEditSidebarControl extends events.EventTarget {
canEditPostFlags: api.hasPrivilege('posts:edit:flags'),
canEditPostContent: api.hasPrivilege('posts:edit:content'),
canEditPostThumbnail: api.hasPrivilege('posts:edit:thumbnail'),
canEditPostSource : api.hasPrivilege('posts:edit:source'),
canCreateAnonymousPosts: api.hasPrivilege('posts:create:anonymous'),
canDeletePosts: api.hasPrivilege('posts:delete'),
canFeaturePosts: api.hasPrivilege('posts:feature'),
@ -78,8 +77,7 @@ class PostEditSidebarControl extends events.EventTarget {
if (this._contentInputNode) {
this._contentFileDropper = new FileDropperControl(
this._contentInputNode, {
allowUrls: true,
this._contentInputNode, {allowUrls: true,
lock: true,
urlPlaceholder: '...or paste an URL here.'});
this._contentFileDropper.addEventListener('fileadd', e => {
@ -284,6 +282,7 @@ class PostEditSidebarControl extends events.EventTarget {
try {
success = document.execCommand('copy');
} catch (err) {
// continue regardless of error
}
textarea.blur();
document.body.removeChild(textarea);
@ -383,10 +382,16 @@ class PostEditSidebarControl extends events.EventTarget {
}
get _videoFlags() {
if (!this._loopVideoInputNode) return undefined;
if (!this._loopVideoInputNode) {
return undefined;
}
let ret = [];
if (this._loopVideoInputNode.checked) ret.push('loop');
if (this._soundVideoInputNode.checked) ret.push('sound');
if (this._loopVideoInputNode.checked) {
ret.push('loop');
}
if (this._soundVideoInputNode.checked) {
ret.push('sound');
}
return ret;
}
@ -462,6 +467,6 @@ class PostEditSidebarControl extends events.EventTarget {
showError(message) {
views.showError(this._hostNode, message);
}
};
}
module.exports = PostEditSidebarControl;

View file

@ -48,7 +48,7 @@ function _getNoteCentroid(note) {
const y0 = note.polygon.at(i).y;
const x1 = note.polygon.at((i + 1) % vertexCount).x;
const y1 = note.polygon.at((i + 1) % vertexCount).y;
const a = x0 * y1 - x1 * y0;
const a = (x0 * y1) - (x1 * y0);
signedArea += a;
centroid.x += (x0 + x1) * a;
centroid.y += (y0 + y1) * a;
@ -193,7 +193,7 @@ class SelectedState extends ActiveState {
[KEY_DOWN]: [0, delta],
[KEY_RIGHT]: [delta, 0],
};
if (offsetMap.hasOwnProperty(e.which)) {
if (Object.prototype.hasOwnProperty.call(offsetMap, e.witch)) {
e.stopPropagation();
e.stopImmediatePropagation();
e.preventDefault();
@ -283,8 +283,8 @@ class SelectedState extends ActiveState {
const origin = _getNoteCentroid(this._note);
const originalSize = _getNoteSize(this._note);
const targetSize = new Point(
originalSize.x + x / this._control.boundingBox.width,
originalSize.y + y / this._control.boundingBox.height);
originalSize.x + (x / this._control.boundingBox.width),
originalSize.y + (y / this._control.boundingBox.height));
const scale = new Point(
targetSize.x / originalSize.x,
targetSize.y / originalSize.y);
@ -305,7 +305,7 @@ class MovingPointState extends ActiveState {
}
evtCanvasKeyDown(e) {
if (e.which == KEY_ESCAPE) {
if (e.which === KEY_ESCAPE) {
this._notePoint.x = this._originalNotePoint.x;
this._notePoint.y = this._originalNotePoint.y;
this._control._state = new SelectedState(this._control, this._note);
@ -333,7 +333,7 @@ class MovingNoteState extends ActiveState {
}
evtCanvasKeyDown(e) {
if (e.which == KEY_ESCAPE) {
if (e.which === KEY_ESCAPE) {
for (let i of misc.range(this._note.polygon.length)) {
this._note.polygon.at(i).x = this._originalPolygon[i].x;
this._note.polygon.at(i).y = this._originalPolygon[i].y;
@ -366,7 +366,7 @@ class ScalingNoteState extends ActiveState {
}
evtCanvasKeyDown(e) {
if (e.which == KEY_ESCAPE) {
if (e.which === KEY_ESCAPE) {
for (let i of misc.range(this._note.polygon.length)) {
this._note.polygon.at(i).x = this._originalPolygon[i].x;
this._note.polygon.at(i).y = this._originalPolygon[i].y;
@ -384,12 +384,12 @@ class ScalingNoteState extends ActiveState {
const originalPolygonPoint = this._originalPolygon[i];
polygonPoint.x =
originalMousePoint.x +
(originalPolygonPoint.x - originalMousePoint.x) *
(1 + (mousePoint.x - originalMousePoint.x) / originalSize.x);
((originalPolygonPoint.x - originalMousePoint.x) *
(1 + ((mousePoint.x - originalMousePoint.x) / originalSize.x)));
polygonPoint.y =
originalMousePoint.y +
(originalPolygonPoint.y - originalMousePoint.y) *
(1 + (mousePoint.y - originalMousePoint.y) / originalSize.y);
((originalPolygonPoint.y - originalMousePoint.y) *
(1 + ((mousePoint.y - originalMousePoint.y) / originalSize.y)));
}
}
@ -466,12 +466,12 @@ class DrawingPolygonState extends ActiveState {
}
evtCanvasKeyDown(e) {
if (e.which == KEY_ESCAPE) {
if (e.which === KEY_ESCAPE) {
this._note.polygon.remove(this._note.polygon.secondLastPoint);
if (this._note.polygon.length === 1) {
this._cancel();
}
} else if (e.which == KEY_RETURN) {
} else if (e.which === KEY_RETURN) {
this._finish();
}
}
@ -674,13 +674,13 @@ class PostNotesOverlayControl extends events.EventTarget {
const x = (
-bodyRect.left +
svgRect.left +
svgRect.width * centroid.x -
noteRect.width / 2);
(svgRect.width * centroid.x) -
(noteRect.width / 2));
const y = (
-bodyRect.top +
svgRect.top +
svgRect.height * centroid.y -
noteRect.height / 2);
(svgRect.height * centroid.y) -
(noteRect.height / 2));
this._textNode.style.left = x + 'px';
this._textNode.style.top = y + 'px';
}

View file

@ -197,6 +197,6 @@ class PostReadonlySidebarControl extends events.EventTarget {
_evtChangeScore(e) {
this._installScore();
}
};
}
module.exports = PostReadonlySidebarControl;

View file

@ -41,8 +41,7 @@ class TagAutoCompleteControl extends AutoCompleteControl {
return new Promise((resolve, reject) => {
TagList.search(
query, 0, this._options.maxResults,
['names', 'category', 'usages'])
query, 0, this._options.maxResults, ['names', 'category', 'usages'])
.then(
response => resolve(
_tagListToMatches(response.results, this._options)),
@ -52,6 +51,6 @@ class TagAutoCompleteControl extends AutoCompleteControl {
super(input, options);
}
};
}
module.exports = TagAutoCompleteControl;

View file

@ -51,7 +51,7 @@ class SuggestionList {
}
set(suggestion, weight) {
if (this._suggestions.hasOwnProperty(suggestion)) {
if (Object.prototype.hasOwnProperty.call(this._suggestions, suggestion)) {
weight = Math.max(weight, this._suggestions[suggestion]);
}
this._suggestions[suggestion] = weight;
@ -72,7 +72,7 @@ class SuggestionList {
tuples.sort((a, b) => {
let weightDiff = b[1] - a[1];
let nameDiff = a[0].localeCompare(b[0]);
return weightDiff == 0 ? nameDiff : weightDiff;
return weightDiff === 0 ? nameDiff : weightDiff;
});
return tuples.map(tuple => {
return {tagName: tuple[0], weight: tuple[1]};
@ -102,7 +102,7 @@ class TagInputControl extends events.EventTarget {
},
confirm: tag => {
this._tagInputNode.value = '';
// XXX: tags from autocomplete don't contain implications
// note: tags from autocomplete don't contain implications
// so they need to be looked up in API
this.addTagByName(tag.names[0], SOURCE_USER_INPUT);
},
@ -160,7 +160,7 @@ class TagInputControl extends events.EventTarget {
}
addTag(tag, source) {
if (source != SOURCE_INIT && this.tags.isTaggedWith(tag.names[0])) {
if (source !== SOURCE_INIT && this.tags.isTaggedWith(tag.names[0])) {
const listItemNode = this._getListItemNode(tag);
if (source !== SOURCE_IMPLICATION) {
listItemNode.classList.add('duplicate');
@ -240,7 +240,7 @@ class TagInputControl extends events.EventTarget {
}
_evtInputKeyDown(e) {
if (e.which == KEY_RETURN || e.which == KEY_SPACE) {
if (e.which === KEY_RETURN || e.which === KEY_SPACE) {
e.preventDefault();
this._hideAutoComplete();
this.addTagByText(this._tagInputNode.value, SOURCE_USER_INPUT);

View file

@ -11,7 +11,7 @@ class EventTarget {
this[method] = this.eventTarget[method].bind(this.eventTarget);
}
}
};
}
function proxyEvent(source, target, sourceEventType, targetEventType) {
if (!source.addEventListener) {

View file

@ -22,16 +22,41 @@ class Comment extends events.EventTarget {
return comment;
}
get id() { return this._id; }
get postId() { return this._postId; }
get text() { return this._text || ''; }
get user() { return this._user; }
get creationTime() { return this._creationTime; }
get lastEditTime() { return this._lastEditTime; }
get score() { return this._score; }
get ownScore() { return this._ownScore; }
get id() {
return this._id;
}
set text(value) { this._text = value; }
get postId() {
return this._postId;
}
get text() {
return this._text || '';
}
get user() {
return this._user;
}
get creationTime() {
return this._creationTime;
}
get lastEditTime() {
return this._lastEditTime;
}
get score() {
return this._score;
}
get ownScore() {
return this._ownScore;
}
set text(value) {
this._text = value;
}
save() {
const detail = {

View file

@ -11,10 +11,17 @@ class Note extends events.EventTarget {
this._polygon = new PointList();
}
get text() { return this._text; }
get polygon() { return this._polygon; }
get text() {
return this._text;
}
set text(value) { this._text = value; }
get polygon() {
return this._polygon;
}
set text(value) {
this._text = value;
}
static fromResponse(response) {
const note = new Note();

View file

@ -9,8 +9,13 @@ class Point extends events.EventTarget {
this._y = y;
}
get x() { return this._x; }
get y() { return this._y; }
get x() {
return this._x;
}
get y() {
return this._y;
}
set x(value) {
this._x = value;
@ -21,6 +26,6 @@ class Point extends events.EventTarget {
this._y = value;
this.dispatchEvent(new CustomEvent('change', {detail: {point: this}}));
}
};
}
module.exports = Point;

View file

@ -23,43 +23,141 @@ class Post extends events.EventTarget {
this._updateFromResponse({});
}
get id() { return this._id; }
get type() { return this._type; }
get mimeType() { return this._mimeType; }
get creationTime() { return this._creationTime; }
get user() { return this._user; }
get safety() { return this._safety; }
get contentUrl() { return this._contentUrl; }
get fullContentUrl() { return this._fullContentUrl; }
get thumbnailUrl() { return this._thumbnailUrl; }
get source() { return this._source; }
get sourceSplit() { return this._source.split('\n'); }
get canvasWidth() { return this._canvasWidth || 800; }
get canvasHeight() { return this._canvasHeight || 450; }
get fileSize() { return this._fileSize || 0; }
get newContent() { throw 'Invalid operation'; }
get newThumbnail() { throw 'Invalid operation'; }
get id() {
return this._id;
}
get flags() { return this._flags; }
get tags() { return this._tags; }
get tagNames() { return this._tags.map(tag => tag.names[0]); }
get notes() { return this._notes; }
get comments() { return this._comments; }
get relations() { return this._relations; }
get type() {
return this._type;
}
get score() { return this._score; }
get commentCount() { return this._commentCount; }
get favoriteCount() { return this._favoriteCount; }
get ownFavorite() { return this._ownFavorite; }
get ownScore() { return this._ownScore; }
get hasCustomThumbnail() { return this._hasCustomThumbnail; }
get mimeType() {
return this._mimeType;
}
set flags(value) { this._flags = value; }
set safety(value) { this._safety = value; }
set relations(value) { this._relations = value; }
set newContent(value) { this._newContent = value; }
set newThumbnail(value) { this._newThumbnail = value; }
set source(value) { this._source = value; }
get creationTime() {
return this._creationTime;
}
get user() {
return this._user;
}
get safety() {
return this._safety;
}
get contentUrl() {
return this._contentUrl;
}
get fullContentUrl() {
return this._fullContentUrl;
}
get thumbnailUrl() {
return this._thumbnailUrl;
}
get source() {
return this._source;
}
get sourceSplit() {
return this._source.split('\n');
}
get canvasWidth() {
return this._canvasWidth || 800;
}
get canvasHeight() {
return this._canvasHeight || 450;
}
get fileSize() {
return this._fileSize || 0;
}
get newContent() {
throw 'Invalid operation';
}
get newThumbnail() {
throw 'Invalid operation';
}
get flags() {
return this._flags;
}
get tags() {
return this._tags;
}
get tagNames() {
return this._tags.map(tag => tag.names[0]);
}
get notes() {
return this._notes;
}
get comments() {
return this._comments;
}
get relations() {
return this._relations;
}
get score() {
return this._score;
}
get commentCount() {
return this._commentCount;
}
get favoriteCount() {
return this._favoriteCount;
}
get ownFavorite() {
return this._ownFavorite;
}
get ownScore() {
return this._ownScore;
}
get hasCustomThumbnail() {
return this._hasCustomThumbnail;
}
set flags(value) {
this._flags = value;
}
set safety(value) {
this._safety = value;
}
set relations(value) {
this._relations = value;
}
set newContent(value) {
this._newContent = value;
}
set newThumbnail(value) {
this._newThumbnail = value;
}
set source(value) {
this._source = value;
}
static fromResponse(response) {
const ret = new Post();
@ -309,6 +407,6 @@ class Post extends events.EventTarget {
Object.assign(this, map());
Object.assign(this._orig, map());
}
};
}
module.exports = Post;

View file

@ -30,6 +30,7 @@ class Settings extends events.EventTarget {
try {
Object.assign(ret, JSON.parse(localStorage.getItem('settings')));
} catch (e) {
// continue regardless of error
}
return ret;
}
@ -50,6 +51,6 @@ class Settings extends events.EventTarget {
get() {
return this.cache;
}
};
}
module.exports = new Settings();

View file

@ -10,12 +10,29 @@ class Snapshot extends events.EventTarget {
this._updateFromResponse({});
}
get operation() { return this._operation; }
get type() { return this._type; }
get id() { return this._id; }
get user() { return this._user; }
get data() { return this._data; }
get time() { return this._time; }
get operation() {
return this._operation;
}
get type() {
return this._type;
}
get id() {
return this._id;
}
get user() {
return this._user;
}
get data() {
return this._data;
}
get time() {
return this._time;
}
static fromResponse(response) {
const ret = new Snapshot();

View file

@ -20,18 +20,49 @@ class Tag extends events.EventTarget {
this._updateFromResponse({});
}
get names() { return this._names; }
get category() { return this._category; }
get description() { return this._description; }
get suggestions() { return this._suggestions; }
get implications() { return this._implications; }
get postCount() { return this._postCount; }
get creationTime() { return this._creationTime; }
get lastEditTime() { return this._lastEditTime; }
get names() {
return this._names;
}
set names(value) { this._names = value; }
set category(value) { this._category = value; }
set description(value) { this._description = value; }
get category() {
return this._category;
}
get description() {
return this._description;
}
get suggestions() {
return this._suggestions;
}
get implications() {
return this._implications;
}
get postCount() {
return this._postCount;
}
get creationTime() {
return this._creationTime;
}
get lastEditTime() {
return this._lastEditTime;
}
set names(value) {
this._names = value;
}
set category(value) {
this._category = value;
}
set description(value) {
this._description = value;
}
static fromResponse(response) {
const ret = new Tag();
@ -145,6 +176,6 @@ class Tag extends events.EventTarget {
Object.assign(this, map);
Object.assign(this._orig, map);
}
};
}
module.exports = Tag;

View file

@ -15,14 +15,33 @@ class TagCategory extends events.EventTarget {
this._origColor = null;
}
get name() { return this._name; }
get color() { return this._color; }
get tagCount() { return this._tagCount; }
get isDefault() { return this._isDefault; }
get isTransient() { return !this._origName; }
get name() {
return this._name;
}
set name(value) { this._name = value; }
set color(value) { this._color = value; }
get color() {
return this._color;
}
get tagCount() {
return this._tagCount;
}
get isDefault() {
return this._isDefault;
}
get isTransient() {
return !this._origName;
}
set name(value) {
this._name = value;
}
set color(value) {
this._color = value;
}
static fromResponse(response) {
const ret = new TagCategory();

View file

@ -12,7 +12,7 @@ class TopNavigationItem {
this.imageUrl = imageUrl === undefined ? null : imageUrl;
this.key = null;
}
};
}
class TopNavigation extends events.EventTarget {
constructor() {
@ -72,7 +72,7 @@ class TopNavigation extends events.EventTarget {
hide(key) {
this.get(key).available = false;
}
};
}
function _makeTopNavigation() {
const ret = new TopNavigation();

View file

@ -11,28 +11,89 @@ class User extends events.EventTarget {
this._updateFromResponse({});
}
get name() { return this._name; }
get rank() { return this._rank; }
get email() { return this._email; }
get avatarStyle() { return this._avatarStyle; }
get avatarUrl() { return this._avatarUrl; }
get creationTime() { return this._creationTime; }
get lastLoginTime() { return this._lastLoginTime; }
get commentCount() { return this._commentCount; }
get favoritePostCount() { return this._favoritePostCount; }
get uploadedPostCount() { return this._uploadedPostCount; }
get likedPostCount() { return this._likedPostCount; }
get dislikedPostCount() { return this._dislikedPostCount; }
get rankName() { return api.rankNames.get(this.rank); }
get avatarContent() { throw 'Invalid operation'; }
get password() { throw 'Invalid operation'; }
get name() {
return this._name;
}
set name(value) { this._name = value; }
set rank(value) { this._rank = value; }
set email(value) { this._email = value || null; }
set avatarStyle(value) { this._avatarStyle = value; }
set avatarContent(value) { this._avatarContent = value; }
set password(value) { this._password = value; }
get rank() {
return this._rank;
}
get email() {
return this._email;
}
get avatarStyle() {
return this._avatarStyle;
}
get avatarUrl() {
return this._avatarUrl;
}
get creationTime() {
return this._creationTime;
}
get lastLoginTime() {
return this._lastLoginTime;
}
get commentCount() {
return this._commentCount;
}
get favoritePostCount() {
return this._favoritePostCount;
}
get uploadedPostCount() {
return this._uploadedPostCount;
}
get likedPostCount() {
return this._likedPostCount;
}
get dislikedPostCount() {
return this._dislikedPostCount;
}
get rankName() {
return api.rankNames.get(this.rank);
}
get avatarContent() {
throw 'Invalid operation';
}
get password() {
throw 'Invalid operation';
}
set name(value) {
this._name = value;
}
set rank(value) {
this._rank = value;
}
set email(value) {
this._email = value || null;
}
set avatarStyle(value) {
this._avatarStyle = value;
}
set avatarContent(value) {
this._avatarContent = value;
}
set password(value) {
this._password = value;
}
static fromResponse(response) {
const ret = new User();
@ -126,6 +187,6 @@ class User extends events.EventTarget {
this._password = null;
this._avatarContent = null;
}
};
}
module.exports = User;

View file

@ -11,16 +11,41 @@ class UserToken extends events.EventTarget {
this._updateFromResponse({});
}
get token() { return this._token; }
get note() { return this._note; }
get enabled() { return this._enabled; }
get version() { return this._version; }
get expirationTime() { return this._expirationTime; }
get creationTime() { return this._creationTime; }
get lastEditTime() { return this._lastEditTime; }
get lastUsageTime() { return this._lastUsageTime; }
get token() {
return this._token;
}
set note(value) { this._note = value; }
get note() {
return this._note;
}
get enabled() {
return this._enabled;
}
get version() {
return this._version;
}
get expirationTime() {
return this._expirationTime;
}
get creationTime() {
return this._creationTime;
}
get lastEditTime() {
return this._lastEditTime;
}
get lastUsageTime() {
return this._lastUsageTime;
}
set note(value) {
this._note = value;
}
static fromResponse(response) {
if (typeof response.results !== 'undefined') {

View file

@ -51,7 +51,7 @@ class Context {
replaceState() {
history.replaceState(this.state, this.title, this.canonicalPath);
}
};
}
class Route {
constructor(path) {
@ -119,7 +119,7 @@ class Route {
return true;
}
};
}
class Router {
constructor() {
@ -217,14 +217,14 @@ class Router {
if (current === ctx.canonicalPath) {
return;
}
router.stop();
this.stop();
location.href = ctx.canonicalPath;
}
get url() {
return location.pathname + location.search + location.hash;
}
};
}
const _onPopState = router => {
let loaded = false;

View file

@ -5,6 +5,7 @@ const settings = require('../models/settings.js');
let paused = false;
const _originalStopCallback = mousetrap.prototype.stopCallback;
// eslint-disable-next-line func-names
mousetrap.prototype.stopCallback = function(...args) {
var self = this;
if (paused) {
@ -28,6 +29,10 @@ function unbind(hotkey) {
module.exports = {
bind: bind,
unbind: unbind,
pause: () => { paused = true; },
unpause: () => { paused = false; },
pause: () => {
paused = true;
},
unpause: () => {
paused = false;
},
};

View file

@ -127,7 +127,7 @@ function createRenderer() {
const renderer = new marked.Renderer();
renderer.image = (href, title, alt) => {
let [_, url, width, height] =
/^(.+?)(?:\s=\s*(\d*)\s*x\s*(\d*)\s*)?$/.exec(href);
(/^(.+?)(?:\s=\s*(\d*)\s*x\s*(\d*)\s*)?$/).exec(href);
let res = '<img src="' + sanitize(url) + '" alt="' + sanitize(alt);
if (width) {
res += '" width="' + width;

View file

@ -13,7 +13,7 @@ function decamelize(str, sep) {
}
function *range(start = 0, end = null, step = 1) {
if (end == null) {
if (end === null) {
end = start;
start = 0;
}
@ -192,7 +192,7 @@ function dataURItoBlob(dataURI) {
unescape(chunks[1]);
const mimeString = chunks[0].split(':')[1].split(';')[0];
const data = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
for (let i = 0; i < byteString.length; i++) {
data[i] = byteString.charCodeAt(i);
}
return new Blob([data], {type: mimeString});

View file

@ -15,7 +15,7 @@ function resize() {
}
function runCallbacks() {
callbacks.forEach(function(callback) {
callbacks.forEach(callback => {
callback();
});
running = false;

View file

@ -1,3 +1,5 @@
/* eslint-disable func-names, no-extend-native */
'use strict';
// fix iterating over NodeList in Chrome and Opera

View file

@ -1,3 +1,5 @@
'use strict';
const nprogress = require('nprogress');
let nesting = 0;

View file

@ -1,3 +1,5 @@
'use strict';
const direction = {
NONE: null,
LEFT: 'left',
@ -26,14 +28,12 @@ function handleTouchMove(handler, evt) {
} else {
handler._direction = direction.RIGHT;
}
} else {
if (yDirection > 0) {
} else if (yDirection > 0) {
handler._direction = direction.DOWN;
} else {
handler._direction = direction.UP;
}
}
}
function handleTouchEnd(handler) {
switch (handler._direction) {
@ -50,6 +50,7 @@ function handleTouchEnd(handler) {
break;
case direction.UP:
handler._swipeUpTask();
// no default
}
handler._xStart = null;
@ -74,11 +75,17 @@ class Touch {
this._direction = direction.NONE;
this._target.addEventListener('touchstart',
(evt) => { handleTouchStart(this, evt); });
evt => {
handleTouchStart(this, evt);
});
this._target.addEventListener('touchmove',
(evt) => { handleTouchMove(this, evt); });
evt => {
handleTouchMove(this, evt);
});
this._target.addEventListener('touchend',
() => { handleTouchEnd(this); });
() => {
handleTouchEnd(this);
});
}
}

View file

@ -72,7 +72,7 @@ function extractRootDomain(url) {
if (arrLen > 2) {
domain = splitArr[arrLen - 2] + '.' + splitArr[arrLen - 1];
// check to see if it's using a Country Code Top Level Domain (ccTLD) (i.e. ".me.uk")
if (splitArr[arrLen - 2].length == 2 && splitArr[arrLen - 1].length == 2) {
if (splitArr[arrLen - 2].length === 2 && splitArr[arrLen - 1].length === 2) {
// this is using a ccTLD
domain = splitArr[arrLen - 3] + '.' + domain;
}

View file

@ -94,8 +94,7 @@ function makeSelect(options) {
name: options.name,
disabled: options.readonly,
},
...Object.keys(options.keyValues).map(key =>
makeElement(
...Object.keys(options.keyValues).map(key => makeElement(
'option',
{value: key, selected: key === options.selectedKey},
options.keyValues[key])));
@ -157,10 +156,7 @@ function makeColorInput(options) {
color: ${options.value}`,
});
return makeElement(
'label', {class: 'color'},
textInput,
backgroundPreviewNode,
textPreviewNode);
'label', {class: 'color'}, textInput, backgroundPreviewNode, textPreviewNode);
}
function makeNumericInput(options) {
@ -175,14 +171,12 @@ function makeDateInput(options) {
function getPostUrl(id, parameters) {
return uri.formatClientLink(
'post', id,
parameters ? {query: parameters.query} : {});
'post', id, parameters ? {query: parameters.query} : {});
}
function getPostEditUrl(id, parameters) {
return uri.formatClientLink(
'post', id, 'edit',
parameters ? {query: parameters.query} : {});
'post', id, 'edit', parameters ? {query: parameters.query} : {});
}
function makePostLink(id, includeHash) {
@ -346,15 +340,14 @@ function htmlToDom(html) {
col: [2, '<table><tbody></tbody><colgroup>', '</colgroup></table>'],
};
wrapMap.optgroup = wrapMap.option;
wrapMap.tbody =
wrapMap.tfoot =
wrapMap.colgroup =
wrapMap.caption =
wrapMap.thead;
wrapMap.tbody = wrapMap.thead;
wrapMap.tfoot = wrapMap.thead;
wrapMap.colgroup = wrapMap.thead;
wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;
let element = document.createElement('div');
const match = /<\s*(\w+)[^>]*?>/g.exec(html);
const match = (/<\s*(\w+)[^>]*?>/g).exec(html);
if (match) {
const tag = match[1];
@ -444,7 +437,7 @@ function enableForm(form) {
function syncScrollPosition() {
window.requestAnimationFrame(
() => {
if (history.state && history.state.hasOwnProperty('scrollX')) {
if (history.state && Object.prototype.hasOwnProperty.call(history.state, 'scrollX')) {
window.scrollTo(history.state.scrollX, history.state.scrollY);
} else {
window.scrollTo(0, 0);

View file

@ -27,8 +27,7 @@ class HomeView {
this._autoCompleteControl = new TagAutoCompleteControl(
this._searchInputNode,
{
confirm: tag =>
this._autoCompleteControl.replaceSelectedText(
confirm: tag => this._autoCompleteControl.replaceSelectedText(
misc.escapeSearchTerm(tag.names[0]), true),
});
this._formNode.addEventListener(
@ -99,8 +98,7 @@ class HomeView {
_evtFormSubmit(e) {
e.preventDefault();
this._searchInputNode.blur();
router.show(uri.formatClientLink('posts', {
query: this._searchInputNode.value}));
router.show(uri.formatClientLink('posts', {query: this._searchInputNode.value}));
}
}

View file

@ -9,7 +9,7 @@ const navTemplate = views.getTemplate('manual-pager-nav');
function _removeConsecutiveDuplicates(a) {
return a.filter((item, pos, ary) => {
return !pos || item != ary[pos - 1];
return !pos || item !== ary[pos - 1];
});
}
@ -30,7 +30,9 @@ function _getVisiblePageNumbers(currentPage, totalPages) {
pagesVisible = pagesVisible.filter((item, pos, ary) => {
return item >= 1 && item <= totalPages;
});
pagesVisible = pagesVisible.sort((a, b) => { return a - b; });
pagesVisible = pagesVisible.sort((a, b) => {
return a - b;
});
pagesVisible = _removeConsecutiveDuplicates(pagesVisible);
return pagesVisible;
}
@ -46,7 +48,7 @@ function _getPages(
pages.set(page, {
number: page,
offset:
(page - 1) * limit -
((page - 1) * limit) -
(page > currentPage ? removedItems : 0),
limit: limit === defaultLimit ? null : limit,
active: currentPage === page,

View file

@ -43,7 +43,7 @@ class PostMainView {
margin,
iosCorrectedInnerHeight() -
topNavigationNode.getBoundingClientRect().height -
margin * 2,
(margin * 2),
];
});
@ -80,7 +80,7 @@ class PostMainView {
});
keyboard.bind(['a', 'left'], showPreviousImage);
keyboard.bind(['d', 'right'], showNextImage);
keyboard.bind('del', (e) => {
keyboard.bind('del', e => {
if (ctx.editMode) {
this.sidebarControl._evtDeleteClick(e);
}

View file

@ -62,8 +62,7 @@ class PostMergeView extends events.EventTarget {
_refreshSide(post, sideNode, sideName, isEditable) {
views.replaceContent(
sideNode,
sideTemplate(Object.assign({}, this._ctx, {
post: post,
sideTemplate(Object.assign({}, this._ctx, {post: post,
name: sideName,
editable: isEditable})));
@ -85,10 +84,10 @@ class PostMergeView extends events.EventTarget {
'.target-post-content :checked').value;
this.dispatchEvent(new CustomEvent('submit', {
detail: {
post: checkedTargetPost == 'left' ?
post: checkedTargetPost === 'left' ?
this._rightPost :
this._leftPost,
targetPost: checkedTargetPost == 'left' ?
targetPost: checkedTargetPost === 'left' ?
this._leftPost :
this._rightPost,
useOldContent: checkedTargetPostContent !== checkedTargetPost,

View file

@ -52,10 +52,6 @@ class BulkEditor extends events.EventTarget {
}
class BulkSafetyEditor extends BulkEditor {
constructor(hostNode) {
super(hostNode);
}
_evtOpenLinkClick(e) {
e.preventDefault();
this.toggleOpen(true);
@ -75,8 +71,7 @@ class BulkTagEditor extends BulkEditor {
this._autoCompleteControl = new TagAutoCompleteControl(
this._inputNode,
{
confirm: tag =>
this._autoCompleteControl.replaceSelectedText(
confirm: tag => this._autoCompleteControl.replaceSelectedText(
tag.names[0], false),
});
this._hostNode.addEventListener('submit', e => this._evtFormSubmit(e));
@ -132,8 +127,7 @@ class PostsHeaderView extends events.EventTarget {
this._autoCompleteControl = new TagAutoCompleteControl(
this._queryInputNode,
{
confirm: tag =>
this._autoCompleteControl.replaceSelectedText(
confirm: tag => this._autoCompleteControl.replaceSelectedText(
misc.escapeSearchTerm(tag.names[0]), true),
});

View file

@ -100,7 +100,7 @@ class PostsPageView extends events.EventTarget {
if (tagFlipperNode) {
let tagged = true;
for (let tag of this._ctx.bulkEdit.tags) {
tagged = tagged & post.tags.isTaggedWith(tag);
tagged &= post.tags.isTaggedWith(tag);
}
tagFlipperNode.classList.toggle('tagged', tagged);
}
@ -109,7 +109,7 @@ class PostsPageView extends events.EventTarget {
if (safetyFlipperNode) {
for (let linkNode of safetyFlipperNode.querySelectorAll('a')) {
const safety = linkNode.getAttribute('data-safety');
linkNode.classList.toggle('active', post.safety == safety);
linkNode.classList.toggle('active', post.safety === safety);
}
}
}

View file

@ -22,8 +22,7 @@ class TagMergeView extends events.EventTarget {
this._autoCompleteControl = new TagAutoCompleteControl(
this._targetTagFieldNode,
{
confirm: tag =>
this._autoCompleteControl.replaceSelectedText(
confirm: tag => this._autoCompleteControl.replaceSelectedText(
tag.names[0], false),
});
}

View file

@ -20,8 +20,7 @@ class TagsHeaderView extends events.EventTarget {
this._autoCompleteControl = new TagAutoCompleteControl(
this._queryInputNode,
{
confirm: tag =>
this._autoCompleteControl.replaceSelectedText(
confirm: tag => this._autoCompleteControl.replaceSelectedText(
misc.escapeSearchTerm(tag.names[0]), true),
});
}

View file

@ -11,8 +11,8 @@ class UserEditView extends events.EventTarget {
constructor(ctx) {
super();
ctx.userNamePattern = api.getUserNameRegex() + /|^$/.source;
ctx.passwordPattern = api.getPasswordRegex() + /|^$/.source;
ctx.userNamePattern = api.getUserNameRegex() + (/|^$/).source;
ctx.passwordPattern = api.getPasswordRegex() + (/|^$/).source;
this._user = ctx.user;
this._hostNode = ctx.hostNode;

View file

@ -37,7 +37,7 @@ class UserView extends events.EventTarget {
}
ctx.hostNode = this._hostNode.querySelector('#user-content-holder');
if (ctx.section == 'edit') {
if (ctx.section === 'edit') {
if (!this._ctx.canEditAnything) {
this._view = new EmptyView();
this._view.showError(
@ -46,7 +46,7 @@ class UserView extends events.EventTarget {
this._view = new UserEditView(ctx);
events.proxyEvent(this._view, this, 'submit');
}
} else if (ctx.section == 'list-tokens') {
} else if (ctx.section === 'list-tokens') {
if (!this._ctx.canListTokens) {
this._view = new EmptyView();
this._view.showError(
@ -57,7 +57,7 @@ class UserView extends events.EventTarget {
events.proxyEvent(this._view, this, 'submit', 'create-token');
events.proxyEvent(this._view, this, 'update', 'update-token');
}
} else if (ctx.section == 'delete') {
} else if (ctx.section === 'delete') {
if (!this._ctx.canDelete) {
this._view = new EmptyView();
this._view.showError(