update prettier to v2 & format files

This commit is contained in:
David Sevilla Martin 2020-03-28 11:59:00 -04:00
parent 458045ad33
commit be844519f2
No known key found for this signature in database
GPG Key ID: F764F1417E16B15F
52 changed files with 2500 additions and 1485 deletions

6
js/dist/admin.js vendored
View File

@ -993,7 +993,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/
},
scrollTop: function scrollTop(value) {
if (!this.length) return;
var hasScrollTop = 'scrollTop' in this[0];
var hasScrollTop = ('scrollTop' in this[0]);
if (value === undefined) return hasScrollTop ? this[0].scrollTop : this[0].pageYOffset;
return this.each(hasScrollTop ? function () {
this.scrollTop = value;
@ -1003,7 +1003,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/
},
scrollLeft: function scrollLeft(value) {
if (!this.length) return;
var hasScrollLeft = 'scrollLeft' in this[0];
var hasScrollLeft = ('scrollLeft' in this[0]);
if (value === undefined) return hasScrollLeft ? this[0].scrollLeft : this[0].pageXOffset;
return this.each(hasScrollLeft ? function () {
this.scrollLeft = value;
@ -1147,7 +1147,7 @@ var __WEBPACK_AMD_DEFINE_RESULT__;/*** IMPORTS FROM imports-loader ***/
},
handlers = {},
specialEvents = {},
focusinSupported = 'onfocusin' in window,
focusinSupported = ('onfocusin' in window),
focus = {
focus: 'focusin',
blur: 'focusout'

File diff suppressed because one or more lines are too long

2811
js/dist/forum.js vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

825
js/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -22,19 +22,19 @@
"scripts": {
"dev": "webpack --mode development --watch",
"build": "webpack --mode production",
"lint": "prettier --single-quote --trailing-comma es5 --print-width 150 --tab-width 4 --write \"src/**/*\" \"*.{ts,js}\""
"lint": "prettier --single-quote --trailing-comma es5 --print-width 150 --tab-width 4 --write src \"*.{ts,js}\""
},
"devDependencies": {
"@babel/core": "^7.8.7",
"@babel/core": "^7.9.0",
"@babel/plugin-proposal-class-properties": "^7.8.3",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-object-assign": "^7.8.3",
"@babel/plugin-transform-react-jsx": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.8.3",
"@babel/preset-env": "^7.8.7",
"@babel/preset-react": "^7.8.3",
"@babel/preset-typescript": "^7.8.3",
"@babel/runtime": "^7.8.7",
"@babel/plugin-transform-react-jsx": "^7.9.4",
"@babel/plugin-transform-runtime": "^7.9.0",
"@babel/preset-env": "^7.9.0",
"@babel/preset-react": "^7.9.4",
"@babel/preset-typescript": "^7.9.0",
"@babel/runtime": "^7.9.2",
"@types/classnames": "^2.2.10",
"@types/mithril": "^2.0.2",
"@types/zepto": "^1.0.30",
@ -42,10 +42,10 @@
"expose-loader": "^0.7.5",
"friendly-errors-webpack-plugin": "^1.7.0",
"imports-loader": "^0.8.0",
"prettier": "^1.19.1",
"prettier": "^2.0.2",
"source-map-loader": "^0.2.4",
"typescript": "^3.8.3",
"webpack": "^4.42.0",
"webpack": "^4.42.1",
"webpack-bundle-analyzer": "^3.6.1",
"webpack-cli": "^3.3.11",
"webpack-merge": "^4.2.2"

View File

@ -113,7 +113,7 @@ export default abstract class Application {
}
boot() {
this.initializers.toArray().forEach(initializer => initializer(this));
this.initializers.toArray().forEach((initializer) => initializer(this));
this.store.pushPayload({ data: this.data.resources });
@ -127,7 +127,7 @@ export default abstract class Application {
}
bootExtensions(extensions) {
Object.keys(extensions).forEach(name => {
Object.keys(extensions).forEach((name) => {
const extension = extensions[name];
const extenders = flattenDeep(extension.extend);
@ -145,13 +145,13 @@ export default abstract class Application {
if ($modal) m.mount($modal, (this.modal = new ModalManager()));
if ($alerts) m.mount($alerts, (this.alerts = new AlertManager({ oninit: vnode => (this.alerts = vnode.state) })));
if ($alerts) m.mount($alerts, (this.alerts = new AlertManager({ oninit: (vnode) => (this.alerts = vnode.state) })));
if ($content) m.route($content, basePath + '/', mapRoutes(this.routes, basePath));
// Add a class to the body which indicates that the page has been scrolled
// down.
new ScrollListener(top => {
new ScrollListener((top) => {
const $app = $('#app');
const offset = $app.offset().top;
@ -248,11 +248,11 @@ export default abstract class Application {
// When we deserialize JSON data, if for some reason the server has provided
// a dud response, we don't want the application to crash. We'll show an
// error message to the user instead.
options.deserialize = options.deserialize || (responseText => responseText);
options.deserialize = options.deserialize || ((responseText) => responseText);
options.errorHandler =
options.errorHandler ||
(error => {
((error) => {
throw error;
});
@ -260,7 +260,7 @@ export default abstract class Application {
// response code and show an error message to the user if something's gone
// awry.
const original = options.extract;
options.extract = xhr => {
options.extract = (xhr) => {
let responseText;
if (original) {
@ -292,8 +292,8 @@ export default abstract class Application {
// Now make the request. If it's a failure, inspect the error that was
// returned and show an alert containing its contents.
return m.request(options).then(
res => res,
error => {
(res) => res,
(error) => {
this.requestError = error;
let children;
@ -301,7 +301,7 @@ export default abstract class Application {
switch (error.status) {
case 422:
children = error.response.errors
.map(error => [error.detail, m('br')])
.map((error) => [error.detail, m('br')])
.reduce((a, b) => a.concat(b), [])
.slice(0, -1);
break;

View File

@ -164,7 +164,7 @@ export default abstract class Model {
// If everything went well, we'll make sure the store knows that this
// model exists now (if it didn't already), and we'll push the data that
// the API returned into the store.
payload => {
(payload) => {
this.store.data[payload.data.type] = this.store.data[payload.data.type] || {};
this.store.data[payload.data.type][payload.data.id] = this;
return this.store.pushPayload(payload);
@ -172,7 +172,7 @@ export default abstract class Model {
// If something went wrong, though... good thing we backed up our model's
// old data! We'll revert to that and let others handle the error.
response => {
(response) => {
this.pushData(oldData);
m.redraw();
throw response;
@ -229,7 +229,7 @@ export default abstract class Model {
* @param [transform] A function to transform the attribute value
*/
static attribute(name: string, transform?: Function): () => any {
return function(this: Model) {
return function (this: Model) {
const value = this.data.attributes && this.data.attributes[name];
return transform ? transform(value) : value;
@ -245,7 +245,7 @@ export default abstract class Model {
* has not been loaded; or the model if it has been loaded.
*/
static hasOne(name: string): () => Model | boolean {
return function(this: Model) {
return function (this: Model) {
if (this.data.relationships) {
const relationship = this.data.relationships[name];
@ -267,12 +267,12 @@ export default abstract class Model {
* loaded, and undefined for those that have not.
*/
static hasMany(name: string): () => any[] | false {
return function(this: Model) {
return function (this: Model) {
if (this.data.relationships) {
const relationship = this.data.relationships[name];
if (relationship && Array.isArray(relationship.data)) {
return relationship.data.map(data => app.store.getById(data.type, data.id));
return relationship.data.map((data) => app.store.getById(data.type, data.id));
}
}

View File

@ -119,7 +119,7 @@ export default class Store {
* @param value The value of the model attribute.
*/
getBy<T extends Model = Model>(type: string, key: string, value: any): T {
return this.all<T>(type).filter(model => model[key]() === value)[0];
return this.all<T>(type).filter((model) => model[key]() === value)[0];
}
/**
@ -128,7 +128,7 @@ export default class Store {
all<T extends Model = Model>(type: string): T[] {
const records = this.data[type];
return records ? Object.keys(records).map(id => records[id]) : [];
return records ? Object.keys(records).map((id) => records[id]) : [];
}
/**

View File

@ -52,7 +52,7 @@ export default class Translator {
const hydrated: any[] = [];
const open: any[][] = [hydrated];
parts.forEach(part => {
parts.forEach((part) => {
const match = part.match(new RegExp('{([a-z0-9_]+)}|<(/?)([a-z0-9_]+)>', 'i'));
if (match) {
@ -72,7 +72,7 @@ export default class Translator {
}
});
return hydrated.filter(part => part);
return hydrated.filter((part) => part);
}
pluralize(translation: string, number: number): string | undefined {
@ -84,7 +84,7 @@ export default class Translator {
standardRules = [],
explicitRules = [];
translation.split('|').forEach(part => {
translation.split('|').forEach((part) => {
if (cPluralRegex.test(part)) {
const matches = part.match(cPluralRegex);
explicitRules[matches[0]] = matches[matches.length - 1];

View File

@ -15,7 +15,7 @@ export default class AlertManager extends Component {
view() {
return (
<div className="AlertManager">
{this.components.map(vnode => (
{this.components.map((vnode) => (
<div className="AlertManager-alert">{vnode}</div>
))}
</div>

View File

@ -81,11 +81,7 @@ export default abstract class Modal<T extends ComponentProps = ComponentProps> e
* Focus on the first input when the modal is ready to be used.
*/
onready() {
this.$('form')
.find('input, select, textarea')
.first()
.focus()
.select();
this.$('form').find('input, select, textarea').first().focus().select();
}
onhide() {}

View File

@ -51,9 +51,7 @@ export default class ModalManager extends Component {
m.redraw();
if (!$('.modal-backdrop').length) {
$('<div />')
.addClass('modal-backdrop')
.appendTo('body');
$('<div />').addClass('modal-backdrop').appendTo('body');
}
MicroModal.show('Modal', {

View File

@ -25,7 +25,7 @@ export default class SelectDropdown extends Dropdown<SelectDropdownProps> {
}
getButtonContent() {
const activeChild = this.props.children.filter(child => child.attrs.active)[0];
const activeChild = this.props.children.filter((child) => child.attrs.active)[0];
let label = (activeChild && activeChild.attrs.children) || this.props.defaultLabel;
if (label instanceof Array) label = label[0];

View File

@ -59,7 +59,7 @@ export function extend(object, method, callback) {
export function override(object, method, newMethod) {
const original = object[method];
object[method] = function(...args) {
object[method] = function (...args) {
// @ts-ignore
return newMethod.apply(this, [original.bind(this)].concat(args));
};

View File

@ -28,9 +28,7 @@ export default function highlight(string: string, phrase: string | RegExp, lengt
// Convert the string into HTML entities, then highlight all matches with
// <mark> tags. Then we will return the result as a trusted HTML string.
highlighted = $('<div/>')
.text(highlighted)
.html();
highlighted = $('<div/>').text(highlighted).html();
if (phrase) highlighted = highlighted.replace(regexp, '<mark>$&</mark>');

View File

@ -28,7 +28,7 @@ export function withoutUnnecessarySeparators(items) {
export default function listItems(items) {
if (!(items instanceof Array)) items = [items];
return withoutUnnecessarySeparators(items).map(item => {
return withoutUnnecessarySeparators(items).map((item) => {
const isListItem = item.tag?.isListItem;
const active = item.tag?.isActive && item.tag.isActive(item.attrs);
const className = item.attrs?.itemClassName || item.itemClassName;

View File

@ -20,18 +20,18 @@ export default class Discussion extends Model {
lastPostNumber = Model.attribute('lastPostNumber') as () => number;
commentCount = Model.attribute('commentCount') as () => number;
replyCount = computed('commentCount', commentCount => Math.max(0, commentCount - 1)) as () => number;
replyCount = computed('commentCount', (commentCount) => Math.max(0, commentCount - 1)) as () => number;
posts = Model.hasMany('posts') as () => Post[];
mostRelevantPost = Model.hasOne('mostRelevantPost') as () => Post;
lastReadAt = Model.attribute('lastReadAt', Model.transformDate) as () => Date;
lastReadPostNumber = Model.attribute('lastReadPostNumber') as () => number;
isUnread = computed('unreadCount', unreadCount => !!unreadCount) as () => boolean;
isRead = computed('unreadCount', unreadCount => app.session.user && !unreadCount) as () => boolean;
isUnread = computed('unreadCount', (unreadCount) => !!unreadCount) as () => boolean;
isRead = computed('unreadCount', (unreadCount) => app.session.user && !unreadCount) as () => boolean;
hiddenAt = Model.attribute('hiddenAt', Model.transformDate) as () => Date;
hiddenUser = Model.hasOne('hiddenUser') as () => User;
isHidden = computed('hiddenAt', hiddenAt => !!hiddenAt) as () => boolean;
isHidden = computed('hiddenAt', (hiddenAt) => !!hiddenAt) as () => boolean;
canReply = Model.attribute('canReply') as () => boolean;
canRename = Model.attribute('canRename') as () => boolean;
@ -90,6 +90,6 @@ export default class Discussion extends Model {
postIds(): string[] {
const posts = this.data.relationships?.posts;
return posts ? posts.data.map(link => link.id) : [];
return posts ? posts.data.map((link) => link.id) : [];
}
}

View File

@ -18,11 +18,11 @@ export default class Post extends Model {
editedAt = Model.attribute('editedAt', Model.transformDate) as () => Date;
editedUser = Model.hasOne('editedUser') as () => User;
isEdited = computed('editedAt', editedAt => !!editedAt) as () => boolean;
isEdited = computed('editedAt', (editedAt) => !!editedAt) as () => boolean;
hiddenAt = Model.attribute('hiddenAt', Model.transformDate) as () => Date;
hiddenUser = Model.hasOne('hiddenUser') as () => User;
isHidden = computed('hiddenAt', hiddenAt => !!hiddenAt) as () => boolean;
isHidden = computed('hiddenAt', (hiddenAt) => !!hiddenAt) as () => boolean;
canEdit = Model.attribute('canEdit') as () => boolean;
canHide = Model.attribute('canHide') as () => boolean;

View File

@ -38,7 +38,7 @@ export default class User extends Model {
canDelete = Model.attribute('canDelete') as () => boolean;
avatarColor = null;
color = computed(['username', 'avatarUrl', 'avatarColor'], function(username, avatarUrl, avatarColor) {
color = computed(['username', 'avatarUrl', 'avatarColor'], function (username, avatarUrl, avatarColor) {
// If we've already calculated and cached the dominant color of the user's
// avatar, then we can return that in RGB format. If we haven't, we'll want
// to calculate it. Unless the user doesn't have an avatar, in which case
@ -54,12 +54,7 @@ export default class User extends Model {
}) as () => string;
isOnline(): boolean {
return (
this.lastSeenAt() >
dayjs()
.subtract(5, 'minutes')
.toDate()
);
return this.lastSeenAt() > dayjs().subtract(5, 'minutes').toDate();
}
/**
@ -70,7 +65,7 @@ export default class User extends Model {
const groups = this.groups();
if (groups) {
groups.forEach(group => {
groups.forEach((group) => {
items.add('group' + group.id(), GroupBadge.component({ group }));
});
}
@ -88,7 +83,7 @@ export default class User extends Model {
const image = new Image();
const user = this;
image.onload = function() {
image.onload = function () {
const colorThief = new ColorThief();
user.avatarColor = colorThief.getColor(this);
user.freshness = new Date();

View File

@ -9,7 +9,7 @@ export default class Drawer {
constructor() {
// Set up an event handler so that whenever the content area is tapped,
// the drawer will close.
$('#content').click(e => {
$('#content').click((e) => {
if (this.isOpen()) {
e.preventDefault();
this.hide();

View File

@ -26,7 +26,7 @@ export default class Evented {
* @param args Arguments to pass to event handlers.
*/
public trigger(event: string, ...args: any): this {
this.getHandlers(event).forEach(handler => handler.apply(this, args));
this.getHandlers(event).forEach((handler) => handler.apply(this, args));
return this;
}
@ -51,7 +51,7 @@ export default class Evented {
* @param handler The function to handle the event.
*/
one(event: string, handler: EventHandler): this {
const wrapper = function(this: Evented) {
const wrapper = function (this: Evented) {
handler.apply(this, Array.from(arguments));
this.off(event, wrapper);

View File

@ -83,6 +83,6 @@ export default class ItemList<T = any> {
}
return 1;
})
.map(item => item.content);
.map((item) => item.content);
}
}

View File

@ -4,7 +4,7 @@ const later =
window.mozRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
(callback => window.setTimeout(callback, 1000 / 60));
((callback) => window.setTimeout(callback, 1000 / 60));
/**
* The `ScrollListener` class sets up a listener that handles window scroll

View File

@ -12,12 +12,12 @@ export default function computed(dependentKeys: string | string[], compute: Func
const dependentValues = {};
let computedValue;
return function() {
return function () {
let recompute = false;
// Read all of the dependent values. If any of them have changed since last
// time, then we'll want to recompute our output.
keys.forEach(key => {
keys.forEach((key) => {
const value = typeof this[key] === 'function' ? this[key]() : this[key];
if (dependentValues[key] !== value) {
@ -29,7 +29,7 @@ export default function computed(dependentKeys: string | string[], compute: Func
if (recompute) {
computedValue = compute.apply(
this,
keys.map(key => dependentValues[key])
keys.map((key) => dependentValues[key])
);
}

View File

@ -6,7 +6,7 @@
*/
export default function extractText(vdom: any): string {
if (vdom instanceof Array) {
return vdom.map(element => extractText(element)).join('');
return vdom.map((element) => extractText(element)).join('');
} else if (typeof vdom === 'object' && vdom !== null) {
return vdom.text || extractText(vdom.children);
} else {

View File

@ -6,7 +6,7 @@ import Component from '../Component';
export default () => {
const mo = window['m'];
const _m = function(comp, ...args) {
const _m = function (comp, ...args) {
if (!arguments[1]) arguments[1] = {};
if (comp.prototype && comp.prototype instanceof Component) {
@ -34,10 +34,10 @@ export default () => {
return node;
};
Object.keys(mo).forEach(key => (_m[key] = mo[key]));
Object.keys(mo).forEach((key) => (_m[key] = mo[key]));
_m.withAttr = (key: string, cb: Function) =>
function() {
function () {
cb(this.getAttribute(key) || this[key]);
};

View File

@ -2,8 +2,8 @@ import jump from 'jump.js';
import Tooltip from 'tooltip.js';
// add $.fn.tooltip
$.fn.tooltip = function(option) {
return this.each(function(this: HTMLElement) {
$.fn.tooltip = function (option) {
return this.each(function (this: HTMLElement) {
const $this = $(this);
let data = $this.data('bs.tooltip');
const options = (typeof option === 'object' && option) || {};
@ -24,19 +24,19 @@ $.fn.tooltip = function(option) {
};
// add $.fn.outerWidth and $.fn.outerHeight
['width', 'height'].forEach(function(dimension) {
const Dimension = dimension.replace(/./, function(m) {
['width', 'height'].forEach(function (dimension) {
const Dimension = dimension.replace(/./, function (m) {
return m[0].toUpperCase();
});
$.fn[`outer${Dimension}`] = function(margin) {
$.fn[`outer${Dimension}`] = function (margin) {
const elem = this;
if (elem) {
const sides = { width: ['left', 'right'], height: ['top', 'bottom'] };
let size = elem[dimension]();
sides[dimension].forEach(function(side) {
sides[dimension].forEach(function (side) {
if (margin) size += parseInt(elem.css('margin-' + side), 10);
});
@ -49,17 +49,17 @@ $.fn.tooltip = function(option) {
// allow use of $(':input')
// @ts-ignore
$.expr[':']['input'] = function() {
$.expr[':']['input'] = function () {
if ('disabled' in this || ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'].includes(this.tagName)) return this;
};
// add $().hover() method
$.fn.hover = function(hover, leave) {
$.fn.hover = function (hover, leave) {
return this.on('mouseenter', hover).on('mouseleave', leave || hover);
};
// add animated scroll
$.fn.animateScrollTop = function(to, duration = $.fx.speeds._default, callback) {
$.fn.animateScrollTop = function (to, duration = $.fx.speeds._default, callback) {
if (typeof to === 'number') to -= window.scrollY || window.pageYOffset;
jump(to, {
@ -71,7 +71,7 @@ $.fn.animateScrollTop = function(to, duration = $.fx.speeds._default, callback)
};
// add basic $().slideUp() function
$.fn.slideUp = function(duration = $.fx.speeds._default, easing?, callback?) {
$.fn.slideUp = function (duration = $.fx.speeds._default, easing?, callback?) {
this.css({ overflow: 'hidden', height: this.height() });
this.animate(
@ -98,7 +98,7 @@ $.event.special = $.event.special || {};
const bindBeforeSpecialEvents = $.fn.bind;
$.fn.bind = function(eventName, data, callback) {
$.fn.bind = function (eventName, data, callback) {
const el = this;
if (!callback) {
@ -118,14 +118,14 @@ $.fn.bind = function(eventName, data, callback) {
/// intercept and replace the special event handler to add functionality
specialEvent.originalHandler = specialEvent.handler;
specialEvent.handler = function() {
specialEvent.handler = function () {
/// make event argument writable, like on jQuery
const args = Array.prototype.slice.call(arguments);
args[0] = $.extend({}, args[0]);
/// define the event handle, $.event.dispatch is only for newer versions of jQuery
$.event.handle = function() {
$.event.handle = function () {
/// make context of trigger the event element
const args = Array.prototype.slice.call(arguments);
const event = args[0];

View File

@ -28,10 +28,7 @@ export function getPlainContent(string: string): string {
dom.find(getPlainContent.removeSelectors.join(',')).remove();
return dom
.text()
.replace(/\s+/g, ' ')
.trim();
return dom.text().replace(/\s+/g, ' ').trim();
}
/**

View File

@ -146,7 +146,7 @@ export default class AvatarEditor extends Component<AvatarEditorProps> {
.appendTo('body')
.hide()
.click()
.on('change', e => {
.on('change', (e) => {
this.upload($(e.target)[0].files[0]);
});
}
@ -167,7 +167,7 @@ export default class AvatarEditor extends Component<AvatarEditorProps> {
app.request({
method: 'POST',
url: `${app.forum.attribute('apiUrl')}/users/${user.id()}/avatar`,
serialize: raw => raw,
serialize: (raw) => raw,
body,
}).then(this.success.bind(this), this.failure.bind(this));
}

View File

@ -58,7 +58,7 @@ export default class CommentPost extends Post {
// all of the <script> tags in the content and evaluate them. This is
// necessary because TextFormatter outputs them for e.g. syntax highlighting.
if (vnode.contentHtml !== contentHtml) {
this.$('.Post-body script').each(function() {
this.$('.Post-body script').each(function () {
eval.call(window, $(this).text());
});
}

View File

@ -60,7 +60,7 @@ export default class DiscussionList<T extends DiscussionListProps = DiscussionLi
return (
<div className={'DiscussionList' + (this.props.params.q ? ' DiscussionList--searchResults' : '')}>
<ul className="DiscussionList-discussions">
{this.discussions.map(discussion => {
{this.discussions.map((discussion) => {
return (
<li key={discussion.id()} data-id={discussion.id()}>
{DiscussionListItem.component({ discussion, params })}
@ -121,7 +121,7 @@ export default class DiscussionList<T extends DiscussionListProps = DiscussionLi
}
return this.loadResults().then(
results => {
(results) => {
this.discussions = [];
this.parseResults(results);
},

View File

@ -97,7 +97,7 @@ export default class DiscussionListItem<T extends DiscussionListItemProps = Disc
user: user,
ago: humanTime(discussion.createdAt()),
})}
oncreate={vnode => $(vnode.dom).tooltip({ placement: 'right' })}
oncreate={(vnode) => $(vnode.dom).tooltip({ placement: 'right' })}
>
{avatar(user, { title: '' })}
</LinkButton>

View File

@ -97,7 +97,7 @@ export default class DiscussionPage extends Page {
<PostStream
discussion={discussion}
includedPosts={this.includedPosts}
oninit={vnode => {
oninit={(vnode) => {
this.stream = vnode.state;
this.scrubber.stream = vnode.state;
@ -196,13 +196,13 @@ export default class DiscussionPage extends Page {
this.includedPosts = discussion.payload.included
.filter(
record =>
(record) =>
record.type === 'posts' &&
record.relationships &&
record.relationships.discussion &&
record.relationships.discussion.data.id === discussionId
)
.map(record => app.store.getById('posts', record.id))
.map((record) => app.store.getById('posts', record.id))
.sort((a, b) => a.id() - b.id())
.slice(0, 20);
}
@ -262,7 +262,7 @@ export default class DiscussionPage extends Page {
})
);
items.add('scrubber', <PostStreamScrubber oninit={vnode => (this.scrubber = vnode.state)} className="App-titleControl" />, -100);
items.add('scrubber', <PostStreamScrubber oninit={(vnode) => (this.scrubber = vnode.state)} className="App-titleControl" />, -100);
return items;
}

View File

@ -21,7 +21,7 @@ export default class DiscussionsSearchSource extends SearchSource {
include: 'mostRelevantPost',
};
return app.store.find<Discussion>('discussions', params).then(results => (this.results[query] = results));
return app.store.find<Discussion>('discussions', params).then((results) => (this.results[query] = results));
}
view(query: string) {
@ -38,7 +38,7 @@ export default class DiscussionsSearchSource extends SearchSource {
href: app.route('index', { q: query }),
})}
</li>,
results.map(discussion => {
results.map((discussion) => {
const mostRelevantPost = discussion.mostRelevantPost();
return (

View File

@ -48,7 +48,7 @@ export default class IndexPage extends Page {
// are currently present in the cached discussion list. If they differ, we
// will clear the cache and set up a new discussion list component with
// the new parameters.
Object.keys(params).some(key => {
Object.keys(params).some((key) => {
if (app.cache.discussionList!.props.params[key] !== params[key]) {
app.cache.discussionList = null;
return true;
@ -57,7 +57,7 @@ export default class IndexPage extends Page {
}
if (!app.cache.discussionList) {
app.cache.discussionList = new DiscussionList({ params, oninit: vnode => (app.cache.discussionList = vnode.state) });
app.cache.discussionList = new DiscussionList({ params, oninit: (vnode) => (app.cache.discussionList = vnode.state) });
}
app.history.push('index', app.translator.transText('core.forum.header.back_to_index_tooltip'));
@ -225,8 +225,8 @@ export default class IndexPage extends Page {
'sort',
Dropdown.component({
buttonClassName: 'Button',
label: sortOptions[this.params().sort] || Object.keys(sortMap).map(key => sortOptions[key])[0],
children: Object.keys(sortOptions).map(value => {
label: sortOptions[this.params().sort] || Object.keys(sortMap).map((key) => sortOptions[key])[0],
children: Object.keys(sortOptions).map((value) => {
const label = sortOptions[value];
const active = (this.params().sort || Object.keys(sortMap)[0]) === value;

View File

@ -51,8 +51,8 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
// For each of the notification type-method combinations, create and store a
// new checkbox component instance, which we will render in the view.
this.types.forEach(type =>
this.methods.forEach(method => {
this.types.forEach((type) =>
this.methods.forEach((method) => {
const key = this.preferenceKey(type.name, method.name);
const preference = this.props.user.preferences()[key];
@ -60,7 +60,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
state: !!preference,
disabled: typeof preference === 'undefined',
onchange: () => this.toggle([key]),
oninit: vnode => (this.inputs[key] = vnode.state),
oninit: (vnode) => (this.inputs[key] = vnode.state),
});
})
);
@ -72,7 +72,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
<thead>
<tr>
<td />
{this.methods.map(method => (
{this.methods.map((method) => (
<th className="NotificationGrid-groupToggle" onclick={this.toggleMethod.bind(this, method.name)}>
{icon(method.icon)} {method.label}
</th>
@ -81,12 +81,12 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
</thead>
<tbody>
{this.types.map(type => (
{this.types.map((type) => (
<tr>
<td className="NotificationGrid-groupToggle" onclick={this.toggleType.bind(this, type.name)}>
{icon(type.icon)} {type.label}
</td>
{this.methods.map(method => (
{this.methods.map((method) => (
<td className="NotificationGrid-checkbox">{this.inputs[this.preferenceKey(type.name, method.name)].render()}</td>
))}
</tr>
@ -99,7 +99,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
oncreate(vnode) {
super.oncreate(vnode);
this.$('thead .NotificationGrid-groupToggle').bind('mouseenter mouseleave', function(e) {
this.$('thead .NotificationGrid-groupToggle').bind('mouseenter mouseleave', function (e) {
const i = parseInt($(this).index(), 10) + 1;
$(this)
.parents('table')
@ -107,7 +107,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
.toggleClass('highlighted', e.type === 'mouseenter');
});
this.$('tbody .NotificationGrid-groupToggle').bind('mouseenter mouseleave', function(e) {
this.$('tbody .NotificationGrid-groupToggle').bind('mouseenter mouseleave', function (e) {
$(this)
.parent()
.find('td')
@ -124,7 +124,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
const preferences = user.preferences();
const enabled = !preferences[keys[0]];
keys.forEach(key => {
keys.forEach((key) => {
const control = this.inputs[key];
control.loading = true;
@ -135,7 +135,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
m.redraw();
user.save({ preferences }).then(() => {
keys.forEach(key => (this.inputs[key].loading = false));
keys.forEach((key) => (this.inputs[key].loading = false));
m.redraw();
});
@ -145,7 +145,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
* Toggle all notification types for the given method.
*/
toggleMethod(method: string) {
const keys = this.types.map(type => this.preferenceKey(type.name, method)).filter(key => !this.inputs[key].props.disabled);
const keys = this.types.map((type) => this.preferenceKey(type.name, method)).filter((key) => !this.inputs[key].props.disabled);
this.toggle(keys);
}
@ -154,7 +154,7 @@ export default class NotificationGrid extends Component<NotificationGridProps> {
* Toggle all notification methods for the given type.
*/
toggleType(type: string) {
const keys = this.methods.map(method => this.preferenceKey(type, method.name)).filter(key => !this.inputs[key].props.disabled);
const keys = this.methods.map((method) => this.preferenceKey(type, method.name)).filter((key) => !this.inputs[key].props.disabled);
this.toggle(keys);
}

View File

@ -45,11 +45,11 @@ export default class NotificationList extends Component {
<div className="NotificationList-content">
{pages.length
? pages.map(notifications => {
? pages.map((notifications) => {
const groups: { discussion: Discussion; notifications: Notification[] }[] = [];
const discussions = {};
notifications.forEach(notification => {
notifications.forEach((notification) => {
const subject = notification.subject();
if (typeof subject === 'undefined') return;
@ -72,7 +72,7 @@ export default class NotificationList extends Component {
}
});
return groups.map(group => {
return groups.map((group) => {
const badges = group.discussion?.badges().toArray();
return (
@ -91,7 +91,7 @@ export default class NotificationList extends Component {
)}
<ul className="NotificationGroup-content">
{group.notifications.map(notification => {
{group.notifications.map((notification) => {
const NotificationComponent = app.notificationComponents[notification.contentType()];
return NotificationComponent ? <li>{NotificationComponent.component({ notification })}</li> : '';
})}
@ -199,8 +199,8 @@ export default class NotificationList extends Component {
app.session.user.pushAttributes({ unreadNotificationCount: 0 });
app.cache.notifications.forEach(notifications => {
notifications.forEach(notification => notification.pushAttributes({ isRead: true }));
app.cache.notifications.forEach((notifications) => {
notifications.forEach((notification) => notification.pushAttributes({ isRead: true }));
});
app.request({

View File

@ -37,9 +37,7 @@ export default class PostEdited extends Component<PostProp> {
super.onupdate(vnode);
if (this.shouldUpdateTooltip) {
this.$()
.tooltip('destroy')
.tooltip();
this.$().tooltip('destroy').tooltip();
this.shouldUpdateTooltip = false;
}
}

View File

@ -13,13 +13,8 @@ export default class PostMeta extends Component<PostProp> {
// When the dropdown menu is shown, select the contents of the permalink
// input so that the user can quickly copy the URL.
const selectPermalink = function(this: HTMLElement) {
setTimeout(() =>
$(this)
.parent()
.find('.PostMeta-permalink')
.select()
);
const selectPermalink = function (this: HTMLElement) {
setTimeout(() => $(this).parent().find('.PostMeta-permalink').select());
};
return (
@ -36,7 +31,7 @@ export default class PostMeta extends Component<PostProp> {
{permalink}
</a>
) : (
<input className="FormControl PostMeta-permalink" value={permalink} onclick={e => e.stopPropagation()} />
<input className="FormControl PostMeta-permalink" value={permalink} onclick={(e) => e.stopPropagation()} />
)}
</div>
</div>

View File

@ -184,7 +184,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
return this.discussion
.postIds()
.slice(this.visibleStart, this.visibleEnd)
.map(id => {
.map((id) => {
const post = app.store.getById<Post>('posts', id);
return post && post.discussion() && typeof post.canEdit() !== 'undefined' ? post : null;
@ -193,10 +193,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
view() {
function fadeIn(vnode) {
if (!vnode.state.fadedIn)
$(vnode.dom)
.hide()
.fadeIn();
if (!vnode.state.fadedIn) $(vnode.dom).hide().fadeIn();
vnode.state.fadedIn = true;
}
@ -409,7 +406,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
this.discussion
.postIds()
.slice(start, end)
.forEach(id => {
.forEach((id) => {
const post = app.store.getById<Post>('posts', id);
if (post && post.discussion() && typeof post.canEdit() !== 'undefined') {
@ -428,7 +425,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
* resolved immediately.
*/
loadNearNumber(number: string | number): Promise<void> {
if (this.posts().some(post => post && Number(post.number()) === Number(number))) {
if (this.posts().some((post) => post && Number(post.number()) === Number(number))) {
return Promise.resolve();
}
@ -554,7 +551,7 @@ class PostStream<T extends PostStreamProps = PostStreamProps> extends Component<
// TODO const top = bottom ? itemBottom - $(window).height() + app.composer.computedHeight() : $item.is(':first-child') ? 0 : itemTop;
const top = bottom ? itemBottom - $(window).height() : $item.is(':first-child') ? 0 : itemTop;
return new Promise<void>(resolve => {
return new Promise<void>((resolve) => {
if (noAnimation) {
$container.scrollTop(top);
resolve();

View File

@ -196,7 +196,7 @@ export default class PostStreamScrubber extends Component {
// Now loop through each of the items in the discussion. An 'item' is
// either a single post or a 'gap' of one or more posts that haven't
// been loaded yet.
$items.each(function(this: HTMLElement) {
$items.each(function (this: HTMLElement) {
const $this = $(this);
const top = $this.offset().top;
const height = $this.outerHeight(true);
@ -268,14 +268,14 @@ export default class PostStreamScrubber extends Component {
// Now we want to make the scrollbar handle draggable. Let's start by
// preventing default browser events from messing things up.
.css({ cursor: 'pointer', 'user-select': 'none' })
.on('dragstart mousedown touchstart', e => e.preventDefault());
.on('dragstart mousedown touchstart', (e) => e.preventDefault());
this.$('.Scrubber-handle')
.css('cursor', 'move')
.on('mousedown touchstart', this.onmousedown.bind(this) as ZeptoEventHandler)
// Exempt the scrollbar handle from the 'jump to' click event.
.click(e => e.stopPropagation());
.click((e) => e.stopPropagation());
// When the mouse moves and when it is released, we pass the
// information that we captured when the mouse was first pressed onto
@ -293,9 +293,7 @@ export default class PostStreamScrubber extends Component {
$(window).off('resize', this.handlers.onresize);
$(document)
.off('mousemove touchmove', this.handlers.onmousemove)
.off('mouseup touchend', this.handlers.onmouseup);
$(document).off('mousemove touchmove', this.handlers.onmousemove).off('mouseup touchend', this.handlers.onmouseup);
}
/**

View File

@ -70,7 +70,7 @@ export default class PostsUserPage extends UserPage {
return (
<div className="PostsUserPage">
<ul className="PostsUserPage-list">
{this.posts.map(post => (
{this.posts.map((post) => (
<li>
<div className="PostsUserPage-discussion">
{app.translator.trans('core.forum.user.in_discussion_text', {

View File

@ -105,7 +105,7 @@ export default class Search extends Component {
)}
</div>
<ul className="Dropdown-menu Search-results">
{this.value() && this.hasFocus ? this.sources.map(source => source.view(this.value())) : ''}
{this.value() && this.hasFocus ? this.sources.map((source) => source.view(this.value())) : ''}
</ul>
</div>
);
@ -120,11 +120,11 @@ export default class Search extends Component {
const search = this;
this.$('.Search-results')
.on('mousedown', e => e.preventDefault())
.on('mousedown', (e) => e.preventDefault())
.on('click', () => this.$('input').blur())
// Whenever the mouse is hovered over a search result, highlight it.
.on('mouseenter', '> li:not(.Dropdown-header)', function(this: HTMLElement) {
.on('mouseenter', '> li:not(.Dropdown-header)', function (this: HTMLElement) {
search.setIndex(search.selectableItems().index(this));
});
@ -139,7 +139,7 @@ export default class Search extends Component {
// Handle input key events on the search input, triggering results to load.
$input
.on('input focus', function(this: HTMLInputElement) {
.on('input focus', function (this: HTMLInputElement) {
const query = this.value.toLowerCase();
if (!query) return;
@ -149,7 +149,7 @@ export default class Search extends Component {
if (search.searched.indexOf(query) !== -1) return;
if (query.length >= 3 && search.sources) {
search.sources.map(source => {
search.sources.map((source) => {
if (!source.search) return;
search.loadingSources++;
@ -166,9 +166,9 @@ export default class Search extends Component {
}, 250);
})
.on('focus', function(this: HTMLElement) {
.on('focus', function (this: HTMLElement) {
$(this)
.one('mouseup', e => e.preventDefault())
.one('mouseup', (e) => e.preventDefault())
.select();
});
}
@ -188,11 +188,7 @@ export default class Search extends Component {
this.loadingSources = 0;
if (this.value()) {
m.route.set(
this.getItem(this.index)
.find('a')
.attr('href')
);
m.route.set(this.getItem(this.index).find('a').attr('href'));
} else {
this.clear();
}
@ -274,10 +270,7 @@ export default class Search extends Component {
fixedIndex = 0;
}
const $item = $items
.removeClass('active')
.eq(fixedIndex)
.addClass('active');
const $item = $items.removeClass('active').eq(fixedIndex).addClass('active');
this.index = Number($item.attr('data-index') || fixedIndex);

View File

@ -85,7 +85,7 @@ export default abstract class UserPage extends Page {
this.username = lowercaseUsername;
app.store.all<User>('users').some(user => {
app.store.all<User>('users').some((user) => {
if ((user.username().toLowerCase() === lowercaseUsername || user.id() === username) && user.joinTime()) {
this.show(user);
return true;

View File

@ -19,7 +19,7 @@ export default class UsersSearchSource extends SearchSource {
filter: { q: query },
page: { limit: 5 },
})
.then(results => {
.then((results) => {
this.results[query] = results;
m.redraw();
});
@ -32,7 +32,7 @@ export default class UsersSearchSource extends SearchSource {
.concat(
app.store
.all<User>('users')
.filter(user => [user.username(), user.displayName()].some(value => value.toLowerCase().substr(0, query.length) === query))
.filter((user) => [user.username(), user.displayName()].some((value) => value.toLowerCase().substr(0, query.length) === query))
)
.filter((e, i, arr) => arr.lastIndexOf(e) === i)
.sort((a, b) => a.displayName().localeCompare(b.displayName()));
@ -41,7 +41,7 @@ export default class UsersSearchSource extends SearchSource {
return [
<li className="Dropdown-header">{app.translator.trans('core.forum.search.users_heading')}</li>,
results.map(user => {
results.map((user) => {
const name = username(user);
if (!name.children) {

View File

@ -8,7 +8,7 @@ import Discussion from '../common/models/Discussion';
import Post from '../common/models/Post';
import User from '../common/models/User';
export default app => {
export default (app) => {
app.routes = {
index: { path: '/all', component: IndexPage },

View File

@ -24,10 +24,10 @@ export default {
controls(discussion: Discussion, context: any): ItemList {
const items = new ItemList();
['user', 'moderation', 'destructive'].forEach(section => {
['user', 'moderation', 'destructive'].forEach((section) => {
const controls = this[section](discussion, context).toArray();
if (controls.length) {
controls.forEach(item => items.add(item.itemName, item));
controls.forEach((item) => items.add(item.itemName, item));
items.add(section + 'Separator', Separator.component());
}
});

View File

@ -26,7 +26,7 @@ export default class KeyboardNavigatable {
* This will be triggered by the Up key.
*/
onUp(callback: KeyboardEventCallback): this {
this.callbacks[38] = e => {
this.callbacks[38] = (e) => {
e.preventDefault();
callback(e);
};
@ -40,7 +40,7 @@ export default class KeyboardNavigatable {
* This will be triggered by the Down key.
*/
onDown(callback: KeyboardEventCallback): this {
this.callbacks[40] = e => {
this.callbacks[40] = (e) => {
e.preventDefault();
callback(e);
};
@ -54,7 +54,7 @@ export default class KeyboardNavigatable {
* This will be triggered by the Return and Tab keys..
*/
onSelect(callback: KeyboardEventCallback): this {
this.callbacks[9] = this.callbacks[13] = e => {
this.callbacks[9] = this.callbacks[13] = (e) => {
e.preventDefault();
callback(e);
};
@ -68,7 +68,7 @@ export default class KeyboardNavigatable {
* This will be triggered by the Escape key.
*/
onCancel(callback: Function): this {
this.callbacks[27] = e => {
this.callbacks[27] = (e) => {
e.stopPropagation();
e.preventDefault();
callback(e);
@ -83,7 +83,7 @@ export default class KeyboardNavigatable {
* This will be triggered by the Backspace key.
*/
onRemove(callback: Function): this {
this.callbacks[8] = e => {
this.callbacks[8] = (e) => {
if (e.target.selectionStart === 0 && e.target.selectionEnd === 0) {
callback(e);
e.preventDefault();

View File

@ -23,11 +23,11 @@ export default {
controls(post: Post, context: any) {
const items = new ItemList();
['user', 'moderation', 'destructive'].forEach(section => {
['user', 'moderation', 'destructive'].forEach((section) => {
const controls = this[section](post, context).toArray();
if (controls.length) {
controls.forEach(item => items.add(item.itemName, item));
controls.forEach((item) => items.add(item.itemName, item));
items.add(section + 'Separator', Separator.component());
}
});
@ -128,7 +128,7 @@ export default {
* Open the composer to edit a post.
*/
editAction(this: Post) {
return new Promise<EditPostComposer>(resolve => {
return new Promise<EditPostComposer>((resolve) => {
const component = new EditPostComposer({ post: this });
app.composer.load(component);

View File

@ -21,10 +21,10 @@ export default {
controls(user: User, context: any): ItemList {
const items = new ItemList();
['user', 'moderation', 'destructive'].forEach(section => {
['user', 'moderation', 'destructive'].forEach((section) => {
const controls = this[section](user, context).toArray();
if (controls.length) {
controls.forEach(item => items.add(item.itemName, item));
controls.forEach((item) => items.add(item.itemName, item));
items.add(section + 'Separator', Separator.component());
}
});

View File

@ -47,7 +47,7 @@ module.exports = (options = {}) => {
// Set up entry points for each of the forum + admin apps, but only
// if they exist.
entry: (function() {
entry: (function () {
const entries = {};
for (const app of ['forum', 'admin']) {
@ -116,7 +116,7 @@ module.exports = (options = {}) => {
mithril: 'm',
},
(function() {
(function () {
const externals = {};
if (options.useExtensions) {
@ -130,7 +130,7 @@ module.exports = (options = {}) => {
})(),
// Support importing old-style core modules.
function(context, request, callback) {
function (context, request, callback) {
const matches = /^flarum\/(.+?)(?:\/(.+))?$/.exec(request);
if (matches) {