1
0
mirror of https://github.com/flarum/core.git synced 2025-08-13 11:54:32 +02:00

Compare commits

...

10 Commits

Author SHA1 Message Date
Alexander Skvortsov
3ef541a152 Webpack 5, use v1 of flarum webpack config 2021-05-09 14:02:34 -04:00
Alexander Skvortsov
81894d7cc2 Implement registry, move patchMithril call to Application boot. 2021-05-09 14:01:10 -04:00
Alexander Skvortsov
97aa569bfa Don't export objects directly 2021-05-09 13:59:34 -04:00
Alexander Skvortsov
7d80b88d5c Add semicolons in flarum.extension assignments
Without these, content generated by webpack 5 breaks
2021-05-09 01:30:13 -04:00
flarum-bot
2cd1c2964a Bundled output for commit 8a451e0bfc [skip ci] 2021-05-07 16:31:01 +00:00
Alexander Skvortsov
8a451e0bfc Fix exception in bootExtensions
Frontend extenders exist in a weird state of limbo, where they are technically defined, but aren't used or tested at all. In da5db714c2, we shifted from passing `extension.extend` to `flattenDeep` to calling `flat` on `extension.extend`. If an extension doesn't define extenders (as is the case for most extensions), the change breaks the forum. All we do here is add a null check.
2021-05-07 12:29:10 -04:00
flarum-bot
0b9ad5425c Bundled output for commit da5db714c2 [skip ci] 2021-05-05 23:29:41 +00:00
David Wheatley
da5db714c2 Remove lodash from core (#2827)
* Remove `lodash-es` dependency

* Replace `escapeRegExp` with home-made util

* Replace `throttle` with `throttle-debounce` library

* Use native browser methods for `deepFlatten`

We need a polyfill for iOS 11 and below. I think using a native method with this polyfill is better than having our own function instead, even if the bundle size is ~150B more.

* Save a few bytes in `escapeRegExp`

* Fix typo in comment

* Undo import re-organisation

* Use spread instead of slice

* Use smaller Array.flat polyfill from MDN

* Export new utils in `compat.js`
2021-05-06 00:28:22 +01:00
flarum-bot
d4a2357a32 Bundled output for commit 588a9f952f [skip ci] 2021-05-05 14:47:48 +00:00
David Wheatley
588a9f952f Remove unneeded delete (#2835) 2021-05-05 15:46:23 +01:00
22 changed files with 156 additions and 80 deletions

6
js/dist/admin.js generated vendored

File diff suppressed because one or more lines are too long

2
js/dist/admin.js.map generated vendored

File diff suppressed because one or more lines are too long

10
js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

2
js/dist/forum.js.map generated vendored

File diff suppressed because one or more lines are too long

58
js/package-lock.json generated
View File

@@ -15,16 +15,15 @@
"expose-loader": "^1.0.3",
"jquery": "^3.6.0",
"jquery.hotkeys": "^0.1.0",
"lodash-es": "^4.17.21",
"mithril": "^2.0.4",
"punycode": "^2.1.1",
"spin.js": "^3.1.0",
"textarea-caret": "^3.1.0"
"textarea-caret": "^3.1.0",
"throttle-debounce": "^3.0.1"
},
"devDependencies": {
"@babel/preset-typescript": "^7.13.0",
"@types/jquery": "^3.5.5",
"@types/lodash-es": "^4.17.4",
"@types/mithril": "^2.0.7",
"@types/punycode": "^2.1.0",
"@types/textarea-caret": "^3.0.0",
@@ -1498,21 +1497,6 @@
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA=="
},
"node_modules/@types/lodash": {
"version": "4.14.168",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz",
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==",
"dev": true
},
"node_modules/@types/lodash-es": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.4.tgz",
"integrity": "sha512-BBz79DCJbD2CVYZH67MBeHZRX++HF+5p8Mo5MzjZi64Wac39S3diedJYHZtScbRVf4DjZyN6LzA0SB0zy+HSSQ==",
"dev": true,
"dependencies": {
"@types/lodash": "*"
}
},
"node_modules/@types/mithril": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.0.7.tgz",
@@ -4669,11 +4653,6 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -6660,6 +6639,14 @@
"resolved": "https://registry.npmjs.org/textarea-caret/-/textarea-caret-3.1.0.tgz",
"integrity": "sha512-cXAvzO9pP5CGa6NKx0WYHl+8CHKZs8byMkt3PCJBCmq2a34YA9pO1NrQET5pzeqnBjBdToF5No4rrmkDUgQC2Q=="
},
"node_modules/throttle-debounce": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
"integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==",
"engines": {
"node": ">=10"
}
},
"node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
@@ -8885,21 +8872,6 @@
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz",
"integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA=="
},
"@types/lodash": {
"version": "4.14.168",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz",
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==",
"dev": true
},
"@types/lodash-es": {
"version": "4.17.4",
"resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.4.tgz",
"integrity": "sha512-BBz79DCJbD2CVYZH67MBeHZRX++HF+5p8Mo5MzjZi64Wac39S3diedJYHZtScbRVf4DjZyN6LzA0SB0zy+HSSQ==",
"dev": true,
"requires": {
"@types/lodash": "*"
}
},
"@types/mithril": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.0.7.tgz",
@@ -11399,11 +11371,6 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -13016,6 +12983,11 @@
"resolved": "https://registry.npmjs.org/textarea-caret/-/textarea-caret-3.1.0.tgz",
"integrity": "sha512-cXAvzO9pP5CGa6NKx0WYHl+8CHKZs8byMkt3PCJBCmq2a34YA9pO1NrQET5pzeqnBjBdToF5No4rrmkDUgQC2Q=="
},
"throttle-debounce": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz",
"integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg=="
},
"through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",

View File

@@ -8,31 +8,30 @@
"clsx": "^1.1.1",
"color-thief-browser": "^2.0.2",
"dayjs": "^1.10.4",
"expose-loader": "^1.0.3",
"expose-loader": "^2.0.0",
"jquery": "^3.6.0",
"jquery.hotkeys": "^0.1.0",
"lodash-es": "^4.17.21",
"mithril": "^2.0.4",
"punycode": "^2.1.1",
"spin.js": "^3.1.0",
"textarea-caret": "^3.1.0"
"textarea-caret": "^3.1.0",
"throttle-debounce": "^3.0.1"
},
"devDependencies": {
"@babel/preset-typescript": "^7.13.0",
"@types/jquery": "^3.5.5",
"@types/lodash-es": "^4.17.4",
"@types/mithril": "^2.0.7",
"@types/punycode": "^2.1.0",
"@types/textarea-caret": "^3.0.0",
"bundlewatch": "^0.3.2",
"cross-env": "^7.0.3",
"flarum-webpack-config": "0.1.0-beta.10",
"flarum-webpack-config": "^1.0.0",
"husky": "^4.3.8",
"prettier": "^2.2.1",
"webpack": "^4.46.0",
"webpack-bundle-analyzer": "^4.4.0",
"webpack-cli": "^3.3.12",
"webpack-merge": "^4.2.2"
"webpack": "^5.0.0",
"webpack-bundle-analyzer": "^4.4.1",
"webpack-cli": "^4.0.0",
"webpack-merge": "^4.0.0"
},
"scripts": {
"dev": "webpack --mode development --watch",

View File

@@ -100,8 +100,6 @@ export default class AdminPage extends Page {
const { setting, help, ...componentAttrs } = entry;
delete componentAttrs.help;
const value = this.setting([setting])();
if (['bool', 'checkbox', 'switch', 'boolean'].includes(componentAttrs.type)) {
return (

View File

@@ -12,6 +12,7 @@ import mapRoutes from './utils/mapRoutes';
import RequestError from './utils/RequestError';
import ScrollListener from './utils/ScrollListener';
import liveHumanTimes from './utils/liveHumanTimes';
import patchMithril from './utils/patchMithril';
import { extend } from './extend';
import Forum from './models/Forum';
@@ -20,7 +21,6 @@ import Discussion from './models/Discussion';
import Post from './models/Post';
import Group from './models/Group';
import Notification from './models/Notification';
import { flattenDeep } from 'lodash-es';
import PageState from './states/PageState';
import ModalManagerState from './states/ModalManagerState';
import AlertManagerState from './states/AlertManagerState';
@@ -167,6 +167,8 @@ export default class Application {
}
boot() {
patchMithril(window);
this.initializers.toArray().forEach((initializer) => initializer(this));
this.store.pushPayload({ data: this.data.resources });
@@ -180,11 +182,15 @@ export default class Application {
this.initialRoute = window.location.href;
}
// TODO: This entire system needs a do-over for v2
bootExtensions(extensions) {
Object.keys(extensions).forEach((name) => {
const extension = extensions[name];
const extenders = flattenDeep(extension.extend);
// If an extension doesn't define extenders, there's nothing more to do here.
if (!extension.extend) return;
const extenders = extension.extend.flat(Infinity);
for (const extender of extenders) {
extender.extend(this, { name, exports: extension });

View File

@@ -0,0 +1,60 @@
interface ExportRegistry {
moduleExports: object;
onLoads: object;
/**
* Add an instance to the registry.
* This serves as the equivalent of `flarum.core.compat[id] = object`
*/
add(namespace: string, id: string, object: any): void;
/**
* Add a function to run when object of id "id" is added (or overriden).
* If such an object is already registered, the handler will be applied immediately.
*/
onLoad(namespace: string, id: string, handler: Function): void;
/**
* Retrieve an object of type `id` from the registry.
*/
get(namespace: string, id: string): any;
}
export default class FlarumRegistry implements ExportRegistry {
moduleExports = new Map<string, any>();
onLoads = new Map<string, Function[]>();
protected genKey(namespace: string, id: string): string {
return `${namespace};${id}`;
}
add(namespace: string, id: string, object: any) {
const key = this.genKey(namespace, id);
const onLoads = this.onLoads.get(key);
if (onLoads) {
onLoads.reduce((acc, handler) => handler(acc), object);
}
this.moduleExports.set(key, object);
}
onLoad(namespace: string, id: string, handler: Function) {
const key = this.genKey(namespace, id);
const loadedObject = this.moduleExports.get(key);
if (loadedObject) {
this.moduleExports[id] = handler(loadedObject);
} else {
const currOnLoads = this.onLoads.get(key);
this.onLoads.set(key, [...(currOnLoads || []), handler]);
}
}
get(namespace: string, id: string): any {
const key = this.genKey(namespace, id);
return this.moduleExports.get(key);
}
}

View File

@@ -12,7 +12,9 @@ import Drawer from './utils/Drawer';
import anchorScroll from './utils/anchorScroll';
import RequestError from './utils/RequestError';
import abbreviateNumber from './utils/abbreviateNumber';
import escapeRegExp from './utils/escapeRegExp';
import * as string from './utils/string';
import * as ThrottleDebounce from './utils/throttleDebounce';
import Stream from './utils/Stream';
import SubtreeRetainer from './utils/SubtreeRetainer';
import setRouteWithForcedRefresh from './utils/setRouteWithForcedRefresh';
@@ -91,6 +93,7 @@ export default {
'utils/abbreviateNumber': abbreviateNumber,
'utils/string': string,
'utils/SubtreeRetainer': SubtreeRetainer,
'utils/escapeRegExp': escapeRegExp,
'utils/extract': extract,
'utils/ScrollListener': ScrollListener,
'utils/stringToColor': stringToColor,
@@ -104,6 +107,7 @@ export default {
'utils/formatNumber': formatNumber,
'utils/mapRoutes': mapRoutes,
'utils/withAttr': withAttr,
'utils/throttleDebounce': ThrottleDebounce,
'models/Notification': Notification,
'models/User': User,
'models/Post': Post,

View File

@@ -1,5 +1,5 @@
// Expose jQuery, mithril and dayjs to the window browser object
import 'expose-loader?exposes[]=$&exposes[]=jQuery!jquery';
import 'expose-loader?exposes=$,jQuery!jquery';
import 'expose-loader?exposes=m!mithril';
import 'expose-loader?exposes=dayjs!dayjs';
@@ -16,10 +16,12 @@ import localizedFormat from 'dayjs/plugin/localizedFormat';
dayjs.extend(relativeTime);
dayjs.extend(localizedFormat);
import patchMithril from './utils/patchMithril';
import FlarumRegistry from './FlarumRegistry';
patchMithril(window);
window.flreg = new FlarumRegistry();
import * as Extend from './extend/index';
export { Extend };
import './utils/arrayFlatPolyfill';

View File

@@ -0,0 +1,14 @@
// Based off of the polyfill on MDN
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat#reduce_concat_isarray_recursivity
//
// Needed to provide support for Safari on iOS < 12
if (!Array.prototype['flat']) {
Array.prototype['flat'] = function flat(this: any[], depth: number = 1): any[] {
return depth > 0
? Array.prototype.reduce.call(this, (acc, val): any[] => acc.concat(Array.isArray(val) ? flat.call(val, depth - 1) : val), [])
: // If no depth is provided, or depth is 0, just return a copy of
// the array. Spread is supported in all major browsers (iOS 8+)
[...this];
};
}

View File

@@ -0,0 +1,10 @@
const specialChars = /[.*+?^${}()|[\]\\]/g;
/**
* Escapes the `RegExp` special characters in `input`.
*
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping
*/
export default function escapeRegExp(input: string): string {
return input.replace(specialChars, '\\$&');
}

View File

@@ -2,7 +2,7 @@
* The `evented` mixin provides methods allowing an object to trigger events,
* running externally registered event handlers.
*/
export default {
const evented = {
/**
* Arrays of registered event handlers, grouped by the event name.
*
@@ -79,3 +79,5 @@ export default {
}
},
};
export default evented;

View File

@@ -0,0 +1,3 @@
// Re-exports `throttle-debounce` to be used in `compat.js`.
export { throttle, debounce } from 'throttle-debounce';

View File

@@ -15,8 +15,8 @@ import slidable from '../utils/slidable';
import extractText from '../../common/utils/extractText';
import classList from '../../common/utils/classList';
import DiscussionPage from './DiscussionPage';
import escapeRegExp from '../../common/utils/escapeRegExp';
import { escapeRegExp } from 'lodash-es';
/**
* The `DiscussionListItem` component shows a single discussion in the
* discussion list.

View File

@@ -1,4 +1,4 @@
import { throttle } from 'lodash-es';
import { throttle } from 'throttle-debounce';
import anchorScroll from '../../common/utils/anchorScroll';
class PostStreamState {
@@ -50,8 +50,8 @@ class PostStreamState {
*/
this.forceUpdateScrubber = false;
this.loadNext = throttle(this._loadNext, 300);
this.loadPrevious = throttle(this._loadPrevious, 300);
this.loadNext = throttle(300, this._loadNext);
this.loadPrevious = throttle(300, this._loadPrevious);
this.show(includedPosts);
}

View File

@@ -11,7 +11,7 @@ import extractText from '../../common/utils/extractText';
* The `DiscussionControls` utility constructs a list of buttons for a
* discussion which perform actions on it.
*/
export default {
const DiscussionControls = {
/**
* Get a list of controls for a discussion.
*
@@ -259,3 +259,5 @@ export default {
});
},
};
export default DiscussionControls;

View File

@@ -8,7 +8,7 @@ import extractText from '../../common/utils/extractText';
* The `PostControls` utility constructs a list of buttons for a post which
* perform actions on it.
*/
export default {
const PostControls = {
/**
* Get a list of controls for a post.
*
@@ -199,3 +199,5 @@ export default {
});
},
};
export default PostControls;

View File

@@ -8,7 +8,7 @@ import ItemList from '../../common/utils/ItemList';
* The `UserControls` utility constructs a list of buttons for a user which
* perform actions on it.
*/
export default {
const UserControls = {
/**
* Get a list of controls for a user.
*
@@ -141,3 +141,5 @@ export default {
app.modal.show(EditUserModal, { user });
},
};
export default UserControls;

View File

@@ -24,4 +24,4 @@ module.exports = merge(config(), {
});
module.exports['module'].rules[0].test = /\.(tsx?|js)$/;
module.exports['module'].rules[0].use.options.presets.push('@babel/preset-typescript');
module.exports['module'].rules[0].use[1].options.presets.push('@babel/preset-typescript');

View File

@@ -97,11 +97,11 @@ class Frontend implements ExtenderInterface
if ($this->js) {
$assets->js(function (SourceCollector $sources) use ($moduleName) {
$sources->addString(function () {
return 'var module={}';
return 'var module={};';
});
$sources->addFile($this->js);
$sources->addString(function () use ($moduleName) {
return "flarum.extensions['$moduleName']=module.exports";
return "flarum.extensions['$moduleName']=module.exports;";
});
});
}