diff --git a/.bundlewatch.config.json b/.bundlewatch.config.json
index e86ccd8289..ea2aa4f98c 100644
--- a/.bundlewatch.config.json
+++ b/.bundlewatch.config.json
@@ -4,9 +4,17 @@
"path": "./framework/core/js/dist/*.js",
"maxSize": "150KB"
},
+ {
+ "path": "./framework/core/js/dist/*/**/*.js",
+ "maxSize": "30KB"
+ },
{
"path": "./extensions/*/js/dist/*.js",
"maxSize": "30KB"
+ },
+ {
+ "path": "./extensions/*/js/dist/*/**/*.js",
+ "maxSize": "30KB"
}
],
"defaultCompression": "gzip",
diff --git a/extensions/embed/js/src/forum/index.js b/extensions/embed/js/src/forum/index.js
index ecdd52508c..f858688120 100644
--- a/extensions/embed/js/src/forum/index.js
+++ b/extensions/embed/js/src/forum/index.js
@@ -4,8 +4,6 @@ import { override, extend } from 'flarum/common/extend';
import app from 'flarum/forum/app';
import Stream from 'flarum/common/utils/Stream';
import ForumApplication from 'flarum/forum/ForumApplication';
-import Composer from 'flarum/forum/components/Composer';
-import PostStream from 'flarum/forum/components/PostStream';
import ModalManager from 'flarum/common/components/ModalManager';
import PostMeta from 'flarum/forum/components/PostMeta';
@@ -13,7 +11,7 @@ import DiscussionPage from 'flarum/forum/components/DiscussionPage';
extend(ForumApplication.prototype, 'mount', function () {
if (m.route.param('hideFirstPost')) {
- extend(PostStream.prototype, 'view', (vdom) => {
+ extend('flarum/forum/components/PostStream', 'view', (vdom) => {
if (vdom.children[0].attrs['data-number'] === 1) {
vdom.children.splice(0, 1);
}
@@ -42,7 +40,7 @@ const reposition = function () {
};
extend(ModalManager.prototype, 'show', reposition);
-extend(Composer.prototype, 'show', reposition);
+extend('flarum/forum/components/Composer', 'show', reposition);
window.iFrameResizer = {
readyCallback: function () {
@@ -50,7 +48,7 @@ window.iFrameResizer = {
},
};
-extend(PostStream.prototype, 'goToNumber', function (promise, number) {
+extend('flarum/forum/components/PostStream', 'goToNumber', function (promise, number) {
if (number === 'reply' && 'parentIFrame' in window && app.composer.isFullScreen()) {
const itemTop = this.$('.PostStream-item:last').offset().top;
window.parentIFrame.scrollToOffset(0, itemTop);
diff --git a/extensions/emoji/extend.php b/extensions/emoji/extend.php
index 54a5d79780..00d190b91b 100644
--- a/extensions/emoji/extend.php
+++ b/extensions/emoji/extend.php
@@ -13,7 +13,8 @@
return [
(new Extend\Frontend('forum'))
->js(__DIR__.'/js/dist/forum.js')
- ->css(__DIR__.'/less/forum.less'),
+ ->css(__DIR__.'/less/forum.less')
+ ->jsDirectory(__DIR__.'/js/dist/forum'),
(new Extend\Formatter)
->configure(function (Configurator $config) {
diff --git a/extensions/emoji/js/src/forum/addComposerAutocomplete.js b/extensions/emoji/js/src/forum/addComposerAutocomplete.js
index 195dc605d0..4aa886fcf5 100644
--- a/extensions/emoji/js/src/forum/addComposerAutocomplete.js
+++ b/extensions/emoji/js/src/forum/addComposerAutocomplete.js
@@ -1,7 +1,4 @@
-import emojiMap from 'simple-emoji-map';
-
import { extend } from 'flarum/common/extend';
-import TextEditor from 'flarum/common/components/TextEditor';
import TextEditorButton from 'flarum/common/components/TextEditorButton';
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
@@ -10,11 +7,15 @@ import getEmojiIconCode from './helpers/getEmojiIconCode';
import cdn from './cdn';
export default function addComposerAutocomplete() {
- const emojiKeys = Object.keys(emojiMap);
const $container = $('
');
const dropdown = new AutocompleteDropdown();
+ let emojiMap = null;
+
+ extend('flarum/common/components/TextEditor', 'oninit', function () {
+ this._loaders.push(async () => await import('./emojiMap').then((m) => (emojiMap = m.default)));
+ });
- extend(TextEditor.prototype, 'oncreate', function () {
+ extend('flarum/common/components/TextEditor', 'onbuild', function () {
const $editor = this.$('.TextEditor-editor').wrap('');
this.navigator = new KeyboardNavigatable();
@@ -29,7 +30,9 @@ export default function addComposerAutocomplete() {
$editor.after($container);
});
- extend(TextEditor.prototype, 'buildEditorParams', function (params) {
+ extend('flarum/common/components/TextEditor', 'buildEditorParams', function (params) {
+ const emojiKeys = Object.keys(emojiMap);
+
let relEmojiStart;
let absEmojiStart;
let typed;
@@ -166,7 +169,7 @@ export default function addComposerAutocomplete() {
});
});
- extend(TextEditor.prototype, 'toolbarItems', function (items) {
+ extend('flarum/common/components/TextEditor', 'toolbarItems', function (items) {
items.add(
'emoji',
this.attrs.composer.editor.insertAtCursor(' :')} icon="far fa-smile">
diff --git a/extensions/emoji/js/src/forum/emojiMap.ts b/extensions/emoji/js/src/forum/emojiMap.ts
new file mode 100644
index 0000000000..25d34d6cb2
--- /dev/null
+++ b/extensions/emoji/js/src/forum/emojiMap.ts
@@ -0,0 +1,3 @@
+import emojiMap from 'simple-emoji-map';
+
+export default emojiMap;
diff --git a/extensions/likes/js/src/forum/index.js b/extensions/likes/js/src/forum/index.js
index 29d7a1d653..45adb6891f 100644
--- a/extensions/likes/js/src/forum/index.js
+++ b/extensions/likes/js/src/forum/index.js
@@ -1,6 +1,5 @@
import { extend } from 'flarum/common/extend';
import app from 'flarum/forum/app';
-import NotificationGrid from 'flarum/forum/components/NotificationGrid';
import addLikeAction from './addLikeAction';
import addLikesList from './addLikesList';
@@ -16,7 +15,7 @@ app.initializers.add('flarum-likes', () => {
addLikesList();
addLikesTabToUserProfile();
- extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
+ extend('flarum/forum/components/NotificationGrid', 'notificationTypes', function (items) {
items.add('postLiked', {
name: 'postLiked',
icon: 'far fa-thumbs-up',
diff --git a/extensions/lock/js/src/forum/index.js b/extensions/lock/js/src/forum/index.js
index 0ac405d3cf..fd3f9cda02 100644
--- a/extensions/lock/js/src/forum/index.js
+++ b/extensions/lock/js/src/forum/index.js
@@ -1,6 +1,5 @@
import { extend } from 'flarum/common/extend';
import app from 'flarum/forum/app';
-import NotificationGrid from 'flarum/forum/components/NotificationGrid';
import DiscussionLockedNotification from './components/DiscussionLockedNotification';
import addLockBadge from './addLockBadge';
@@ -14,7 +13,7 @@ app.initializers.add('flarum-lock', () => {
addLockBadge();
addLockControl();
- extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
+ extend('flarum/forum/components/NotificationGrid', 'notificationTypes', function (items) {
items.add('discussionLocked', {
name: 'discussionLocked',
icon: 'fas fa-lock',
diff --git a/extensions/markdown/js/src/common/index.js b/extensions/markdown/js/src/common/index.js
index 6e3bbdf13f..94249a88d5 100644
--- a/extensions/markdown/js/src/common/index.js
+++ b/extensions/markdown/js/src/common/index.js
@@ -9,7 +9,6 @@
import app from 'flarum/common/app';
import { extend, override } from 'flarum/common/extend';
-import TextEditor from 'flarum/common/components/TextEditor';
import BasicEditorDriver from 'flarum/common/utils/BasicEditorDriver';
import styleSelectedText from 'flarum/common/utils/styleSelectedText';
@@ -89,13 +88,9 @@ export function initialize(app) {
items.add('italic', makeShortcut('italic', 'i', this));
});
- if (TextEditor.prototype.markdownToolbarItems) {
- override(TextEditor.prototype, 'markdownToolbarItems', markdownToolbarItems);
- } else {
- TextEditor.prototype.markdownToolbarItems = markdownToolbarItems;
- }
+ override('flarum/common/components/TextEditor', 'markdownToolbarItems', markdownToolbarItems);
- extend(TextEditor.prototype, 'toolbarItems', function (items) {
+ extend('flarum/common/components/TextEditor', 'toolbarItems', function (items) {
items.add(
'markdown',
(shortcutHandler = handler)}>
diff --git a/extensions/markdown/js/tsconfig.json b/extensions/markdown/js/tsconfig.json
new file mode 100644
index 0000000000..519ed73b2d
--- /dev/null
+++ b/extensions/markdown/js/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ // Use Flarum's tsconfig as a starting point
+ "extends": "flarum-tsconfig",
+ // This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder
+ // and also tells your Typescript server to read core's global typings for
+ // access to `dayjs` and `$` in the global namespace.
+ "include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"],
+ "compilerOptions": {
+ // This will output typings to `dist-typings`
+ "declarationDir": "./dist-typings",
+ "paths": {
+ "flarum/*": ["../../../framework/core/js/dist-typings/*"]
+ }
+ }
+}
diff --git a/extensions/mentions/js/src/forum/addComposerAutocomplete.js b/extensions/mentions/js/src/forum/addComposerAutocomplete.js
index a4f02e20e2..5212dd5fc0 100644
--- a/extensions/mentions/js/src/forum/addComposerAutocomplete.js
+++ b/extensions/mentions/js/src/forum/addComposerAutocomplete.js
@@ -1,6 +1,5 @@
import app from 'flarum/forum/app';
import { extend } from 'flarum/common/extend';
-import TextEditor from 'flarum/common/components/TextEditor';
import TextEditorButton from 'flarum/common/components/TextEditorButton';
import KeyboardNavigatable from 'flarum/common/utils/KeyboardNavigatable';
@@ -11,7 +10,7 @@ export default function addComposerAutocomplete() {
const $container = $('');
const dropdown = new AutocompleteDropdown();
- extend(TextEditor.prototype, 'oncreate', function () {
+ extend('flarum/common/components/TextEditor', 'onbuild', function () {
const $editor = this.$('.TextEditor-editor').wrap('');
this.navigator = new KeyboardNavigatable();
@@ -26,7 +25,7 @@ export default function addComposerAutocomplete() {
$editor.after($container);
});
- extend(TextEditor.prototype, 'buildEditorParams', function (params) {
+ extend('flarum/common/components/TextEditor', 'buildEditorParams', function (params) {
let relMentionStart;
let absMentionStart;
let matchTyped;
@@ -128,7 +127,7 @@ export default function addComposerAutocomplete() {
params.inputListeners.push(suggestionsInputListener);
});
- extend(TextEditor.prototype, 'toolbarItems', function (items) {
+ extend('flarum/common/components/TextEditor', 'toolbarItems', function (items) {
items.add(
'mention',
this.attrs.composer.editor.insertAtCursor(' @')} icon="fas fa-at">
diff --git a/extensions/mentions/js/src/forum/index.js b/extensions/mentions/js/src/forum/index.js
index 3022293c87..a8797b006e 100644
--- a/extensions/mentions/js/src/forum/index.js
+++ b/extensions/mentions/js/src/forum/index.js
@@ -1,6 +1,5 @@
import { extend } from 'flarum/common/extend';
import app from 'flarum/forum/app';
-import NotificationGrid from 'flarum/forum/components/NotificationGrid';
import { getPlainContent } from 'flarum/common/utils/string';
import textContrastClass from 'flarum/common/helpers/textContrastClass';
import Post from 'flarum/forum/components/Post';
@@ -46,7 +45,7 @@ app.initializers.add('flarum-mentions', function () {
app.notificationComponents.groupMentioned = GroupMentionedNotification;
// Add notification preferences.
- extend(NotificationGrid.prototype, 'notificationTypes', function (items) {
+ extend('flarum/forum/components/NotificationGrid', 'notificationTypes', function (items) {
items.add('postMentioned', {
name: 'postMentioned',
icon: 'fas fa-reply',
diff --git a/extensions/mentions/js/src/forum/mentionables/PostMention.tsx b/extensions/mentions/js/src/forum/mentionables/PostMention.tsx
index 172fa8f46b..e32c07789a 100644
--- a/extensions/mentions/js/src/forum/mentionables/PostMention.tsx
+++ b/extensions/mentions/js/src/forum/mentionables/PostMention.tsx
@@ -6,8 +6,6 @@ import usernameHelper from 'flarum/common/helpers/username';
import avatar from 'flarum/common/helpers/avatar';
import highlight from 'flarum/common/helpers/highlight';
import { truncate } from 'flarum/common/utils/string';
-import ReplyComposer from 'flarum/forum/components/ReplyComposer';
-import EditPostComposer from 'flarum/forum/components/EditPostComposer';
import getCleanDisplayName from '../utils/getCleanDisplayName';
import type AtMentionFormat from './formats/AtMentionFormat';
@@ -23,7 +21,10 @@ export default class PostMention extends MentionableModel
* match any username characters that have been typed.
*/
initialResults(): Post[] {
- if (!app.composer.bodyMatches(ReplyComposer) && !app.composer.bodyMatches(EditPostComposer)) {
+ const EditPostComposer = flarum.reg.checkModule('core', 'forum/components/EditPostComposer');
+ const ReplyComposer = flarum.reg.checkModule('core', 'forum/components/ReplyComposer');
+
+ if ((!ReplyComposer || !app.composer.bodyMatches(ReplyComposer)) && (!EditPostComposer || !app.composer.bodyMatches(EditPostComposer))) {
return [];
}
diff --git a/extensions/mentions/js/src/forum/utils/reply.js b/extensions/mentions/js/src/forum/utils/reply.js
index 5a2961e77b..816ed83ef6 100644
--- a/extensions/mentions/js/src/forum/utils/reply.js
+++ b/extensions/mentions/js/src/forum/utils/reply.js
@@ -1,6 +1,5 @@
import app from 'flarum/forum/app';
import DiscussionControls from 'flarum/forum/utils/DiscussionControls';
-import EditPostComposer from 'flarum/forum/components/EditPostComposer';
export function insertMention(post, composer, quote) {
return new Promise((resolve) => {
@@ -27,7 +26,9 @@ export function insertMention(post, composer, quote) {
}
export default function reply(post, quote) {
- if (app.composer.bodyMatches(EditPostComposer) && app.composer.body.attrs.post.discussion() === post.discussion()) {
+ const EditPostComposer = flarum.reg.checkModule('core', 'forum/components/EditPostComposer');
+
+ if (EditPostComposer && app.composer.bodyMatches(EditPostComposer) && app.composer.body.attrs.post.discussion() === post.discussion()) {
// If we're already editing a post in the discussion of post we're quoting,
// insert the mention directly.
return insertMention(post, app.composer, quote);
diff --git a/extensions/nicknames/js/src/forum/index.js b/extensions/nicknames/js/src/forum/index.js
index 8c353494cc..aea6faed88 100644
--- a/extensions/nicknames/js/src/forum/index.js
+++ b/extensions/nicknames/js/src/forum/index.js
@@ -1,9 +1,6 @@
import app from 'flarum/forum/app';
import { extend } from 'flarum/common/extend';
import Button from 'flarum/common/components/Button';
-import EditUserModal from 'flarum/common/components/EditUserModal';
-import SignUpModal from 'flarum/forum/components/SignUpModal';
-import SettingsPage from 'flarum/forum/components/SettingsPage';
import extractText from 'flarum/common/utils/extractText';
import Stream from 'flarum/common/utils/Stream';
import NickNameModal from './components/NicknameModal';
@@ -11,7 +8,7 @@ import NickNameModal from './components/NicknameModal';
export { default as extend } from './extend';
app.initializers.add('flarum/nicknames', () => {
- extend(SettingsPage.prototype, 'accountItems', function (items) {
+ extend('flarum/forum/components/SettingsPage', 'accountItems', function (items) {
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
if (this.user.canEditNickname()) {
@@ -24,11 +21,11 @@ app.initializers.add('flarum/nicknames', () => {
}
});
- extend(EditUserModal.prototype, 'oninit', function () {
+ extend('flarum/common/components/EditUserModal', 'oninit', function () {
this.nickname = Stream(this.attrs.user.displayName());
});
- extend(EditUserModal.prototype, 'fields', function (items) {
+ extend('flarum/common/components/EditUserModal', 'fields', function (items) {
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
if (!this.attrs.user.canEditNickname()) return;
@@ -47,7 +44,7 @@ app.initializers.add('flarum/nicknames', () => {
);
});
- extend(EditUserModal.prototype, 'data', function (data) {
+ extend('flarum/common/components/EditUserModal', 'data', function (data) {
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
if (!this.attrs.user.canEditNickname()) return;
@@ -57,13 +54,13 @@ app.initializers.add('flarum/nicknames', () => {
}
});
- extend(SignUpModal.prototype, 'oninit', function () {
+ extend('flarum/forum/components/SignUpModal', 'oninit', function () {
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
this.nickname = Stream(this.attrs.username || '');
});
- extend(SignUpModal.prototype, 'onready', function () {
+ extend('flarum/forum/components/SignUpModal', 'onready', function () {
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
if (app.forum.attribute('setNicknameOnRegistration') && app.forum.attribute('randomizeUsernameOnRegistration')) {
@@ -71,7 +68,7 @@ app.initializers.add('flarum/nicknames', () => {
}
});
- extend(SignUpModal.prototype, 'fields', function (items) {
+ extend('flarum/forum/components/SignUpModal', 'fields', function (items) {
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
if (app.forum.attribute('setNicknameOnRegistration')) {
@@ -97,7 +94,7 @@ app.initializers.add('flarum/nicknames', () => {
}
});
- extend(SignUpModal.prototype, 'submitData', function (data) {
+ extend('flarum/forum/components/SignUpModal', 'submitData', function (data) {
if (app.forum.attribute('displayNameDriver') !== 'nickname') return;
if (app.forum.attribute('setNicknameOnRegistration')) {
diff --git a/extensions/subscriptions/js/src/forum/addSubscriptionSettings.tsx b/extensions/subscriptions/js/src/forum/addSubscriptionSettings.tsx
index 78aaf05155..3ad961dd84 100644
--- a/extensions/subscriptions/js/src/forum/addSubscriptionSettings.tsx
+++ b/extensions/subscriptions/js/src/forum/addSubscriptionSettings.tsx
@@ -1,10 +1,10 @@
import app from 'flarum/forum/app';
import { extend } from 'flarum/common/extend';
-import SettingsPage from 'flarum/forum/components/SettingsPage';
+import type SettingsPage from 'flarum/forum/components/SettingsPage';
import Switch from 'flarum/common/components/Switch';
export default function () {
- extend(SettingsPage.prototype, 'notificationsItems', function (this: SettingsPage, items) {
+ extend('flarum/forum/components/SettingsPage', 'notificationsItems', function (this: SettingsPage, items) {
items.add(
'followAfterReply',
js(__DIR__.'/js/dist/forum.js')
+ ->jsDirectory(__DIR__.'/js/dist/forum')
->css(__DIR__.'/less/forum.less')
->route('/t/{slug}', 'tag', Content\Tag::class)
->route('/tags', 'tags', Content\Tags::class),
+ (new Extend\Frontend('common'))
+ ->jsDirectory(__DIR__.'/js/dist/common'),
+
(new Extend\Frontend('admin'))
->js(__DIR__.'/js/dist/admin.js')
->css(__DIR__.'/less/admin.less'),
diff --git a/extensions/tags/js/src/admin/components/SelectTagsSettingComponent.tsx b/extensions/tags/js/src/admin/components/SelectTagsSettingComponent.tsx
index ead367b580..acf01fcd46 100644
--- a/extensions/tags/js/src/admin/components/SelectTagsSettingComponent.tsx
+++ b/extensions/tags/js/src/admin/components/SelectTagsSettingComponent.tsx
@@ -2,7 +2,6 @@ import app from 'flarum/admin/app';
import Component from 'flarum/common/Component';
import Button from 'flarum/common/components/Button';
import LoadingIndicator from 'flarum/common/components/LoadingIndicator';
-import TagSelectionModal from '../../common/components/TagSelectionModal';
import tagsLabel from '../../common/helpers/tagsLabel';
import type { CommonSettingsItemOptions } from 'flarum/admin/components/AdminPage';
@@ -46,7 +45,7 @@ export default class SelectTagsSettingComponent<