1
0
mirror of https://github.com/flarum/core.git synced 2025-08-13 20:04:24 +02:00

Compare commits

..

69 Commits

Author SHA1 Message Date
Franz Liedke
fc5eddb99d Default parameter value 2020-08-02 09:25:36 +02:00
Franz Liedke
bad8115a4a Remove obsolete properties in post stream state 2020-08-02 08:01:55 +02:00
Franz Liedke
1fc76acf06 Stop injecting post stream state into scrubber 2020-08-02 07:56:58 +02:00
Franz Liedke
527d93120a Shrink the diff, e.g. by moving methods around 2020-08-01 02:59:55 +02:00
Franz Liedke
53582ab999 WIP: Re-work stream, scrubber and state
Mostly, this tries to move common logic up to the DiscussionPage as the
lowest common ancestor of these components sharing certain state.

It's still messy, though. :-/
2020-08-01 02:47:36 +02:00
Franz Liedke
6f6a09d7c4 Start decoupling scrolling from state 2020-07-31 23:23:32 +02:00
Franz Liedke
e8394e4a1d Unify pausing 2020-07-31 16:42:42 +02:00
Franz Liedke
e455e6c431 Restore old implementation of goToLast()
It's not clear whether this was intentionally omitted.
2020-07-31 16:13:16 +02:00
Franz Liedke
a044c642f6 Add default parameter value
This is actually relied on already by not passing the parameter in other
methods.
2020-07-31 16:12:17 +02:00
Franz Liedke
01384139ef Encapsulate a bit more logic in the state 2020-07-31 15:42:01 +02:00
Franz Liedke
57f5ad4893 Move method to previous position 2020-07-31 13:27:26 +02:00
Franz Liedke
8b69b24272 Fix docblocks 2020-07-31 13:21:45 +02:00
Franz Liedke
09c722e522 Remove unused prop 2020-07-31 12:14:00 +02:00
Franz Liedke
3ce94757fc Rename props 2020-07-31 12:13:25 +02:00
Franz Liedke
aae6f24356 Fix docblock 2020-07-31 12:06:33 +02:00
Franz Liedke
1a2f9527fd Revert formatting changes 2020-07-31 11:32:54 +02:00
Alexander Skvortsov
8c362bf7c7 Don't save index twice in post stream post-load 2020-07-31 11:18:12 +02:00
Alexander Skvortsov
f99f79e3c0 De-propify visible 2020-07-31 11:18:12 +02:00
Alexander Skvortsov
bbd8136695 A bit more cleanup 2020-07-31 11:17:46 +02:00
Alexander Skvortsov
1d8662088f A bit more cleanup and bugfixes 2020-07-31 11:17:45 +02:00
Alexander Skvortsov
a850f4a6fb Restore old scrubber index calculation system 2020-07-31 11:17:45 +02:00
Alexander Skvortsov
af55a13c61 A bit more cleanup, UI bugfixes 2020-07-31 11:17:45 +02:00
Alexander Skvortsov
92b62e7ab6 Minor cleanup of PostStreamState methods 2020-07-31 11:17:44 +02:00
Alexander Skvortsov
5ef4de75d1 Fix date not showing up properly 2020-07-31 11:17:44 +02:00
Alexander Skvortsov
88e6be9d0e When scrolling to first post, scroll all the way to top, simplify scrollToItem promise structure 2020-07-31 11:17:44 +02:00
Alexander Skvortsov
228c7b883d move index calculation back out of show 2020-07-31 11:17:44 +02:00
Alexander Skvortsov
cdcf64852e Restore scrubber behavior 2020-07-31 11:17:43 +02:00
Alexander Skvortsov
d20650fb42 Use date of the post in index 2020-07-31 11:17:43 +02:00
Alexander Skvortsov
875a1f70c1 Fix date, index calculation on reload 2020-07-31 11:17:42 +02:00
Alexander Skvortsov
ef206495cd Try calculating index before redraw to avoid calling redraw immediately after scroll 2020-07-31 11:17:42 +02:00
Alexander Skvortsov
2360745237 Fix jumping around on page reload 2020-07-31 11:17:42 +02:00
Alexander Skvortsov
cc10eaadd2 Get rid of separate system for scrollToLast 2020-07-31 11:17:42 +02:00
Alexander Skvortsov
c98c0b027f Fix missing method call 2020-07-31 11:17:41 +02:00
Alexander Skvortsov
73507f403a Don't use anchorScroll on goToNumber, instead scrolling directly to item 2020-07-31 11:17:41 +02:00
Alexander Skvortsov
d3fb5ee77c Handle scroll to end as a special case of scroll to index to ensure that we get completely to the bottom and flash the bottom element 2020-07-31 11:17:41 +02:00
Alexander Skvortsov
479e5a8cf6 in goToNumber, only redraw when the response has been returned. 2020-07-31 11:17:40 +02:00
Alexander Skvortsov
4bce030115 Use same logic as in updateScrubber to calculate current post number 2020-07-31 11:17:40 +02:00
Alexander Skvortsov
9f2540dbe3 Properly bind loadNext button to the state 2020-07-31 11:17:40 +02:00
Alexander Skvortsov
aa15db6f44 Ensure consistent index in scrubber, rework current post index calculation logic. 2020-07-31 11:17:39 +02:00
Alexander Skvortsov
0c63be527b Pass in a selector string to anchorScroll instead of a DOM element. Because the DOM element gets destroyed on redraw, it's offset height is interpreted as 0 which throws off our position in the stream. 2020-07-31 11:17:39 +02:00
Alexander Skvortsov
9db2f78939 Incorporate math floor in sanitizeIndex, use that for scrubber index display. 2020-07-31 11:17:39 +02:00
Alexander Skvortsov
9572863648 Add anchorScroll with redraw after loadPromise loads in scrollToItem 2020-07-31 11:17:39 +02:00
Alexander Skvortsov
ac1eef7578 Remove unused anchorScroll import 2020-07-31 11:17:38 +02:00
Alexander Skvortsov
514165c3af Anchor scroll after loading posts 2020-07-31 11:17:38 +02:00
Alexander Skvortsov
e84960dcd1 Cleanup 2020-07-31 11:17:38 +02:00
Alexander Skvortsov
f8d1c7a317 Add redraws after posts have been loaded from the API 2020-07-31 11:17:37 +02:00
Alexander Skvortsov
ba82969a58 Remove unnecessary redraw 2020-07-31 11:17:37 +02:00
Alexander Skvortsov
b2917c8716 Add more console logs 2020-07-31 11:17:12 +02:00
Alexander Skvortsov
c150c097c1 Add some more debugging flags 2020-07-31 11:17:11 +02:00
Alexander Skvortsov
beab8ce39c Update scrubber after scrollToItem 2020-07-31 11:17:11 +02:00
Alexander Skvortsov
1360723c3f Separate updateScrubber into separate method from onscroll 2020-07-31 11:17:11 +02:00
Alexander Skvortsov
5cdfeaf9a5 Move scrollPromise log into scrollToItem 2020-07-31 11:17:10 +02:00
Alexander Skvortsov
6e1d385268 Code cleanup, added a bunch of debug console logging 2020-07-31 11:17:10 +02:00
Alexander Skvortsov
193f3b040d Slightly improve scrubber label accuracy on click 2020-07-31 11:17:10 +02:00
Alexander Skvortsov
74cb4f9007 Get rid of post stream events. Initial load is still buggy 2020-07-31 11:17:09 +02:00
Alexander Skvortsov
eb24e628fa Get rid of js-PostStream 2020-07-31 11:17:09 +02:00
Alexander Skvortsov
c03feceb9f Fix goToLast 2020-07-31 11:17:09 +02:00
Alexander Skvortsov
51008bc65d Use scrollToIndex to contain scrollToLast 2020-07-31 11:17:09 +02:00
Alexander Skvortsov
9a357f5d19 Add scrubber height change transition css, don't apply when dragging 2020-07-31 11:17:08 +02:00
Alexander Skvortsov
9c63c54868 Simplify paused logic 2020-07-31 11:17:08 +02:00
Alexander Skvortsov
5427b35c6d Large simplifications of PostStreamScrubber 2020-07-31 11:17:08 +02:00
Franz Liedke
2ec49db6df Pass discussion as prop to stream components
- Law of demeter (no need to access discussion through the state)
- Less public API surface of the state object
2020-07-31 11:17:07 +02:00
Franz Liedke
062dc8f57f Don't call protected method outside of state
In addition, this again avoids writing a state property from
outside the state class.

I am not 100% sure whether this extra sanitization is necessary,
but it seems to be the only place where it is not applied when
changing the value of `visibleEnd` (and not safeguarded otherwise),
so I erred on the safe side.
2020-07-31 11:17:07 +02:00
Franz Liedke
8a9e50d192 Encapsulate viewingEnd() in state
...instead of calculating this derived value outside the state class.
2020-07-31 11:17:07 +02:00
Franz Liedke
6c087da65f Remove obsolete event handler
The event is not triggered anymore.
This is now handled through the `positionHandler` prop.
2020-07-31 11:17:06 +02:00
Franz Liedke
6bcecd623b Revert inlining method, rename the method instead 2020-07-31 11:17:06 +02:00
Alexander Skvortsov
614bb0d71e Moved refresh method of discussionpage into init, as its not used externally (and using it would be bad practice), fixing up PostStream 2020-07-31 11:17:06 +02:00
Alexander Skvortsov
cff9b327a9 Remove event from PostState, pass handler in via props, 2020-07-31 11:17:06 +02:00
Alexander Skvortsov
7af8e35a6e Extract PostStream state 2020-07-31 11:17:03 +02:00
946 changed files with 14217 additions and 45718 deletions

View File

@@ -15,5 +15,5 @@ indent_size = 2
[*.{diff,md}]
trim_trailing_whitespace = false
[*.{php,xml,json}]
[*.{php,xml}]
indent_size = 4

4
.gitattributes vendored
View File

@@ -11,7 +11,3 @@ phpunit.xml export-ignore
tests export-ignore
js/dist/* -diff
js/dist/* linguist-generated
js/dist-typings/* linguist-generated
* text=auto eol=lf

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
github: flarum
open_collective: flarum
tidelift: packagist/flarum/core

24
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,24 @@
<!--
IMPORTANT: We applaud pull requests, they excite us every single time. As we have an obligation to maintain a healthy code standard and quality, we take sufficient time for reviews. Please do create a separate pull request per change/issue/feature; we will ask you to split bundled pull requests.
-->
**Fixes #0000**
**Changes proposed in this pull request:**
<!-- fill this out, mention the pages and/or components which have been impacted -->
**Reviewers should focus on:**
<!-- fill this out, ask for feedback on specific changes you are unsure about -->
**Screenshot**
<!-- include an image of the most relevant user-facing change, if any -->
**Confirmed**
- [ ] Frontend changes: tested on a local Flarum installation.
- [ ] Backend changes: tests are green (run `composer test`).
**Required changes:**
- [ ] Related documentation PR: (Remove if irrelevant)
- [ ] Related core extension PRs: (Remove if irrelevant)

13
.github/SECURITY.md vendored Normal file
View File

@@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
During the beta phase, we will only patch security vulnerabilities in the latest beta release.
## Reporting a Vulnerability
If you discover a security vulnerability within Flarum, please send an email to security@flarum.org so we can address it promptly.
We will get back to you as time allows.
Discussions may commence internally, so you may not hear back immediately.
When reporting a vulnerability, please provide your GitHub username (if available), so that we can invite you to collaborate on a [security advisory on GitHub](https://help.github.com/en/articles/about-maintainer-security-advisories).

16
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,16 @@
name: JavaScript
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: flarum/action-build@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,76 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
# Run on:
# - pushes to master, or
# - PRs with a base of `master`
# - which do not **only** consist of changes to .md or .less files
on:
push:
branches: [ master ]
paths-ignore:
- '**/*.md'
- '**/*.less'
pull_request:
branches: [ master ]
paths-ignore:
- '**/*.md'
- '**/*.less'
schedule:
- cron: '0 0 * * 1,3,5'
jobs:
analyze:
name: Analyze / ${{ matrix.language }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

View File

@@ -1,91 +0,0 @@
name: JS
on: [workflow_dispatch, push, pull_request]
env:
NODE_VERSION: 16
jobs:
prettier:
name: Prettier
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
cache-dependency-path: js/package-lock.json
- name: Install JS dependencies
run: npm ci
working-directory: ./js
- name: Check JS formatting
run: npm run format-check
working-directory: ./js
build-prod:
name: Build and commit
runs-on: ubuntu-latest
needs: [prettier]
# Only commit JS on push to master branch
# Remember to change in `build-test` job too
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
cache-dependency-path: js/package-lock.json
# Our action will install npm, cd into `./js`, run `npm run build` and
# `npm run build-typings`, then commit and upload any changes
- name: Build production JS
uses: flarum/action-build@2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
build_script: build
package_manager: npm
typings_script: build-typings
build-test:
name: Test build
runs-on: ubuntu-latest
needs: [prettier]
# Inverse check of `build-prod`
# Remember to change in `build-prod` job too
if: github.ref != 'refs/heads/master' || github.event_name != 'push'
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
cache: "npm"
cache-dependency-path: js/package-lock.json
# Our action will install npm, cd into `./js`, run `npm run build` and
# `npm run build-typings`, then commit and upload any changes
- name: Build production JS
uses: flarum/action-build@2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
build_script: build
package_manager: npm
typings_script: build-typings
do_not_commit: true

31
.github/workflows/lint.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: Lint
on:
push:
paths:
- 'js/src/**'
pull_request:
paths:
- 'js/src/**'
jobs:
prettier:
runs-on: ubuntu-latest
name: JS / Prettier
steps:
- uses: actions/checkout@master
- name: Setup Node.js
uses: actions/setup-node@v1
with:
node-version: "12"
- name: Install JS dependencies
run: npm ci
working-directory: ./js
- name: Check JS code for formatting
run: node_modules/.bin/prettier --check src
working-directory: ./js

View File

@@ -1,45 +0,0 @@
name: Bundle size checker
on:
workflow_dispatch:
push:
paths:
- "js/**"
pull_request:
paths:
- "js/**"
jobs:
bundlewatch:
runs-on: ubuntu-latest
name: Bundlewatch
steps:
- name: Check out code
uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: "14"
- name: Use npm v7
run: sudo npm install -g npm@7.x.x
- name: Install JS dependencies
# We need to use `npm install` here. If we don't, the workflow will fail.
run: npm install
working-directory: ./js
- name: Build production assets
run: npm run build
working-directory: ./js
- name: Check bundle size change
run: node_modules/.bin/bundlewatch --config .bundlewatch.config.json
working-directory: ./js
env:
BUNDLEWATCH_GITHUB_TOKEN: ${{ secrets.BUNDLEWATCH_GITHUB_TOKEN }}
CI_COMMIT_SHA: ${{ github.event.pull_request.head.sha }}

View File

@@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
php: [7.3, 7.4, '8.0']
php: [7.2, 7.3, 7.4]
service: ['mysql:5.7', mariadb]
prefix: ['', flarum_]
@@ -21,16 +21,16 @@ jobs:
prefixStr: (prefix)
exclude:
- php: 7.3
- php: 7.2
service: 'mysql:5.7'
prefix: flarum_
- php: 7.3
- php: 7.2
service: mariadb
prefix: flarum_
- php: 8.0
- php: 7.3
service: 'mysql:5.7'
prefix: flarum_
- php: 8.0
- php: 7.3
service: mariadb
prefix: flarum_
@@ -43,25 +43,15 @@ jobs:
name: 'PHP ${{ matrix.php }} / ${{ matrix.db }} ${{ matrix.prefixStr }}'
steps:
- name: Check out code
uses: actions/checkout@v2
- uses: actions/checkout@master
- name: Setup PHP
uses: shivammathur/setup-php@0b9d33cd0782337377999751fc10ea079fdd7104 # pin@v2
with:
php-version: ${{ matrix.php }}
coverage: xdebug
extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
tools: phpunit, composer:v2
- name: Select PHP version
run: sudo update-alternatives --set php $(which php${{ matrix.php }})
# The authentication alter is necessary because newer mysql versions use the `caching_sha2_password` driver,
# which isn't supported prior to PHP7.4
# When we drop support for PHP7.3, we should remove this from the setup.
- name: Create MySQL Database
run: |
sudo systemctl start mysql
mysql -uroot -proot -e 'CREATE DATABASE flarum_test;' --port 13306
mysql -uroot -proot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root';" --port 13306
- name: Install Composer dependencies
run: composer install
@@ -75,5 +65,3 @@ jobs:
- name: Run Composer tests
run: composer test
env:
COMPOSER_PROCESS_TIMEOUT: 600

2
.gitignore vendored
View File

@@ -4,8 +4,6 @@ composer.phar
node_modules
.DS_Store
Thumbs.db
tests/.phpunit.result.cache
/tests/integration/tmp
.vagrant
.idea/*
.vscode

View File

@@ -12,3 +12,7 @@ disabled:
- phpdoc_order
- phpdoc_separation
- phpdoc_types
finder:
exclude:
- "stubs"

View File

@@ -1,412 +1,5 @@
# Changelog
## [1.1.0](https://github.com/flarum/core/compare/v1.0.4...v1.1.0)
### Added
- Info command now displays MySQL version, queue driver, mail driver (https://github.com/flarum/core/pull/2991)
- Use organization Prettier config (https://github.com/flarum/core/pull/2967)
- Support for global typings in extensions (https://github.com/flarum/core/pull/2992)
- Typings for class component state attribute (https://github.com/flarum/core/pull/2995)
- Custom colorising with CSS custom properties (https://github.com/flarum/core/pull/3001)
- Theme Extender to allow overriding LESS files (https://github.com/flarum/core/pull/3008)
- Update lastSeenAt when authenticating via API (https://github.com/flarum/core/pull/3058)
- NoJs Admin View (https://github.com/flarum/core/pull/3059)
- Preload FontAwesome, JS and CSS, and add `preload` extender (https://github.com/flarum/core/pull/3057)
### Changed
- Move Day.js plugin types import to global typings (https://github.com/flarum/core/pull/2954)
- Avoid resolving excluded middleware on each middleware items
- Allow extra attrs provided to `<Select>` to be passed through to the DOM element (https://github.com/flarum/core/pull/2959)
- Limit height of code blocks (https://github.com/flarum/core/pull/3012)
- Update normalize.css from v3.0.2 to v8.0.1 (https://github.com/flarum/core/pull/3015)
- Permission Grid: stick the headers to handle a lot of tags (https://github.com/flarum/core/pull/2887)
- Use `ItemList` for `DiscussionPage` content (https://github.com/flarum/core/pull/3004)
- Move email confirmation to POST request (https://github.com/flarum/core/pull/3038)
- Minor CSS code cleanup (https://github.com/flarum/core/pull/3026)
- Replace username with display name in more places (https://github.com/flarum/core/pull/3040)
- Rewrite Button to Typescript (https://github.com/flarum/core/pull/2984)
- Rewrite AdminPage abstract component into Typescript (https://github.com/flarum/core/pull/2996)
- Allow adding page parameters to PaginatedListState (https://github.com/flarum/core/pull/2935)
- Pass filter params to getApiDocument (https://github.com/flarum/core/pull/3037)
- Use author filter instead of gambit to get a user's discussions (https://github.com/flarum/core/pull/3068)
- [A11Y] Accessibility improvements for the Search component (https://github.com/flarum/core/pull/3017)
- Add determinsm to extension order resolution (https://github.com/flarum/core/pull/3076)
- Add cache control headers to the admin area (https://github.com/flarum/core/pull/3097)
### Fixed
- HLJS 11 new styles resulting in double padding (https://github.com/flarum/core/pull/2909)
- Internal API client attempting to load an uninstantiated session
- Empty post footer taking visual space (https://github.com/flarum/core/pull/2926)
- Unrecognized component class custom attribute typings (https://github.com/flarum/core/pull/2962)
- User edit groups permission not visually depending on view hidden groups permission (https://github.com/flarum/core/pull/2880)
- Event post excerpt preview triggers error (https://github.com/flarum/core/pull/2964)
- Missing settings defaults for display name driver and User slug driver (https://github.com/flarum/core/pull/2971)
- [A11Y] Icons not hidden from screenreaders (https://github.com/flarum/core/pull/3027)
- [A11Y] Checkboxes not focusable (https://github.com/flarum/core/pull/3014)
- Uploading ICO favicons resulting in server errors (https://github.com/flarum/core/pull/2949)
- Missing proper validation for large avatar upload payload (https://github.com/flarum/core/pull/3042)
- [A11Y] Missing focus rings in control elements (https://github.com/flarum/core/pull/3016)
- Unsanitised integer query parameters (https://github.com/flarum/core/pull/3064)
###### Code Contributors
@lhsazevedo, @Ornanovitch, @pierres, @the-turk, @iPurpl3x
###### Issue Reporters
@uamv, @dannyuk1982, @BurnNoticeSpy, @haarp, @peopleinside, @matteocontrini
## [1.0.4](https://github.com/flarum/core/compare/v1.0.3...v1.0.4)
### Fixed
- Upgrade to v1.0 resets the "view" permission on all tags (https://github.com/flarum/core/pull/2941)
## [1.0.3](https://github.com/flarum/core/compare/v1.0.2...v1.0.3)
### Changed
- Removed [forum] prefix from Request Password and Email Confirmation emails ([a4a81c0](https://github.com/flarum/core/commit/a4a81c0ec237476cd6e7ca00c1ed9465493af476))
- Adopt huntr.dev for handling our security vulnerability reports (https://github.com/flarum/core/pull/2918)
- Maintenance handler can now be replaced through the service container (ioc) ([4acff91](https://github.com/flarum/core/commit/4acff91f8063fcced9bf8c9a76fbb510d06823c0))
- The colors on the auto generated avatars are now based on the Display Name of the user (https://github.com/flarum/core/pull/2873)
### Fixed
- Avatar in notifications list are incorrectly aligned (https://github.com/flarum/core/pull/2906)
- FilesystemManager is not compatible with upstream Laravel implementation (https://github.com/flarum/core/pull/2936)
## [1.0.2](https://github.com/flarum/core/compare/v1.0.1...v1.0.2)
### Fixed
- Critical XSS vulnerability
## [1.0.1](https://github.com/flarum/core/compare/v1.0.0...v1.0.1)
### Fixed
- Installation fails on environments without proc_* functions enabled or mysql client binary (https://github.com/flarum/core/issues/2890)
## [1.0.0](https://github.com/flarum/core/compare/v0.1.0-beta.16...v1.0.0)
### Added
- Task scheduling
- `load()` method on `ApiController` extender to allow eager loading of relations (https://github.com/flarum/core/pull/2724)
- Installation supports enabling a set of extensions (https://github.com/flarum/core/pull/2757)
- RequestUtil helper class added to abstract the logic of the actor, session, locale and route name from the request (https://github.com/flarum/core/pull/2449)
- Code scanning action with GitHub CodeQL (https://github.com/flarum/core/pull/2744)
- The Formatter extender now has an `unparse` method to allow extensions to hook into the unparsing of content (https://github.com/flarum/core/pull/2780)
- A Filesystem extender allows direct modification and addition of filesystem disks (https://github.com/flarum/core/pull/2732)
- A slug driver based on the User ID was introduced (https://github.com/flarum/core/pull/2787)
- An extensible users list was added to the admin area (https://github.com/flarum/core/pull/2626)
- Headers hardened by adding Referer Policy, Xss Protection and Content type (https://github.com/flarum/core/pull/2721)
- Tooltip component (https://github.com/flarum/core/pull/2843)
- Moved `insertText` and `styleSelectedText` from markdown to core (https://github.com/flarum/core/pull/2826)
- A squashed database schema install dump to speed up new installs (https://github.com/flarum/core/pull/2842)
- Pagination in the canonical URL for discussion pages (https://github.com/flarum/core/pull/2853)
- PaginatedListState for the DiscussionList and to support paginated lists in the frontend (https://github.com/flarum/core/pull/2781)
- Introduce the new webpack config and flarum-tsconfig for typehinting (https://github.com/flarum/core/pull/2856)
### Changed
- Now tracking bundle sizes to keep an eye on web performance (https://github.com/flarum/core/pull/2695)
- Eager load relations on ListPostsController to improve performance (https://github.com/flarum/core/pull/2717)
- Replace classList with clsx library (https://github.com/flarum/core/pull/2760)
- Replaced the javascript based loading spinner with a pure CSS version (https://github.com/flarum/core/pull/2764)
- Route names now have to be unique (https://github.com/flarum/core/pull/2771)
- ActorReference is now available from the error handler middleware (https://github.com/flarum/core/pull/2410)
- The `migrations` table now has an Auto Increment ID (https://github.com/flarum/core/pull/2794)
- Assets and avatars are now managed using Laravel filesystem disks (https://github.com/flarum/core/pull/2729)
- Extracted asset publishing (`php flarum assets:publish`) from migrating (https://github.com/flarum/core/pull/2731)
- Assets were compiled in the format `<asset>-<revision>.<js|css>`, this is now `<asset>.<js|css>?v=<revision>` (https://github.com/flarum/core/pull/2805)
- The powered by header can now be configured in the config under `headers` (https://github.com/flarum/core/pull/2777)
- Switched to the ICU format for translation files (https://github.com/flarum/core/pull/2759)
- Allow extend and override to apply to multiple methods in one call
- Notifications dropdown and list refactored (https://github.com/flarum/core/pull/2822)
- Updated validation locale strings based on Laravel 8 changes (https://github.com/flarum/core/pull/2829)
- Caching of permissions is now taken care of centrally, reducing code duplication (https://github.com/flarum/core/pull/2832)
- Replaced lodash-es by throttle-debounce to reduce bundle size (https://github.com/flarum/core/pull/2827)
- Internal API requests are now executed through middleware (https://github.com/flarum/core/pull/2783)
- Permission changes: `viewDiscussions` to `viewForum` and `viewUserList` to `searchUsers` (https://github.com/flarum/core/pull/2854)
### Fixes
- Javascript is shown when editing the title of a discussion (https://github.com/flarum/core/pull/2693)
- Canonical url logic uses request object which causes wrong URL's when a different page is default (https://github.com/flarum/core/pull/2674)
- Dropdown toggle has no aria label (https://github.com/flarum/core/pull/2668)
- Nav drawer is focusable when off-screen on small viewports (https://github.com/flarum/core/pull/2666)
- Search input has no aria-label and no role (https://github.com/flarum/core/pull/2669)
- Code duplication exists between SendConfirmationEmailController and AccountActivationMailer (https://github.com/flarum/core/pull/2493)
- When setting tags as homepage default, visiting a tag will show all posts (https://github.com/flarum/core/pull/2754)
- Locale cache is cleared twice when cache clearing (https://github.com/flarum/core/pull/2738)
- When cache clearing fails an exception can be thrown due to a partial flush (https://github.com/flarum/core/pull/2756)
- Database migrations rely on MyISAM even though the eventual migrated database does not use it (https://github.com/flarum/core/pull/2442)
- Discussion search result is not sorted by relevance by default (https://github.com/flarum/core/pull/2773)
- Extensions cannot register custom searcher classes (https://github.com/flarum/core/pull/2755)
- Searching discussion titles is not possible (https://github.com/flarum/core/pull/2698)
- Boot errors due to failing extenders throw a generic error (https://github.com/flarum/core/pull/2740)
- Required argument to `Component.$()` isn't really required (https://github.com/flarum/core/pull/2844)
- Component does not allows use of all mithril lifecycle functionality (https://github.com/flarum/core/pull/2847)
### Removed
- The `make:migration` command has been removed (https://github.com/flarum/core/pull/2686)
- Background fade on the header has been removed (https://github.com/flarum/core/pull/2685)
- Remove vendor prefixes in less (https://github.com/flarum/core/pull/2766)
- The session is no longer available from the User class (https://github.com/flarum/core/pull/2790)
- The `mail` key is removed from the laravel related config (https://github.com/flarum/core/pull/2796)
## [0.1.0-beta.16](https://github.com/flarum/core/compare/v0.1.0-beta.15...v0.1.0-beta.16)
### Added
- Allow event subscribers (https://github.com/flarum/core/pull/2535)
- Allow Settings extender to have a default value (https://github.com/flarum/core/pull/2495)
- Allow hooking into the sending of notifications before being send (https://github.com/flarum/core/pull/2533)
- PHP 8 support (https://github.com/flarum/core/pull/2507)
- Search extender (https://github.com/flarum/core/pull/2483)
- User badges to post preview (https://github.com/flarum/core/pull/2555)
- Optional extension dependencies allow a booting order (https://github.com/flarum/core/pull/2579)
- Auth extender (https://github.com/flarum/core/pull/2176)
- `X-Powered-By` header added to allow indexers easier data aggregation of Flarum adoption (https://github.com/flarum/core/pull/2618)
### Changed
- Run integration tests in transaction (https://github.com/flarum/core/pull/2304)
- Allow policies to return a boolean for simplified allow/deny (https://github.com/flarum/core/pull/2534)
- Converted highlight helper to typescript (https://github.com/flarum/core/pull/2532)
- Add accessibility attributes to Mark as Read button (https://github.com/flarum/core/pull/2564)
- Dismiss errors on change email modal upon a new request ([00913d5](https://github.com/flarum/core/commit/00913d5b0be2172cfce1f16aaf64a24f3d2e6d4b))
- Disabled extensions now are marked with a red circle instead of a red dot (https://github.com/flarum/core/pull/2562)
- Extension dependency errors now show the extension title instead of the ID (https://github.com/flarum/core/pull/2563)
- Change `mutate` method on ApiSerializer extender to `attributes` (https://github.com/flarum/core/pull/2578)
- Moved locale files to the core from the language pack (https://github.com/flarum/core/pull/2408)
- AdminPage extensibility and generic improvements (https://github.com/flarum/core/pull/2593)
- Remove entry of authors, link to https://flarum.org/team (https://github.com/flarum/core/pull/2625)
- Search and filtering are split (https://github.com/flarum/core/pull/2454)
- Move IP identification into a middleware (https://github.com/flarum/core/pull/2624)
- Editor Driver abstraction introduced (https://github.com/flarum/core/pull/2594)
- Allow overriding routes (https://github.com/flarum/core/pull/2577)
- Split user edit permissions into permissions for editing of user credentials, username, groups and suspending (https://github.com/flarum/core/pull/2620)
- Reduced number of admin extension categories (https://github.com/flarum/core/pull/2604)
- Move search related classes to a dedicated Query namespace (https://github.com/flarum/core/pull/2645)
- Rewrite common helpers into typescript (https://github.com/flarum/core/pull/2541)
- `TextEditor` is moved to the common namespace for use in the admin frontend (https://github.com/flarum/core/pull/2649)
- Update Laravel/Illuminate components to 8 (https://github.com/flarum/core/pull/2576)
- Eager load relations in discussion listing to improve performance (https://github.com/flarum/core/pull/2639)
- Adopt flarum/testing package (https://github.com/flarum/core/pull/2545)
- Replace `user` gambit with `author` gambit ([612a57c](https://github.com/flarum/core/commit/612a57c4664415a3ea120103483645c32acc6f12))
- Posts page of on user profile loads posts using username instead of id ([30017ee](https://github.com/flarum/core/commit/30017eef09ae9e78640c4e2cacd4909fffa8d775))
### Fixed
- Transform css breaks iOS scroll functionality (https://github.com/flarum/core/pull/2527)
- Composer header is hidden on mobile devices (https://github.com/flarum/core/pull/2279)
- Cannot delete a post or discussion of a deleted user (https://github.com/flarum/core/pull/2521)
- DiscussionListPane jumps around not keeping the scroll position (https://github.com/flarum/core/pull/2402)
- Infinite scroll on notifications dropdown broken (https://github.com/flarum/core/pull/2524)
- The show language selector switch remains toggled on ([9347b12](https://github.com/flarum/core/commit/9347b12b47bf4ab97ffb7ca92673604b237c1012))
- Model Visibility extender throws exception on extensions that aren't installed or enabled (https://github.com/flarum/core/pull/2580)
- Extensions are marked as enabled when enabling fails to unmet extension dependencies (https://github.com/flarum/core/pull/2558)
- Routes to admin extension pages without a valid ID break the admin page (https://github.com/flarum/core/pull/2584)
- Disabled fieldset use an incorrect CSS property `disallowed` (https://github.com/flarum/core/pull/2585)
- Scrolling to a post that is already loaded the Load More button shows and does not trigger (https://github.com/flarum/core/pull/2388)
- Opening discussions on some mobile devices require a double tap (https://github.com/flarum/core/pull/2607)
- iOS devices show erratic behavior in the post stream while updating (https://github.com/flarum/core/pull/2548)
- Small mobile screens partially hides the composer when the keyboard is open (https://github.com/flarum/core/pull/2631)
- Clearing cache does not clear the template cache in storage/views (https://github.com/flarum/core/pull/2648)
- Boot errors show critical information (https://github.com/flarum/core/pull/2633)
- List user endpoint discloses last online even if user choose against it (https://github.com/flarum/core/pull/2634)
- Group gambit disclosed hidden groups (https://github.com/flarum/core/pull/2657)
- Search results on small windows not fully visible (https://github.com/flarum/core/pull/2650)
- Composer goes off screen on Safari when starting to type (https://github.com/flarum/core/pull/2660)
- A search that has no results shows the search results dropdown ([b88a7cb](https://github.com/flarum/core/commit/b88a7cb33b56e318f11670e9e2d563aef94db039))
- The composer modal moves around when typing on Safari ([a64c398](https://github.com/flarum/core/commit/a64c39835aba43e831209609f4a9638ae589aa41))
### Removed
- Deprecated CSRF wildcard path match
- Deprecated policy and visibility scoping events
- Deprecated post types event
- Deprecated validation events
- Deprecated notification events
- Deprecated floodgate
- Deprecated user preferences event
- Deprecated formatting events
- Deprecated api events
- Deprecated bootstrap.php support
- PHP 7.2 support (https://github.com/flarum/core/pull/2507)
- Bidi attribute in the rendered HTML (https://github.com/flarum/core/pull/2602)
- `AccessToken::find`, use `AccessToken::findValid` instead (https://github.com/flarum/core/pull/2651)
### Deprecated
- `GetModelIsPrivate` event (https://github.com/flarum/core/pull/2587)
- `CheckingPassword` event (https://github.com/flarum/core/pull/2176)
- `event()` helper (https://github.com/flarum/core/pull/2608)
- `AccessToken::generate` argument `$lifetime` (https://github.com/flarum/core/pull/2651)
- `Rememberer::remember` argument `$token` should receive an instance of `RememberAccessToken` with `AccessToken` being deprecated (https://github.com/flarum/core/pull/2651)
- `Rememberer::rememberUser` (https://github.com/flarum/core/pull/2651)
- `SessionAuthenticator::logIn` argument `$userId`, should be replaced with `AccessToken` (https://github.com/flarum/core/pull/2651)
- `TextEditor` has been moved to `common` (https://github.com/flarum/core/pull/2649)
- `UserFilter` ([91e8b56](https://github.com/flarum/core/commit/91e8b569618957c86757ef89bac666e9102db5ae))
## [0.1.0-beta.15](https://github.com/flarum/core/compare/v0.1.0-beta.14.1...v0.1.0-beta.15)
### Added
- Slug drivers support (https://github.com/flarum/core/pull/2456).
- Notification type extender (https://github.com/flarum/core/pull/2424).
- Validation extender (https://github.com/flarum/core/pull/2102).
- Post extender (https://github.com/flarum/core/pull/2101).
- Notification channel extender (https://github.com/flarum/core/pull/2432).
- Service provider extender (https://github.com/flarum/core/pull/2437).
- API serializer extender (https://github.com/flarum/core/pull/2438).
- User preferences extender (https://github.com/flarum/core/pull/2463).
- Settings extender (https://github.com/flarum/core/pull/2452).
- ApiController extender (https://github.com/flarum/core/pull/2451).
- Model visibility extender (https://github.com/flarum/core/pull/2460).
- Policy extender (https://github.com/flarum/core/pull/2461).
### Changed
- Time helpers converted to Typescript (https://github.com/flarum/core/pull/2391).
- Improved the formatter extender (https://github.com/flarum/core/pull/2098).
- Improve wording on installer when facing file permission issues (https://github.com/flarum/core/pull/2435).
- Background color of checkbox toggles improved for better usability (https://github.com/flarum/core/pull/2443).
- Route resolving refactored (https://github.com/flarum/core/pull/2425).
- Administration panel UX refactored (https://github.com/flarum/core/pull/2409).
- Floodgate moved to middleware and extender added (https://github.com/flarum/core/pull/2170).
- DRY up image uploading logic (https://github.com/flarum/core/pull/2477).
- Process isolation on testing (https://github.com/flarum/core/commit/984f751c718c89501cc09857bc271efa2c7eea8c).
- Forum and admin javascript exports namespaced (https://github.com/flarum/core/pull/2488).
### Fixed
- Web updater does not take into account subfolder installations (https://github.com/flarum/core/pull/2426).
- Callables handling in extenders failed (https://github.com/flarum/core/pull/2423).
- Scrolling on mobile from PostSteam changes didn't work correctly (https://github.com/flarum/core/pull/2385).
- Side pane covers part of the discussion page due to `app.discussions` being empty (https://github.com/flarum/core/commit/102e76b084bf47fdfb4c73f95e1fbb322537f7aa).
- Change email modal keeps showing the previous error message even on success (https://github.com/flarum/core/pull/2467).
- Comment count not updated when discussions are deleted (https://github.com/flarum/core/pull/2472).
- `goToIndex` in PostStream does not trigger an xhr to retrieve new data (https://github.com/flarum/core/commit/09e2736cbcc267594b660beabbd001d9030f9880).
- On refresh the post number is reduced by one (https://github.com/flarum/core/pull/2476).
- Queue worker would instantiate a new Queue factory, not the bound one (https://github.com/flarum/core/pull/2481).
- Header accidentally has a border bottom (https://github.com/flarum/core/pull/2489).
- Namespace mentioned in docblock is incorrect (https://github.com/flarum/core/pull/2494).
- Scrolling inside longer discussions (especially Firefox) skips posts (https://github.com/flarum/core/commit/210a6b3e253d7917bd1eacd3ed8d2f95073ae99d).
- Uploading avatars that are jpg/jpeg fails with a validation error (https://github.com/flarum/core/pull/2497).
### Removed
- MomentJS alias (https://github.com/flarum/core/pull/2428).
- Deprecated user events `GetDisplayName` and `PrepareUserGroups` (https://github.com/flarum/core/pull/2428).
- AssertPermissionTrait (https://github.com/flarum/core/pull/2428).
- Path related helpers and methods in Application (https://github.com/flarum/core/pull/2428).
- Backward compatibility layers from the frontend rewrite (https://github.com/flarum/core/pull/2428).
### Deprecated
- `CheckingForFlooding` (https://github.com/flarum/core/commit/8e25bcb68f86cc992c46dfa70368419fe9f936ac).
## [0.1.0-beta.14.1](https://github.com/flarum/core/compare/v0.1.0-beta.14...v0.1.0-beta.14.1)
### Fixed
- SuperTextarea component is not exported.
- Symfony dependencies do not match those depended on by Laravel (https://github.com/flarum/core/pull/2407).
- Scripts from textformatter aren't executed (https://github.com/flarum/core/pull/2415)
- Sub path installations have no page title.
- Losing focus of Composer area when coming from fullscreen.
## [0.1.0-beta.14](https://github.com/flarum/core/compare/v0.1.0-beta.13...v0.1.0-beta.14)
### Added
- Check dependencies before enabling / disabling extensions (https://github.com/flarum/core/pull/2188)
- Set up temporary infrastructure for TypeScript in core (https://github.com/flarum/core/pull/2206)
- Better UI for request error modals (https://github.com/flarum/core/pull/1929)
- Display name extender, tests, frontend UI (https://github.com/flarum/core/pull/2174)
- Scroll to post or show alert when editing a post from another page (https://github.com/flarum/core/pull/2108)
- Feature to test email config by sending an email to the current user (https://github.com/flarum/core/pull/2023)
- Allow searching users by group ID using the group gambit (https://github.com/flarum/core/pull/2192)
- Use `liveHumanTimes` helper to update times without reload/rerender (https://github.com/flarum/core/pull/2208)
- View extender, tests (https://github.com/flarum/core/pull/2134)
- User extender to replace `PrepareUserGroups` (https://github.com/flarum/core/pull/2110)
- Increase extensibility of skeleton PHP (https://github.com/flarum/core/pull/2308, https://github.com/flarum/core/pull/2318)
- Pass a translator instance to `getEmailSubject` in `MailableInterface` (https://github.com/flarum/core/pull/2244)
- Force LF line endings on windows (https://github.com/flarum/core/pull/2321)
- Add a `Link` component for internal and external links (https://github.com/flarum/core/pull/2315)
- `ConfirmDocumentUnload` component
- Error handler middleware can now be manipulated by the middleware extender
### Changed
- Update to Mithril 2 (https://github.com/flarum/core/pull/2255)
- Stop storing component instances (https://github.com/flarum/core/issues/1821, https://github.com/flarum/core/issues/2144)
- Update to Laravel 6.x (https://github.com/flarum/core/issues/2055)
- `Flarum\Foundation\Application` no longer implements `Illuminate\Contracts\Foundation\Application` (#2142)
- `Flarum\Foundation\Application` no longer inherits `Illuminate\Container\Container` (#2142)
- `paths` have been split off from `Flarum\Foundation\Application` into `Flarum\Foundation\Paths`, which can be injected where needed (#2142)
- `Flarum\User\Gate` no longer implements `Illuminate\Contracts\Auth\Access\Gate` (https://github.com/flarum/core/pull/2181)
- Improve Group Gambit performance (https://github.com/flarum/core/pull/2192)
- Switch to `dayjs` from `momentjs` (https://github.com/flarum/core/pull/2219)
- Don't create a `bio` column in `users` for new installations (https://github.com/flarum/core/pull/2215)
- Start converting core JS to TypeScript (https://github.com/flarum/core/pull/2207)
- Make Carbon an explicit dependency (https://github.com/flarum/core/commit/3b39c212e0fef7522e7d541a9214ff3817138d5d)
- Use Symfony's translator interface instead of Laravel's (https://github.com/flarum/core/pull/2243)
- Use newer versions of fontawesome (https://github.com/flarum/core/pull/2274)
- Use URL generator instead of `app()->url()` where possible (https://github.com/flarum/core/pull/2302)
- Move config from `config.php` into an injectable helper class (https://github.com/flarum/core/pull/2271)
- Use reserved TLD for bogus and test urls (https://github.com/flarum/core/commit/6860b24b70bd04544dde90e537ce021a5fc5a689)
- Replace `m.stream` with `flarum/utils/Stream` (https://github.com/flarum/core/pull/2316)
- Replace `affixedSidebar` util with `AffixedSidebar` component
- Replace `m.withAttr` with `flarum/utils/withAttr`
- Scroll Listener is now passive, performance improvement (https://github.com/flarum/core/pull/2387)
### Fixed
- `generate:migration` command for extensions (https://github.com/flarum/core/commit/443949f7b9d7558dbc1e0994cb898cbac59bec87)
- Container config for `UninstalledSite` (https://github.com/flarum/core/commit/ecdce44d555dd36a365fd472b2916e677ef173cf)
- Tooltip glitch on page chang (https://github.com/flarum/core/issues/2118)
- Using multiple extenders in tests (https://github.com/flarum/core/commit/c4f4f218bf4b175a30880b807f9ccb1a37a25330)
- Header glitch when opening modals (https://github.com/flarum/core/pull/2131)
- Ensure `SameSite` is explicitly set for cookies (https://github.com/flarum/core/pull/2159)
- Ensure `Flarum\User\Event\AvatarChanged` event is properly dispatched (https://github.com/flarum/core/pull/2197)
- Show correct error message on wrong password when changing email (https://github.com/flarum/core/pull/2171)
- Discussion unreadCount could be higher than commentCount if posts deleted (https://github.com/flarum/core/pull/2195)
- Don't show page title on the default route (https://github.com/flarum/core/pull/2047)
- Add page title to `All Discussions` page when it isn't the default route (https://github.com/flarum/core/pull/2047)
- Accept `'0'` as `false` for `flarum/components/Checkbox` (https://github.com/flarum/core/pull/2210)
- Fix PostStreamScrubber background (https://github.com/flarum/core/pull/2222)
- Test port on BaseUrl tests (https://github.com/flarum/core/pull/2226)
- `UrlGenerator` can now generate urls with optional parameters (https://github.com/flarum/core/pull/2246)
- Allow `less` to be compiled independently of Flarum (https://github.com/flarum/core/pull/2252)
- Use correct number abbreviation (https://github.com/flarum/core/pull/2261)
- Ensure avatar html uses alt tags for accessibility (https://github.com/flarum/core/pull/2269)
- Escape regex when searching (https://github.com/flarum/core/pull/2273)
- Remove unneeded semicolons inserted during JS compilation (https://github.com/flarum/core/pull/2280)
- Don't require a username/password for SMTP (https://github.com/flarum/core/pull/2287)
- Allow uppercase entries for SMTP encryption validation (https://github.com/flarum/core/pull/2289)
- Ensure that the right number of posts is returned from list posts API (https://github.com/flarum/core/pull/2291)
- Fix a variety of PostStream bugs (https://github.com/flarum/core/pull/2160, https://github.com/flarum/core/pull/2160)
- Sliding discussion glitch on mobile (https://github.com/flarum/core/pull/2324)
- Sliding discussion button in wrong place (https://github.com/flarum/core/pull/2330, https://github.com/flarum/core/pull/2383)
- Sliding discussion glitch on mobile (https://github.com/flarum/core/pull/2381)
- Fix PostStream for posts with top margins, and scrubber position when scrolling below posts (https://github.com/flarum/core/pull/2369)
### Removed
- `Flarum\Event\AbstractConfigureRoutes` event class
- `Flarum\Event\ConfigureApiRoutes` event class
- `Flarum\Event\ConfigureForumRoutes` event class
- `Flarum\Console\Event\Configuring` event class
- `Flarum\Event\ConfigureModelDates` event class
- `Flarum\Event\ConfigureLocales` event class
- `Flarum\Event\ConfigureModelDefaultAttributes` event class
- `Flarum\Event\GetModelRelationship` event class
- `Flarum\User\Event\BioChanged` event class
- `Flarum\Database\MigrationServiceProvider` moved into `Flarum\Database\DatabaseServiceProvider`
- Unused `admin/components/Widget` component (`admin/component/DashboardWidget` should be used instead)
- Mandrill mail driver (https://github.com/flarum/core/commit/bca833d3f1c34d45d95bf905902368a2753b8908)
### Deprecated
- `Flarum\User\Event\GetDisplayName` event class
- Global path helpers, `Flarum\Foundation\Application` path methods (https://github.com/flarum/core/pull/2155)
- `Flarum\User\AssertPermissionTrait` (https://github.com/flarum/core/pull/2044)
## [0.1.0-beta.13](https://github.com/flarum/core/compare/v0.1.0-beta.12...v0.1.0-beta.13)
### Added
@@ -452,7 +45,7 @@
- SES mail support (#2011)
- Backward compatibility layer for `Flarum\Mail\DriverInterface`, new methods from beta.12 are now required
- `Flarum\Util\Str` helper class
- `Flarum\Event\ConfigureMiddleware` event
- `Flarum\Event\ConfigureMiddleware` event
### Deprecated
- `Flarum\Event\AbstractConfigureRoutes` event class

View File

@@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2019-2021 Stichting Flarum (Flarum Foundation)
Copyright (c) 2019-2020 Stichting Flarum (Flarum Foundation)
Copyright (c) 2014-2019 Toby Zerner (toby.zerner@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy

View File

@@ -1,15 +1,12 @@
<p align="center"><img src="https://flarum.org/assets/img/logo.png"></p>
<p align="center"><img src="https://flarum.org/img/logo.png"></p>
<p align="center">
<a href="https://github.com/flarum/core/actions?query=workflow%3ATests"><img src="https://github.com/flarum/core/workflows/Tests/badge.svg" alt="PHP Tests"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/dt/flarum/core" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/github/v/release/flarum/core?sort=semver" alt="Latest Version"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/l/flarum/core" alt="License"></a>
<a href="https://huntr.dev/bounties/disclose/?target=https://github.com/flarum/core"><img src="https://cdn.huntr.dev/huntr_security_badge_mono.svg" alt="huntr"></a>
<a href="https://github.styleci.io/repos/28257573"><img src="https://github.styleci.io/repos/28257573/shield?style=flat" alt="StyleCI"></a>
<a href="https://travis-ci.org/flarum/core"><img src="https://travis-ci.org/flarum/core.svg" alt="Build Status"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://poser.pugx.org/flarum/core/d/total.svg" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://poser.pugx.org/flarum/core/v/stable.svg" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://poser.pugx.org/flarum/core/license.svg" alt="License"></a>
</p>
## About Flarum
**[Flarum](https://flarum.org/) is a delightfully simple discussion platform for your website.** It's fast and easy to use, with all the features you need to run a successful community. It is designed to be:
@@ -35,3 +32,4 @@ If you discover a security vulnerability within Flarum, please send an e-mail to
## License
Flarum is open-source software licensed under the [MIT License](https://github.com/flarum/flarum/blob/master/LICENSE).

View File

@@ -1,73 +1,70 @@
{
"name": "flarum/core",
"description": "Delightfully simple forum software.",
"keywords": [
"forum",
"discussion"
],
"keywords": ["forum", "discussion"],
"homepage": "https://flarum.org/",
"license": "MIT",
"authors": [
{
"name": "Flarum",
"email": "info@flarum.org",
"homepage": "https://flarum.org/team"
}
],
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/flarum"
"name": "Franz Liedke",
"email": "franz@develophp.org"
},
{
"type": "github",
"url": "https://github.com/sponsors/flarum"
"name": "Daniel Klabbers",
"email": "daniel@klabbers.email",
"homepage": "https://luceos.com"
},
{
"type": "other",
"url": "https://flarum.org/donate"
"name": "David Sevilla Martin",
"email": "me+flarum@datitisev.me",
"homepage": "https://datitisev.me"
},
{
"name": "Clark Winkelmann",
"email": "clark.winkelmann@gmail.com",
"homepage": "https://clarkwinkelmann.com"
},
{
"name": "Matthew Kilgore",
"email": "matthew@kilgore.dev"
}
],
"support": {
"issues": "https://github.com/flarum/core/issues",
"source": "https://github.com/flarum/core",
"docs": "https://docs.flarum.org",
"forum": "https://discuss.flarum.org",
"chat": "https://flarum.org/chat"
"docs": "https://flarum.org/docs/"
},
"require": {
"php": ">=7.3",
"php": ">=7.2",
"axy/sourcemap": "^0.1.4",
"components/font-awesome": "^5.14.0",
"dflydev/fig-cookies": "^3.0.0",
"components/font-awesome": "5.9.*",
"dflydev/fig-cookies": "^2.0.1",
"doctrine/dbal": "^2.7",
"dragonmantank/cron-expression": "^3.1.0",
"franzl/whoops-middleware": "^2.0.0",
"illuminate/bus": "^8.0",
"illuminate/cache": "^8.0",
"illuminate/config": "^8.0",
"illuminate/console": "^8.0",
"illuminate/container": "^8.0",
"illuminate/contracts": "^8.0",
"illuminate/database": "^8.0",
"illuminate/events": "^8.0",
"illuminate/filesystem": "^8.0",
"illuminate/hashing": "^8.0",
"illuminate/mail": "^8.0",
"illuminate/queue": "^8.0",
"illuminate/session": "^8.0",
"illuminate/support": "^8.0",
"illuminate/validation": "^8.0",
"illuminate/view": "^8.0",
"intervention/image": "2.5.* || ^2.6.1",
"laminas/laminas-diactoros": "^2.4.1",
"laminas/laminas-httphandlerrunner": "^1.2.0",
"laminas/laminas-stratigility": "^3.2.2",
"franzl/whoops-middleware": "^0.4.0",
"illuminate/bus": "^6.0",
"illuminate/cache": "^6.0",
"illuminate/config": "^6.0",
"illuminate/container": "^6.0",
"illuminate/contracts": "^6.0",
"illuminate/database": "^6.0",
"illuminate/events": "^6.0",
"illuminate/filesystem": "^6.0",
"illuminate/hashing": "^6.0",
"illuminate/mail": "^6.0",
"illuminate/queue": "^6.0",
"illuminate/session": "^6.0",
"illuminate/support": "^6.0",
"illuminate/validation": "^6.0",
"illuminate/view": "^6.0",
"intervention/image": "^2.5.0",
"laminas/laminas-diactoros": "^1.8.4",
"laminas/laminas-httphandlerrunner": "^1.0",
"laminas/laminas-stratigility": "^3.0",
"league/flysystem": "^1.0.11",
"matthiasmullie/minify": "^1.3",
"middlewares/base-path": "^2.0.1",
"middlewares/base-path-router": "^2.0.1",
"middlewares/request-handler": "^2.0.1",
"middlewares/base-path": "^1.1",
"middlewares/base-path-router": "^0.2.1",
"middlewares/request-handler": "^1.2",
"monolog/monolog": "^1.16.0",
"nesbot/carbon": "^2.0",
"nikic/fast-route": "^0.6",
@@ -75,18 +72,17 @@
"psr/http-server-handler": "^1.0",
"psr/http-server-middleware": "^1.0",
"s9e/text-formatter": "^2.3.6",
"symfony/config": "^5.2.2",
"symfony/console": "^5.2.2",
"symfony/event-dispatcher": "^5.2.2",
"symfony/mime": "^5.2.0",
"symfony/polyfill-intl-messageformatter": "^1.22.0",
"symfony/translation": "^5.1.5",
"symfony/yaml": "^5.2.2",
"symfony/config": "^3.3",
"symfony/console": "^4.2",
"symfony/event-dispatcher": "^4.3.2",
"symfony/translation": "^3.3",
"symfony/yaml": "^3.3",
"tobscure/json-api": "^0.3.0",
"wikimedia/less.php": "^3.0"
},
"require-dev": {
"flarum/testing": "1.0@dev"
"mockery/mockery": "^1.0",
"phpunit/phpunit": "^7.0"
},
"autoload": {
"psr-4": {
@@ -106,7 +102,7 @@
},
"extra": {
"branch-alias": {
"dev-master": "1.x-dev"
"dev-master": "0.1.x-dev"
}
},
"scripts": {

View File

@@ -1,8 +0,0 @@
{
"files": [
{
"path": "./dist/*.js"
}
],
"defaultCompression": "gzip"
}

6
js/.prettierrc.json Normal file
View File

@@ -0,0 +1,6 @@
{
"printWidth": 150,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5"
}

View File

@@ -1,2 +1,11 @@
/*
* This file is part of Flarum.
*
* (c) Toby Zerner <toby.zerner@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
export * from './src/common';
export * from './src/admin';

View File

@@ -1,82 +0,0 @@
/**
* @deprecated Please import `app` from a namespace instead of using it as a global variable.
*
* @example App in forum JS
* ```
* import app from 'flarum/forum/app';
* ```
*
* @example App in admin JS
* ```
* import app from 'flarum/admin/app';
* ```
*
* @example App in common JS
* ```
* import app from 'flarum/common/app';
* ```
*/
declare const app: never;
declare const m: import('mithril').Static;
declare const dayjs: typeof import('dayjs');
type ESModule = { __esModule: true; [key: string]: unknown };
/**
* The global `flarum` variable.
*
* Contains the compiled ES Modules for all Flarum extensions and core.
*
* @example <caption>Check if `flarum-tags` is present</captions>
* if ('flarum-tags' in flarum.extensions) {
* // Tags is installed and enabled!
* }
*/
interface FlarumObject {
/**
* Contains the compiled ES Module for Flarum's core.
*
* You shouldn't need to access this directly for any reason.
*/
core: Readonly<ESModule>;
/**
* Contains the compiled ES Modules for all Flarum extensions.
*
* @example <caption>Check if `flarum-tags` is present</captions>
* if ('flarum-tags' in flarum.extensions) {
* // Tags is installed and enabled!
* }
*/
extensions: Readonly<Record<string, ESModule>>;
}
declare const flarum: FlarumObject;
// Extend JQuery with our custom functions, defined with $.fn
interface JQuery {
/**
* Flarum's tooltip JQuery plugin.
*
* Do not use this directly. Instead use the `<Tooltip>` component that
* is exported from `flarum/common/components/Tooltip`.
*
* This will be removed in a future version of Flarum.
*
* @deprecated
*/
tooltip: import('./tooltips/index').TooltipJQueryFunction;
}
/**
* For more info, see: https://www.typescriptlang.org/docs/handbook/jsx.html#attribute-type-checking
*
* In a nutshell, we need to add `ElementAttributesProperty` to tell Typescript
* what property on component classes to look at for attribute typings. For our
* Component class, this would be `attrs` (e.g. `this.attrs...`)
*/
interface JSX {
ElementAttributesProperty: {
attrs: Record<string, unknown>;
};
}

View File

@@ -1,68 +0,0 @@
/**
* Selection of options accepted by [Bootstrap's tooltips](https://getbootstrap.com/docs/3.3/javascript/#tooltips-options).
*
* ---
*
* Not all options are present from Bootstrap to discourage the use of options
* that will be deprecated in the future.
*
* More commonly used options that will be deprecated remain, but are marked as
* such.
*
* @see https://getbootstrap.com/docs/3.3/javascript/#tooltips-options
*/
export interface TooltipCreationOptions {
/**
* Whether HTML content is allowed in the tooltip.
*
* ---
*
* **Warning:** this is a possible XSS attack vector. This option shouldn't
* be used wherever possible, and will not work when we migrate to CSS-only
* tooltips.
*
* @deprecated
*/
html?: boolean;
/**
* Tooltip position around the target element.
*/
placement?: 'top' | 'bottom' | 'left' | 'right';
/**
* Sets the delay between a trigger state occurring and the tooltip appearing
* on-screen.
*
* ---
*
* **Warning:** this option will be removed when we switch to CSS-only
* tooltips.
*
* @deprecated
*/
delay?: number;
/**
* Value used if no `title` attribute is present on the HTML element.
*
* If a function is given, it will be called with its `this` reference set to
* the element that the tooltip is attached to.
*/
title?: string;
/**
* How the tooltip is triggered.
*
* Either on `hover`, on `hover focus` (either of the two).
*
* ---
*
* **Warning:** `manual`, `click` and `focus` on its own are deprecated options
* which will not be supported in the future.
*/
trigger?: 'hover' | 'hover focus';
}
/**
* Creates a tooltip on a jQuery element reference.
*
* Returns the same jQuery reference to allow for method chaining.
*/
export type TooltipJQueryFunction = (tooltipOptions?: TooltipCreationOptions | 'destroy' | 'show' | 'hide') => JQuery;

View File

@@ -1,17 +0,0 @@
export default class AdminApplication extends Application {
extensionData: ExtensionData;
extensionCategories: {
feature: number;
theme: number;
language: number;
};
history: {
canGoBack: () => boolean;
getPrevious: () => void;
backUrl: () => any;
back: () => void;
};
getRequiredPermissions(permission: any): string[];
}
import Application from "../common/Application";
import ExtensionData from "./utils/ExtensionData";

View File

@@ -1,3 +0,0 @@
import Admin from './AdminApplication';
declare const app: Admin;
export default app;

View File

@@ -1,166 +0,0 @@
declare var _default: {
extend: typeof import("../common/extend");
Session: typeof import("../common/Session").default;
Store: typeof import("../common/Store").default;
'utils/BasicEditorDriver': typeof import("../common/utils/BasicEditorDriver").default;
'utils/evented': {
handlers: Object;
getHandlers(event: string): any[];
trigger(event: string, ...args: any[]): void;
on(event: string, handler: Function): void;
one(event: string, handler: Function): void;
off(event: string, handler: Function): void;
};
'utils/liveHumanTimes': typeof import("../common/utils/liveHumanTimes").default;
'utils/ItemList': typeof import("../common/utils/ItemList").default;
'utils/mixin': typeof import("../common/utils/mixin").default;
'utils/humanTime': typeof import("../common/utils/humanTime").default;
'utils/computed': typeof import("../common/utils/computed").default;
'utils/insertText': typeof import("../common/utils/insertText").default;
'utils/styleSelectedText': typeof import("../common/utils/styleSelectedText").default;
'utils/Drawer': typeof import("../common/utils/Drawer").default;
'utils/anchorScroll': typeof import("../common/utils/anchorScroll").default;
'utils/RequestError': typeof import("../common/utils/RequestError").default;
'utils/abbreviateNumber': typeof import("../common/utils/abbreviateNumber").default;
'utils/string': typeof import("../common/utils/string");
'utils/SubtreeRetainer': typeof import("../common/utils/SubtreeRetainer").default;
'utils/escapeRegExp': typeof import("../common/utils/escapeRegExp").default;
'utils/extract': typeof import("../common/utils/extract").default;
'utils/ScrollListener': typeof import("../common/utils/ScrollListener").default;
'utils/stringToColor': typeof import("../common/utils/stringToColor").default;
'utils/Stream': typeof import("mithril/stream");
'utils/subclassOf': typeof import("../common/utils/subclassOf").default;
'utils/setRouteWithForcedRefresh': typeof import("../common/utils/setRouteWithForcedRefresh").default;
'utils/patchMithril': typeof import("../common/utils/patchMithril").default;
'utils/proxifyCompat': (compat: {
[key: string]: any;
}, namespace: string) => {
[key: string]: any;
};
'utils/classList': (...classes: import("clsx").ClassValue[]) => string;
'utils/extractText': typeof import("../common/utils/extractText").default;
'utils/formatNumber': typeof import("../common/utils/formatNumber").default;
'utils/mapRoutes': typeof import("../common/utils/mapRoutes").default;
'utils/withAttr': (key: string, cb: Function) => (this: Element) => void;
'utils/throttleDebounce': typeof import("../common/utils/throttleDebounce");
'models/Notification': typeof import("../common/models/Notification").default;
'models/User': typeof import("../common/models/User").default;
'models/Post': typeof import("../common/models/Post").default;
'models/Discussion': typeof import("../common/models/Discussion").default;
'models/Group': typeof import("../common/models/Group").default;
'models/Forum': typeof import("../common/models/Forum").default;
Component: typeof import("../common/Component").default;
Fragment: typeof import("../common/Fragment").default;
Translator: typeof import("../common/Translator").default;
'components/AlertManager': typeof import("../common/components/AlertManager").default;
'components/Page': typeof import("../common/components/Page").default;
'components/Switch': typeof import("../common/components/Switch").default;
'components/Badge': typeof import("../common/components/Badge").default;
'components/LoadingIndicator': typeof import("../common/components/LoadingIndicator").default;
'components/Placeholder': typeof import("../common/components/Placeholder").default;
'components/Separator': typeof import("../common/components/Separator").default;
'components/Dropdown': typeof import("../common/components/Dropdown").default;
'components/SplitDropdown': typeof import("../common/components/SplitDropdown").default;
'components/RequestErrorModal': typeof import("../common/components/RequestErrorModal").default;
'components/FieldSet': typeof import("../common/components/FieldSet").default;
'components/Select': typeof import("../common/components/Select").default;
'components/Navigation': typeof import("../common/components/Navigation").default;
'components/Alert': typeof import("../common/components/Alert").default;
'components/Link': typeof import("../common/components/Link").default;
'components/LinkButton': typeof import("../common/components/LinkButton").default;
'components/Checkbox': typeof import("../common/components/Checkbox").default;
'components/SelectDropdown': typeof import("../common/components/SelectDropdown").default;
'components/ModalManager': typeof import("../common/components/ModalManager").default;
'components/Button': typeof import("../common/components/Button").default;
'components/Modal': typeof import("../common/components/Modal").default;
'components/GroupBadge': typeof import("../common/components/GroupBadge").default;
'components/TextEditor': typeof import("../common/components/TextEditor").default;
'components/TextEditorButton': typeof import("../common/components/TextEditorButton").default;
'components/Tooltip': typeof import("../common/components/Tooltip").default;
'components/EditUserModal': typeof import("../common/components/EditUserModal").default;
Model: typeof import("../common/Model").default;
Application: typeof import("../common/Application").default;
'helpers/fullTime': typeof import("../common/helpers/fullTime").default;
'helpers/avatar': typeof import("../common/helpers/avatar").default;
'helpers/icon': typeof import("../common/helpers/icon").default;
'helpers/humanTime': typeof import("../common/helpers/humanTime").default;
'helpers/punctuateSeries': typeof import("../common/helpers/punctuateSeries").default;
'helpers/highlight': typeof import("../common/helpers/highlight").default;
'helpers/username': typeof import("../common/helpers/username").default;
'helpers/userOnline': typeof import("../common/helpers/userOnline").default;
'helpers/listItems': typeof import("../common/helpers/listItems").default;
'resolvers/DefaultResolver': typeof import("../common/resolvers/DefaultResolver").default;
'states/PaginatedListState': typeof import("../common/states/PaginatedListState").default;
} & {
'utils/saveSettings': typeof saveSettings;
'utils/ExtensionData': typeof ExtensionData;
'utils/isExtensionEnabled': typeof isExtensionEnabled;
'utils/getCategorizedExtensions': typeof getCategorizedExtensions;
'utils/generateElementId': typeof generateElementId;
'components/SettingDropdown': typeof SettingDropdown;
'components/EditCustomFooterModal': typeof EditCustomFooterModal;
'components/SessionDropdown': typeof SessionDropdown;
'components/HeaderPrimary': typeof HeaderPrimary;
'components/AdminPage': typeof AdminPage;
'components/AppearancePage': typeof AppearancePage;
'components/StatusWidget': typeof StatusWidget;
'components/ExtensionsWidget': typeof ExtensionsWidget;
'components/HeaderSecondary': typeof HeaderSecondary;
'components/SettingsModal': typeof SettingsModal;
'components/DashboardWidget': typeof DashboardWidget;
'components/ExtensionPage': typeof ExtensionPage;
'components/ExtensionLinkButton': typeof ExtensionLinkButton;
'components/PermissionGrid': typeof PermissionGrid;
'components/ExtensionPermissionGrid': typeof ExtensionPermissionGrid;
'components/MailPage': typeof MailPage;
'components/UploadImageButton': typeof UploadImageButton;
'components/LoadingModal': typeof LoadingModal;
'components/DashboardPage': typeof DashboardPage;
'components/BasicsPage': typeof BasicsPage;
'components/UserListPage': typeof UserListPage;
'components/EditCustomHeaderModal': typeof EditCustomHeaderModal;
'components/PermissionsPage': typeof PermissionsPage;
'components/PermissionDropdown': typeof PermissionDropdown;
'components/AdminNav': typeof AdminNav;
'components/AdminHeader': typeof AdminHeader;
'components/EditCustomCssModal': typeof EditCustomCssModal;
'components/EditGroupModal': typeof EditGroupModal;
routes: typeof routes;
AdminApplication: typeof AdminApplication;
};
export default _default;
import saveSettings from "./utils/saveSettings";
import ExtensionData from "./utils/ExtensionData";
import isExtensionEnabled from "./utils/isExtensionEnabled";
import getCategorizedExtensions from "./utils/getCategorizedExtensions";
import generateElementId from "./utils/generateElementId";
import SettingDropdown from "./components/SettingDropdown";
import EditCustomFooterModal from "./components/EditCustomFooterModal";
import SessionDropdown from "./components/SessionDropdown";
import HeaderPrimary from "./components/HeaderPrimary";
import AdminPage from "./components/AdminPage";
import AppearancePage from "./components/AppearancePage";
import StatusWidget from "./components/StatusWidget";
import ExtensionsWidget from "./components/ExtensionsWidget";
import HeaderSecondary from "./components/HeaderSecondary";
import SettingsModal from "./components/SettingsModal";
import DashboardWidget from "./components/DashboardWidget";
import ExtensionPage from "./components/ExtensionPage";
import ExtensionLinkButton from "./components/ExtensionLinkButton";
import PermissionGrid from "./components/PermissionGrid";
import ExtensionPermissionGrid from "./components/ExtensionPermissionGrid";
import MailPage from "./components/MailPage";
import UploadImageButton from "./components/UploadImageButton";
import LoadingModal from "./components/LoadingModal";
import DashboardPage from "./components/DashboardPage";
import BasicsPage from "./components/BasicsPage";
import UserListPage from "./components/UserListPage";
import EditCustomHeaderModal from "./components/EditCustomHeaderModal";
import PermissionsPage from "./components/PermissionsPage";
import PermissionDropdown from "./components/PermissionDropdown";
import AdminNav from "./components/AdminNav";
import AdminHeader from "./components/AdminHeader";
import EditCustomCssModal from "./components/EditCustomCssModal";
import EditGroupModal from "./components/EditGroupModal";
import routes from "./routes";
import AdminApplication from "./AdminApplication";

View File

@@ -1,4 +0,0 @@
export default class AdminHeader extends Component<import("../../common/Component").ComponentAttrs, undefined> {
constructor();
}
import Component from "../../common/Component";

View File

@@ -1,15 +0,0 @@
export default class AdminNav extends Component<import("../../common/Component").ComponentAttrs, undefined> {
constructor();
query: Stream<string> | undefined;
scrollToActive(): void;
/**
* Build an item list of main links to show in the admin navigation.
*
* @return {ItemList}
*/
items(): ItemList;
extensionItems(): ItemList;
}
import Component from "../../common/Component";
import Stream from "../../common/utils/Stream";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,4 +0,0 @@
export default class AppearancePage extends AdminPage<import("../../common/components/Page").IPageAttrs> {
constructor();
}
import AdminPage from "./AdminPage";

View File

@@ -1,16 +0,0 @@
export default class BasicsPage extends AdminPage<import("../../common/components/Page").IPageAttrs> {
constructor();
localeOptions: {} | undefined;
displayNameOptions: {} | undefined;
slugDriverOptions: {} | undefined;
/**
* Build a list of options for the default homepage. Each option must be an
* object with `path` and `label` properties.
*
* @return {ItemList}
* @public
*/
public homePageItems(): ItemList;
}
import AdminPage from "./AdminPage";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,6 +0,0 @@
export default class DashboardPage extends AdminPage<import("../../common/components/Page").IPageAttrs> {
constructor();
availableWidgets(): ItemList;
}
import AdminPage from "./AdminPage";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,16 +0,0 @@
export default class DashboardWidget extends Component<import("../../common/Component").ComponentAttrs, undefined> {
constructor();
/**
* Get the class name to apply to the widget.
*
* @return {String}
*/
className(): string;
/**
* Get the content of the widget.
*
* @return {VirtualElement}
*/
content(): any;
}
import Component from "../../common/Component";

View File

@@ -1,3 +0,0 @@
export default class EditCustomCssModal extends SettingsModal {
}
import SettingsModal from "./SettingsModal";

View File

@@ -1,3 +0,0 @@
export default class EditCustomFooterModal extends SettingsModal {
}
import SettingsModal from "./SettingsModal";

View File

@@ -1,3 +0,0 @@
export default class EditCustomHeaderModal extends SettingsModal {
}
import SettingsModal from "./SettingsModal";

View File

@@ -1,24 +0,0 @@
/**
* The `EditGroupModal` component shows a modal dialog which allows the user
* to create or edit a group.
*/
export default class EditGroupModal extends Modal {
group: any;
nameSingular: Stream<any> | undefined;
namePlural: Stream<any> | undefined;
icon: Stream<any> | undefined;
color: Stream<any> | undefined;
isHidden: Stream<any> | undefined;
fields(): ItemList;
submitData(): {
nameSingular: any;
namePlural: any;
color: any;
icon: any;
isHidden: any;
};
deleteGroup(): void;
}
import Modal from "../../common/components/Modal";
import Stream from "../../common/utils/Stream";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,5 +0,0 @@
export default class ExtensionLinkButton extends LinkButton {
statusItems(name: any): ItemList;
}
import LinkButton from "../../common/components/LinkButton";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,22 +0,0 @@
export default class ExtensionPage extends AdminPage<import("../../common/components/Page").IPageAttrs> {
constructor();
extension: any;
changingState: boolean | undefined;
infoFields: {
discuss: string;
documentation: string;
support: string;
website: string;
donate: string;
source: string;
} | undefined;
className(): string;
sections(): ItemList;
topItems(): ItemList;
infoItems(): ItemList;
toggle(): void;
isEnabled(): any;
onerror(e: any): void;
}
import AdminPage from "./AdminPage";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,4 +0,0 @@
export default class ExtensionPermissionGrid extends PermissionGrid {
extensionId: any;
}
import PermissionGrid from "./PermissionGrid";

View File

@@ -1,6 +0,0 @@
export default class ExtensionsWidget extends DashboardWidget {
categorizedExtensions: {} | undefined;
extensionCategory(category: any): JSX.Element;
extensionWidget(extension: any): JSX.Element;
}
import DashboardWidget from "./DashboardWidget";

View File

@@ -1,16 +0,0 @@
/**
* The `HeaderPrimary` component displays primary header controls. On the
* default skin, these are shown just to the right of the forum title.
*/
export default class HeaderPrimary extends Component<import("../../common/Component").ComponentAttrs, undefined> {
constructor();
config(isInitialized: any, context: any): void;
/**
* Build an item list for the controls.
*
* @return {ItemList}
*/
items(): ItemList;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,14 +0,0 @@
/**
* The `HeaderSecondary` component displays secondary header controls.
*/
export default class HeaderSecondary extends Component<import("../../common/Component").ComponentAttrs, undefined> {
constructor();
/**
* Build an item list for the controls.
*
* @return {ItemList}
*/
items(): ItemList;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,3 +0,0 @@
export default class LoadingModal extends Modal {
}
import Modal from "../../common/components/Modal";

View File

@@ -1,13 +0,0 @@
export default class MailPage extends AdminPage<import("../../common/components/Page").IPageAttrs> {
constructor();
sendingTest: boolean | undefined;
refresh(): void;
status: {
sending: boolean;
errors: {};
} | undefined;
driverFields: any;
sendTestEmail(): void;
testEmailSuccessAlert: number | undefined;
}
import AdminPage from "./AdminPage";

View File

@@ -1,6 +0,0 @@
export default class PermissionDropdown extends Dropdown {
save(groupIds: any): void;
toggle(groupId: any): void;
isGroupDisabled(id: any): boolean;
}
import Dropdown from "../../common/components/Dropdown";

View File

@@ -1,12 +0,0 @@
export default class PermissionGrid extends Component<import("../../common/Component").ComponentAttrs, undefined> {
constructor();
permissionItems(): ItemList;
viewItems(): ItemList;
startItems(): ItemList;
replyItems(): ItemList;
moderateItems(): ItemList;
scopeItems(): ItemList;
scopeControlItems(): ItemList;
}
import Component from "../../common/Component";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,4 +0,0 @@
export default class PermissionsPage extends AdminPage<import("../../common/components/Page").IPageAttrs> {
constructor();
}
import AdminPage from "./AdminPage";

View File

@@ -1,14 +0,0 @@
/**
* The `SessionDropdown` component shows a button with the current user's
* avatar/name, with a dropdown of session controls.
*/
export default class SessionDropdown extends Dropdown {
/**
* Build an item list for the contents of the dropdown menu.
*
* @return {ItemList}
*/
items(): ItemList;
}
import Dropdown from "../../common/components/Dropdown";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,3 +0,0 @@
export default class SettingDropdown extends SelectDropdown {
}
import SelectDropdown from "../../common/components/SelectDropdown";

View File

@@ -1,10 +0,0 @@
export default class SettingsModal extends Modal {
settings: {} | undefined;
form(): string;
submitButton(): JSX.Element;
setting(key: any, fallback?: string): any;
dirty(): {};
changed(): number;
onsaved(): void;
}
import Modal from "../../common/components/Modal";

View File

@@ -1,6 +0,0 @@
export default class StatusWidget extends DashboardWidget {
items(): ItemList;
handleClearCache(e: any): void;
}
import DashboardWidget from "./DashboardWidget";
import ItemList from "../../common/utils/ItemList";

View File

@@ -1,28 +0,0 @@
export default class UploadImageButton extends Button<import("../../common/components/Button").IButtonAttrs> {
constructor();
loading: boolean;
/**
* Prompt the user to upload an image.
*/
upload(): void;
/**
* Remove the logo.
*/
remove(): void;
resourceUrl(): string;
/**
* After a successful upload/removal, reload the page.
*
* @param {Object} response
* @protected
*/
protected success(response: Object): void;
/**
* If upload/removal fails, stop loading.
*
* @param {Object} response
* @protected
*/
protected failure(response: Object): void;
}
import Button from "../../common/components/Button";

View File

@@ -1,72 +0,0 @@
/// <reference types="mithril" />
import ItemList from '../../common/utils/ItemList';
import AdminPage from './AdminPage';
/**
* Admin page which displays a paginated list of all users on the forum.
*/
export default class UserListPage extends AdminPage {
/**
* Number of users to load per page.
*/
private numPerPage;
/**
* Current page number. Zero-indexed.
*/
private pageNumber;
/**
* Total number of forum users.
*
* Fetched from the active `AdminApplication` (`app`), with
* data provided by `AdminPayload.php`, or `flarum/statistics`
* if installed.
*/
readonly userCount: number;
/**
* Get total number of user pages.
*/
private getTotalPageCount;
/**
* This page's array of users.
*
* `undefined` when page loads as no data has been fetched.
*/
private pageData;
/**
* Are there more users available?
*/
private moreData;
private isLoadingPage;
/**
* Component to render.
*/
content(): JSX.Element[];
/**
* Build an item list of columns to show for each user.
*
* Each column in the list should be an object with keys `name` and `content`.
*
* `name` is a string that will be used as the column name.
* `content` is a function with the User model passed as the first and only argument.
*
* See `UserListPage.tsx` for examples.
*/
columns(): ItemList;
headerInfo(): {
className: string;
icon: string;
title: any;
description: any;
};
/**
* Asynchronously fetch the next set of users to be rendered.
*
* Returns an array of Users, plus the raw API payload.
*
* Uses the `this.numPerPage` as the response limit, and automatically calculates the offset required from `pageNumber`.
*
* @param pageNumber The page number to load and display
*/
loadPage(pageNumber: number): Promise<void>;
nextPage(): void;
previousPage(): void;
}

View File

@@ -1,5 +0,0 @@
import app from './app';
export { app };
export declare const compat: {
[key: string]: any;
};

View File

@@ -1,9 +0,0 @@
import DefaultResolver from '../../common/resolvers/DefaultResolver';
/**
* A custom route resolver for ExtensionPage that generates handles routes
* to default extension pages or a page provided by an extension.
*/
export default class ExtensionPageResolver extends DefaultResolver {
static extension: string | null;
onmatch(args: any, requestedPath: any, route: any): any;
}

View File

@@ -1,6 +0,0 @@
/**
* The `routes` initializer defines the forum app's routes.
*
* @param {App} app
*/
export default function _default(app: any): void;

View File

@@ -1,98 +0,0 @@
export default class ExtensionData {
data: {};
currentExtension: any;
/**
* This function simply takes the extension id
*
* @example
* app.extensionData.load('flarum-tags')
*
* flarum/flags -> flarum-flags | acme/extension -> acme-extension
*
* @param extension
*/
for(extension: any): ExtensionData;
/**
* This function registers your settings with Flarum
*
* It takes either a settings object or a callback.
*
* @example
*
* .registerSetting({
* setting: 'flarum-flags.guidelines_url',
* type: 'text', // This will be inputted into the input tag for the setting (text/number/etc)
* label: app.translator.trans('flarum-flags.admin.settings.guidelines_url_label')
* }, 15) // priority is optional (ItemList)
*
*
* @param content
* @param priority
* @returns {ExtensionData}
*/
registerSetting(content: any, priority?: number): ExtensionData;
/**
* This function registers your permission with Flarum
*
* @example
*
* .registerPermission('permissions', {
* icon: 'fas fa-flag',
* label: app.translator.trans('flarum-flags.admin.permissions.view_flags_label'),
* permission: 'discussion.viewFlags'
* }, 'moderate', 65)
*
* @param content
* @param permissionType
* @param priority
* @returns {ExtensionData}
*/
registerPermission(content: any, permissionType?: any, priority?: number): ExtensionData;
/**
* Replace the default extension page with a custom component.
* This component would typically extend ExtensionPage
*
* @param component
* @returns {ExtensionData}
*/
registerPage(component: any): ExtensionData;
/**
* Get an extension's registered settings
*
* @param extensionId
* @returns {boolean|*}
*/
getSettings(extensionId: any): boolean | any;
/**
*
* Get an ItemList of all extensions' registered permissions
*
* @param extension
* @param type
* @returns {ItemList}
*/
getAllExtensionPermissions(type: any): ItemList;
/**
* Get a singular extension's registered permissions
*
* @param extension
* @param type
* @returns {boolean|*}
*/
getExtensionPermissions(extension: any, type: any): boolean | any;
/**
* Checks whether a given extension has registered permissions.
*
* @param extension
* @returns {boolean}
*/
extensionHasPermissions(extension: any): boolean;
/**
* Returns an extension's custom page component if it exists.
*
* @param extension
* @returns {boolean|*}
*/
getPage(extension: any): boolean | any;
}
import ItemList from "../../common/utils/ItemList";

View File

@@ -1 +0,0 @@
export { nanoid as default } from 'nanoid';

View File

@@ -1 +0,0 @@
export default function getCategorizedExtensions(): {};

View File

@@ -1 +0,0 @@
export default function isExtensionEnabled(name: any): any;

View File

@@ -1 +0,0 @@
export default function saveSettings(settings: any): Promise<any>;

View File

@@ -1,174 +0,0 @@
/**
* The `App` class provides a container for an application, as well as various
* utilities for the rest of the app to use.
*/
export default class Application {
/**
* The forum model for this application.
*
* @type {Forum}
* @public
*/
public forum: Forum;
/**
* A map of routes, keyed by a unique route name. Each route is an object
* containing the following properties:
*
* - `path` The path that the route is accessed at.
* - `component` The Mithril component to render when this route is active.
*
* @example
* app.routes.discussion = {path: '/d/:id', component: DiscussionPage.component()};
*
* @type {Object}
* @public
*/
public routes: Object;
/**
* An ordered list of initializers to bootstrap the application.
*
* @type {ItemList}
* @public
*/
public initializers: ItemList;
/**
* The app's session.
*
* @type {Session}
* @public
*/
public session: Session;
/**
* The app's translator.
*
* @type {Translator}
* @public
*/
public translator: Translator;
/**
* The app's data store.
*
* @type {Store}
* @public
*/
public store: Store;
/**
* A local cache that can be used to store data at the application level, so
* that is persists between different routes.
*
* @type {Object}
* @public
*/
public cache: Object;
/**
* Whether or not the app has been booted.
*
* @type {Boolean}
* @public
*/
public booted: boolean;
/**
* The key for an Alert that was shown as a result of an AJAX request error.
* If present, it will be dismissed on the next successful request.
*
* @type {int}
* @private
*/
private requestErrorAlert;
/**
* The page the app is currently on.
*
* This object holds information about the type of page we are currently
* visiting, and sometimes additional arbitrary page state that may be
* relevant to lower-level components.
*
* @type {PageState}
*/
current: PageState;
/**
* The page the app was on before the current page.
*
* Once the application navigates to another page, the object previously
* assigned to this.current will be moved to this.previous, while this.current
* is re-initialized.
*
* @type {PageState}
*/
previous: PageState;
modal: ModalManagerState;
/**
* An object that manages the state of active alerts.
*
* @type {AlertManagerState}
*/
alerts: AlertManagerState;
data: any;
title: string;
titleCount: number;
initialRoute: any;
load(payload: any): void;
boot(): void;
bootExtensions(extensions: any): void;
mount(basePath?: string): void;
drawer: Drawer | undefined;
/**
* Get the API response document that has been preloaded into the application.
*
* @return {Object|null}
* @public
*/
public preloadedApiDocument(): Object | null;
/**
* Determine the current screen mode, based on our media queries.
*
* @returns {String} - one of "phone", "tablet", "desktop" or "desktop-hd"
*/
screen(): string;
/**
* Set the <title> of the page.
*
* @param {String} title
* @public
*/
public setTitle(title: string): void;
/**
* Set a number to display in the <title> of the page.
*
* @param {Integer} count
*/
setTitleCount(count: any): void;
updateTitle(): void;
/**
* Make an AJAX request, handling any low-level errors that may occur.
*
* @see https://mithril.js.org/request.html
* @param {Object} options
* @return {Promise}
* @public
*/
public request(originalOptions: any): Promise<any>;
/**
* @param {RequestError} error
* @param {string[]} [formattedError]
* @private
*/
private showDebug;
/**
* Construct a URL to the route with the given name.
*
* @param {String} name
* @param {Object} params
* @return {String}
* @public
*/
public route(name: string, params?: Object): string;
}
import Forum from "./models/Forum";
import ItemList from "./utils/ItemList";
import Session from "./Session";
import Translator from "./Translator";
import Store from "./Store";
import PageState from "./states/PageState";
import ModalManagerState from "./states/ModalManagerState";
import AlertManagerState from "./states/AlertManagerState";
import Drawer from "./utils/Drawer";

View File

@@ -1,114 +0,0 @@
import type Mithril from 'mithril';
export interface ComponentAttrs extends Mithril.Attributes {
}
/**
* The `Component` class defines a user interface 'building block'. A component
* generates a virtual DOM to be rendered on each redraw.
*
* Essentially, this is a wrapper for Mithril's components that adds several useful features:
*
* - In the `oninit` and `onbeforeupdate` lifecycle hooks, we store vnode attrs in `this.attrs.
* This allows us to use attrs across components without having to pass the vnode to every single
* method.
* - The static `initAttrs` method allows a convenient way to provide defaults (or to otherwise modify)
* the attrs that have been passed into a component.
* - When the component is created in the DOM, we store its DOM element under `this.element`; this lets
* us use jQuery to modify child DOM state from internal methods via the `this.$()` method.
* - A convenience `component` method, which serves as an alternative to hyperscript and JSX.
*
* As with other Mithril components, components extending Component can be initialized
* and nested using JSX, hyperscript, or a combination of both. The `component` method can also
* be used.
*
* @example
* return m('div', <MyComponent foo="bar"><p>Hello World</p></MyComponent>);
*
* @example
* return m('div', MyComponent.component({foo: 'bar'), m('p', 'Hello World!'));
*
* @see https://mithril.js.org/components.html
*/
export default abstract class Component<Attrs extends ComponentAttrs = ComponentAttrs, State = undefined> implements Mithril.ClassComponent<Attrs> {
/**
* The root DOM element for the component.
*/
protected element: Element;
/**
* The attributes passed into the component.
*
* @see https://mithril.js.org/components.html#passing-data-to-components
*/
protected attrs: Attrs;
/**
* Class component state that is persisted between redraws.
*
* Updating this will **not** automatically trigger a redraw, unlike
* other frameworks.
*
* This is different to Vnode state, which is always an instance of your
* class component.
*
* This is `undefined` by default.
*/
protected state: State;
/**
* @inheritdoc
*/
abstract view(vnode: Mithril.Vnode<Attrs, this>): Mithril.Children;
/**
* @inheritdoc
*/
oninit(vnode: Mithril.Vnode<Attrs, this>): void;
/**
* @inheritdoc
*/
oncreate(vnode: Mithril.VnodeDOM<Attrs, this>): void;
/**
* @inheritdoc
*/
onbeforeupdate(vnode: Mithril.VnodeDOM<Attrs, this>): void;
/**
* @inheritdoc
*/
onupdate(vnode: Mithril.VnodeDOM<Attrs, this>): void;
/**
* @inheritdoc
*/
onbeforeremove(vnode: Mithril.VnodeDOM<Attrs, this>): void;
/**
* @inheritdoc
*/
onremove(vnode: Mithril.VnodeDOM<Attrs, this>): void;
/**
* Returns a jQuery object for this component's element. If you pass in a
* selector string, this method will return a jQuery object, using the current
* element as its buffer.
*
* For example, calling `component.$('li')` will return a jQuery object
* containing all of the `li` elements inside the DOM element of this
* component.
*
* @param [selector] a jQuery-compatible selector string
* @returns the jQuery object for the DOM node
* @final
*/
protected $(selector?: string): JQuery;
/**
* Convenience method to attach a component without JSX.
* Has the same effect as calling `m(THIS_CLASS, attrs, children)`.
*
* @see https://mithril.js.org/hyperscript.html#mselector,-attributes,-children
*/
static component(attrs?: {}, children?: null): Mithril.Vnode;
/**
* Saves a reference to the vnode attrs after running them through initAttrs,
* and checking for common issues.
*/
private setAttrs;
/**
* Initialize the component's attrs.
*
* This can be used to assign default values for missing, optional attrs.
*/
protected static initAttrs<T>(attrs: T): void;
}

View File

@@ -1,53 +0,0 @@
import type Mithril from 'mithril';
/**
* The `Fragment` class represents a chunk of DOM that is rendered once with Mithril and then takes
* over control of its own DOM and lifecycle.
*
* This is very similar to the `Component` wrapper class, but is used for more fine-grained control over
* the rendering and display of some significant chunks of the DOM. In contrast to components, fragments
* do not offer Mithril's lifecycle hooks.
*
* Use this when you want to enjoy the benefits of JSX / VDOM for initial rendering, combined with
* small helper methods that then make updates to that DOM directly, instead of fully redrawing
* everything through Mithril.
*
* This should only be used when necessary, and only with `m.render`. If you are unsure whether you need
* this or `Component, you probably need `Component`.
*/
export default abstract class Fragment {
/**
* The root DOM element for the fragment.
*/
protected element: Element;
/**
* Returns a jQuery object for this fragment's element. If you pass in a
* selector string, this method will return a jQuery object, using the current
* element as its buffer.
*
* For example, calling `fragment.$('li')` will return a jQuery object
* containing all of the `li` elements inside the DOM element of this
* fragment.
*
* @param {String} [selector] a jQuery-compatible selector string
* @returns {jQuery} the jQuery object for the DOM node
* @final
*/
$(selector: any): JQuery<any>;
/**
* Get the renderable virtual DOM that represents the fragment's view.
*
* This should NOT be overridden by subclasses. Subclasses wishing to define
* their virtual DOM should override Fragment#view instead.
*
* @example
* const fragment = new MyFragment();
* m.render(document.body, fragment.render());
*
* @final
*/
render(): Mithril.Vnode<Mithril.Attributes, this>;
/**
* Creates a view out of virtual elements.
*/
abstract view(): Mithril.Vnode<Mithril.Attributes, this>;
}

View File

@@ -1,149 +0,0 @@
/**
* The `Model` class represents a local data resource. It provides methods to
* persist changes via the API.
*
* @abstract
*/
export default class Model {
/**
* Generate a function which returns the value of the given attribute.
*
* @param {String} name
* @param {function} [transform] A function to transform the attribute value
* @return {*}
* @public
*/
public static attribute(name: string, transform?: Function | undefined): any;
/**
* Generate a function which returns the value of the given has-one
* relationship.
*
* @param {String} name
* @return {Model|Boolean|undefined} false if no information about the
* relationship exists; undefined if the relationship exists but the model
* has not been loaded; or the model if it has been loaded.
* @public
*/
public static hasOne(name: string): Model | boolean | undefined;
/**
* Generate a function which returns the value of the given has-many
* relationship.
*
* @param {String} name
* @return {Array|Boolean} false if no information about the relationship
* exists; an array if it does, containing models if they have been
* loaded, and undefined for those that have not.
* @public
*/
public static hasMany(name: string): any[] | boolean;
/**
* Transform the given value into a Date object.
*
* @param {String} value
* @return {Date|null}
* @public
*/
public static transformDate(value: string): Date | null;
/**
* Get a resource identifier object for the given model.
*
* @param {Model} model
* @return {Object}
* @protected
*/
protected static getIdentifier(model: Model): Object;
/**
* @param {Object} data A resource object from the API.
* @param {Store} store The data store that this model should be persisted to.
* @public
*/
constructor(data?: Object, store?: any);
/**
* The resource object from the API.
*
* @type {Object}
* @public
*/
public data: Object;
/**
* The time at which the model's data was last updated. Watching the value
* of this property is a fast way to retain/cache a subtree if data hasn't
* changed.
*
* @type {Date}
* @public
*/
public freshness: Date;
/**
* Whether or not the resource exists on the server.
*
* @type {Boolean}
* @public
*/
public exists: boolean;
/**
* The data store that this resource should be persisted to.
*
* @type {Store}
* @protected
*/
protected store: any;
/**
* Get the model's ID.
*
* @return {Integer}
* @public
* @final
*/
public id(): any;
/**
* Get one of the model's attributes.
*
* @param {String} attribute
* @return {*}
* @public
* @final
*/
public attribute(attribute: string): any;
/**
* Merge new data into this model locally.
*
* @param {Object} data A resource object to merge into this model
* @public
*/
public pushData(data: Object): void;
/**
* Merge new attributes into this model locally.
*
* @param {Object} attributes The attributes to merge.
* @public
*/
public pushAttributes(attributes: Object): void;
/**
* Merge new attributes into this model, both locally and with persistence.
*
* @param {Object} attributes The attributes to save. If a 'relationships' key
* exists, it will be extracted and relationships will also be saved.
* @param {Object} [options]
* @return {Promise}
* @public
*/
public save(attributes: Object, options?: Object | undefined): Promise<any>;
/**
* Send a request to delete the resource.
*
* @param {Object} body Data to send along with the DELETE request.
* @param {Object} [options]
* @return {Promise}
* @public
*/
public delete(body: Object, options?: Object | undefined): Promise<any>;
/**
* Construct a path to the API endpoint for this resource.
*
* @return {String}
* @protected
*/
protected apiEndpoint(): string;
copyData(): any;
}

View File

@@ -1,37 +0,0 @@
/**
* The `Session` class defines the current user session. It stores a reference
* to the current authenticated user, and provides methods to log in/out.
*/
export default class Session {
constructor(user: any, csrfToken: any);
/**
* The current authenticated user.
*
* @type {User|null}
* @public
*/
public user: any | null;
/**
* The CSRF token.
*
* @type {String|null}
* @public
*/
public csrfToken: string | null;
/**
* Attempt to log in a user.
*
* @param {String} identification The username/email.
* @param {String} password
* @param {Object} [options]
* @return {Promise}
* @public
*/
public login(body: any, options?: Object | undefined): Promise<any>;
/**
* Log the user out.
*
* @public
*/
public logout(): void;
}

View File

@@ -1,97 +0,0 @@
/**
* The `Store` class defines a local data store, and provides methods to
* retrieve data from the API.
*/
export default class Store {
constructor(models: any);
/**
* The local data store. A tree of resource types to IDs, such that
* accessing data[type][id] will return the model for that type/ID.
*
* @type {Object}
* @protected
*/
protected data: Object;
/**
* The model registry. A map of resource types to the model class that
* should be used to represent resources of that type.
*
* @type {Object}
* @public
*/
public models: Object;
/**
* Push resources contained within an API payload into the store.
*
* @param {Object} payload
* @return {Model|Model[]} The model(s) representing the resource(s) contained
* within the 'data' key of the payload.
* @public
*/
public pushPayload(payload: Object): any | any[];
/**
* Create a model to represent a resource object (or update an existing one),
* and push it into the store.
*
* @param {Object} data The resource object
* @return {Model|null} The model, or null if no model class has been
* registered for this resource type.
* @public
*/
public pushObject(data: Object): any | null;
/**
* Make a request to the API to find record(s) of a specific type.
*
* @param {String} type The resource type.
* @param {Integer|Integer[]|Object} [id] The ID(s) of the model(s) to retrieve.
* Alternatively, if an object is passed, it will be handled as the
* `query` parameter.
* @param {Object} [query]
* @param {Object} [options]
* @return {Promise}
* @public
*/
public find(type: string, id?: any | any[] | Object, query?: Object | undefined, options?: Object | undefined): Promise<any>;
/**
* Get a record from the store by ID.
*
* @param {String} type The resource type.
* @param {Integer} id The resource ID.
* @return {Model}
* @public
*/
public getById(type: string, id: any): any;
/**
* Get a record from the store by the value of a model attribute.
*
* @param {String} type The resource type.
* @param {String} key The name of the method on the model.
* @param {*} value The value of the model attribute.
* @return {Model}
* @public
*/
public getBy(type: string, key: string, value: any): any;
/**
* Get all loaded records of a specific type.
*
* @param {String} type
* @return {Model[]}
* @public
*/
public all(type: string): any[];
/**
* Remove the given model from the store.
*
* @param {Model} model
*/
remove(model: any): void;
/**
* Create a new record of the given type.
*
* @param {String} type The resource type
* @param {Object} [data] Any data to initialize the model with
* @return {Model}
* @public
*/
public createRecord(type: string, data?: Object | undefined): any;
}

View File

@@ -1,31 +0,0 @@
declare type Translations = Record<string, string>;
declare type TranslatorParameters = Record<string, unknown>;
export default class Translator {
/**
* A map of translation keys to their translated values.
*/
translations: Translations;
/**
* The underlying ICU MessageFormatter util.
*/
protected formatter: any;
setLocale(locale: string): void;
addTranslations(translations: Translations): void;
/**
* An extensible entrypoint for extenders to register type handlers for translations.
*/
protected formatterTypeHandlers(): {
plural: any;
select: any;
};
/**
* A temporary system to preprocess parameters.
* Should not be used by extensions.
* TODO: An extender will be added in v1.x.
*
* @internal
*/
protected preprocessParameters(parameters: TranslatorParameters): TranslatorParameters;
trans(id: string, parameters?: TranslatorParameters): any;
}
export {};

View File

@@ -1,6 +0,0 @@
import type Application from './Application';
declare const _default: Application;
/**
* The instance of Application within the common namespace.
*/
export default _default;

View File

@@ -1,172 +0,0 @@
declare var _default: {
extend: typeof extend;
Session: typeof Session;
Store: typeof Store;
'utils/BasicEditorDriver': typeof BasicEditorDriver;
'utils/evented': {
handlers: Object;
getHandlers(event: string): any[];
trigger(event: string, ...args: any[]): void;
on(event: string, handler: Function): void;
one(event: string, handler: Function): void;
off(event: string, handler: Function): void;
};
'utils/liveHumanTimes': typeof liveHumanTimes;
'utils/ItemList': typeof ItemList;
'utils/mixin': typeof mixin;
'utils/humanTime': typeof humanTime;
'utils/computed': typeof computed;
'utils/insertText': typeof insertText;
'utils/styleSelectedText': typeof styleSelectedText;
'utils/Drawer': typeof Drawer;
'utils/anchorScroll': typeof anchorScroll;
'utils/RequestError': typeof RequestError;
'utils/abbreviateNumber': typeof abbreviateNumber;
'utils/string': typeof string;
'utils/SubtreeRetainer': typeof SubtreeRetainer;
'utils/escapeRegExp': typeof escapeRegExp;
'utils/extract': typeof extract;
'utils/ScrollListener': typeof ScrollListener;
'utils/stringToColor': typeof stringToColor;
'utils/Stream': typeof Stream;
'utils/subclassOf': typeof subclassOf;
'utils/setRouteWithForcedRefresh': typeof setRouteWithForcedRefresh;
'utils/patchMithril': typeof patchMithril;
'utils/proxifyCompat': (compat: {
[key: string]: any;
}, namespace: string) => {
[key: string]: any;
};
'utils/classList': (...classes: import("clsx").ClassValue[]) => string;
'utils/extractText': typeof extractText;
'utils/formatNumber': typeof formatNumber;
'utils/mapRoutes': typeof mapRoutes;
'utils/withAttr': (key: string, cb: Function) => (this: Element) => void;
'utils/throttleDebounce': typeof ThrottleDebounce;
'models/Notification': typeof Notification;
'models/User': typeof User;
'models/Post': typeof Post;
'models/Discussion': typeof Discussion;
'models/Group': typeof Group;
'models/Forum': typeof Forum;
Component: typeof Component;
Fragment: typeof Fragment;
Translator: typeof Translator;
'components/AlertManager': typeof AlertManager;
'components/Page': typeof Page;
'components/Switch': typeof Switch;
'components/Badge': typeof Badge;
'components/LoadingIndicator': typeof LoadingIndicator;
'components/Placeholder': typeof Placeholder;
'components/Separator': typeof Separator;
'components/Dropdown': typeof Dropdown;
'components/SplitDropdown': typeof SplitDropdown;
'components/RequestErrorModal': typeof RequestErrorModal;
'components/FieldSet': typeof FieldSet;
'components/Select': typeof Select;
'components/Navigation': typeof Navigation;
'components/Alert': typeof Alert;
'components/Link': typeof Link;
'components/LinkButton': typeof LinkButton;
'components/Checkbox': typeof Checkbox;
'components/SelectDropdown': typeof SelectDropdown;
'components/ModalManager': typeof ModalManager;
'components/Button': typeof Button;
'components/Modal': typeof Modal;
'components/GroupBadge': typeof GroupBadge;
'components/TextEditor': typeof TextEditor;
'components/TextEditorButton': typeof TextEditorButton;
'components/Tooltip': typeof Tooltip;
'components/EditUserModal': typeof EditUserModal;
Model: typeof Model;
Application: typeof Application;
'helpers/fullTime': typeof fullTime;
'helpers/avatar': typeof avatar;
'helpers/icon': typeof icon;
'helpers/humanTime': typeof humanTimeHelper;
'helpers/punctuateSeries': typeof punctuateSeries;
'helpers/highlight': typeof highlight;
'helpers/username': typeof username;
'helpers/userOnline': typeof userOnline;
'helpers/listItems': typeof listItems;
'resolvers/DefaultResolver': typeof DefaultResolver;
'states/PaginatedListState': typeof PaginatedListState;
};
export default _default;
import * as extend from "./extend";
import Session from "./Session";
import Store from "./Store";
import BasicEditorDriver from "./utils/BasicEditorDriver";
import liveHumanTimes from "./utils/liveHumanTimes";
import ItemList from "./utils/ItemList";
import mixin from "./utils/mixin";
import humanTime from "./utils/humanTime";
import computed from "./utils/computed";
import insertText from "./utils/insertText";
import styleSelectedText from "./utils/styleSelectedText";
import Drawer from "./utils/Drawer";
import anchorScroll from "./utils/anchorScroll";
import RequestError from "./utils/RequestError";
import abbreviateNumber from "./utils/abbreviateNumber";
import * as string from "./utils/string";
import SubtreeRetainer from "./utils/SubtreeRetainer";
import escapeRegExp from "./utils/escapeRegExp";
import extract from "./utils/extract";
import ScrollListener from "./utils/ScrollListener";
import stringToColor from "./utils/stringToColor";
import Stream from "./utils/Stream";
import subclassOf from "./utils/subclassOf";
import setRouteWithForcedRefresh from "./utils/setRouteWithForcedRefresh";
import patchMithril from "./utils/patchMithril";
import extractText from "./utils/extractText";
import formatNumber from "./utils/formatNumber";
import mapRoutes from "./utils/mapRoutes";
import * as ThrottleDebounce from "./utils/throttleDebounce";
import Notification from "./models/Notification";
import User from "./models/User";
import Post from "./models/Post";
import Discussion from "./models/Discussion";
import Group from "./models/Group";
import Forum from "./models/Forum";
import Component from "./Component";
import Fragment from "./Fragment";
import Translator from "./Translator";
import AlertManager from "./components/AlertManager";
import Page from "./components/Page";
import Switch from "./components/Switch";
import Badge from "./components/Badge";
import LoadingIndicator from "./components/LoadingIndicator";
import Placeholder from "./components/Placeholder";
import Separator from "./components/Separator";
import Dropdown from "./components/Dropdown";
import SplitDropdown from "./components/SplitDropdown";
import RequestErrorModal from "./components/RequestErrorModal";
import FieldSet from "./components/FieldSet";
import Select from "./components/Select";
import Navigation from "./components/Navigation";
import Alert from "./components/Alert";
import Link from "./components/Link";
import LinkButton from "./components/LinkButton";
import Checkbox from "./components/Checkbox";
import SelectDropdown from "./components/SelectDropdown";
import ModalManager from "./components/ModalManager";
import Button from "./components/Button";
import Modal from "./components/Modal";
import GroupBadge from "./components/GroupBadge";
import TextEditor from "./components/TextEditor";
import TextEditorButton from "./components/TextEditorButton";
import Tooltip from "./components/Tooltip";
import EditUserModal from "./components/EditUserModal";
import Model from "./Model";
import Application from "./Application";
import fullTime from "./helpers/fullTime";
import avatar from "./helpers/avatar";
import icon from "./helpers/icon";
import humanTimeHelper from "./helpers/humanTime";
import punctuateSeries from "./helpers/punctuateSeries";
import highlight from "./helpers/highlight";
import username from "./helpers/username";
import userOnline from "./helpers/userOnline";
import listItems from "./helpers/listItems";
import DefaultResolver from "./resolvers/DefaultResolver";
import PaginatedListState from "./states/PaginatedListState";

View File

@@ -1,19 +0,0 @@
import Component, { ComponentAttrs } from '../Component';
import type Mithril from 'mithril';
export interface AlertAttrs extends ComponentAttrs {
/** The type of alert this is. Will be used to give the alert a class name of `Alert--{type}`. */
type?: string;
/** An array of controls to show in the alert. */
controls?: Mithril.Children;
/** Whether or not the alert can be dismissed. */
dismissible?: boolean;
/** A callback to run when the alert is dismissed */
ondismiss?: Function;
}
/**
* The `Alert` component represents an alert box, which contains a message,
* some controls, and may be dismissible.
*/
export default class Alert<T extends AlertAttrs = AlertAttrs> extends Component<T> {
view(vnode: Mithril.Vnode): JSX.Element;
}

View File

@@ -1,8 +0,0 @@
/**
* The `AlertManager` component provides an area in which `Alert` components can
* be shown and dismissed.
*/
export default class AlertManager extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
}
import Component from "../Component";

View File

@@ -1,17 +0,0 @@
/**
* The `Badge` component represents a user/discussion badge, indicating some
* status (e.g. a discussion is stickied, a user is an admin).
*
* A badge may have the following special attrs:
*
* - `type` The type of badge this is. This will be used to give the badge a
* class name of `Badge--{type}`.
* - `icon` The name of an icon to show inside the badge.
* - `label`
*
* All other attrs will be assigned as attributes on the badge element.
*/
export default class Badge extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
}
import Component from "../Component";

View File

@@ -1,69 +0,0 @@
import type Mithril from 'mithril';
import Component, { ComponentAttrs } from '../Component';
export interface IButtonAttrs extends ComponentAttrs {
/**
* Class(es) of an optional icon to be rendered within the button.
*
* If provided, the button will gain a `has-icon` class.
*/
icon?: string;
/**
* Disables button from user input.
*
* Default: `false`
*/
disabled?: boolean;
/**
* Show a loading spinner within the button.
*
* If `true`, also disables the button.
*
* Default: `false`
*/
loading?: boolean;
/**
* **DEPRECATED:** Please use the `aria-label` attribute instead. For tooltips, use
* the `<Tooltip>` component.
*
* Accessible text for the button. This should always be present if the button only
* contains an icon.
*
* The textual content of this attribute is passed to the DOM element as `aria-label`.
*
* @deprecated
*/
title?: string | Mithril.ChildArray;
/**
* Accessible text for the button. This should always be present if the button only
* contains an icon.
*
* The textual content of this attribute is passed to the DOM element as `aria-label`.
*/
'aria-label'?: string | Mithril.ChildArray;
/**
* Button type.
*
* Default: `"button"`
*
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attr-type
*/
type?: string;
}
/**
* The `Button` component defines an element which, when clicked, performs an
* action.
*
* Other attrs will be assigned as attributes on the `<button>` element.
*
* Note that a Button has no default class names. This is because a Button can
* be used to represent any generic clickable control, like a menu item. Common
* styles can be applied by providing `className="Button"` to the Button component.
*/
export default class Button<CustomAttrs extends IButtonAttrs = IButtonAttrs> extends Component<CustomAttrs> {
view(vnode: Mithril.Vnode<IButtonAttrs, never>): JSX.Element;
oncreate(vnode: Mithril.VnodeDOM<IButtonAttrs, this>): void;
/**
* Get the template for the button's content.
*/
protected getButtonContent(children: Mithril.Children): Mithril.ChildArray;
}

View File

@@ -1,30 +0,0 @@
/**
* The `Checkbox` component defines a checkbox input.
*
* ### Attrs
*
* - `state` Whether or not the checkbox is checked.
* - `className` The class name for the root element.
* - `disabled` Whether or not the checkbox is disabled.
* - `loading` Whether or not the checkbox is loading.
* - `onchange` A callback to run when the checkbox is checked/unchecked.
* - `children` A text label to display next to the checkbox.
*/
export default class Checkbox extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
/**
* Get the template for the checkbox's display (tick/cross icon).
*
* @return {*}
* @protected
*/
protected getDisplay(): any;
/**
* Run a callback when the state of the checkbox is changed.
*
* @param {Boolean} checked
* @protected
*/
protected onchange(checked: boolean): void;
}
import Component from "../Component";

View File

@@ -1,22 +0,0 @@
/**
* The `ConfirmDocumentUnload` component can be used to register a global
* event handler that prevents closing the browser window/tab based on the
* return value of a given callback prop.
*
* ### Attrs
*
* - `when` - a callback returning true when the browser should prompt for
* confirmation before closing the window/tab
*
* ### Children
*
* NOTE: Only the first child will be rendered. (Use this component to wrap
* another component / DOM element.)
*
*/
export default class ConfirmDocumentUnload extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
handler(): any;
boundHandler: (() => any) | undefined;
}
import Component from "../Component";

View File

@@ -1,38 +0,0 @@
/**
* The `Dropdown` component displays a button which, when clicked, shows a
* dropdown menu beneath it.
*
* ### Attrs
*
* - `buttonClassName` A class name to apply to the dropdown toggle button.
* - `menuClassName` A class name to apply to the dropdown menu.
* - `icon` The name of an icon to show in the dropdown toggle button.
* - `caretIcon` The name of an icon to show on the right of the button.
* - `label` The label of the dropdown toggle button. Defaults to 'Controls'.
* - `accessibleToggleLabel` The label used to describe the dropdown toggle button to assistive readers. Defaults to 'Toggle dropdown menu'.
* - `onhide`
* - `onshow`
*
* The children will be displayed as a list inside of the dropdown menu.
*/
export default class Dropdown extends Component<import("../Component").ComponentAttrs, undefined> {
static initAttrs(attrs: any): void;
constructor();
showing: boolean | undefined;
/**
* Get the template for the button.
*
* @return {*}
* @protected
*/
protected getButton(children: any): any;
/**
* Get the template for the button's content.
*
* @return {*}
* @protected
*/
protected getButtonContent(children: any): any;
getMenu(items: any): JSX.Element;
}
import Component from "../Component";

View File

@@ -1,25 +0,0 @@
/**
* The `EditUserModal` component displays a modal dialog with a login form.
*/
export default class EditUserModal extends Modal {
username: Stream<any> | undefined;
email: Stream<any> | undefined;
isEmailConfirmed: Stream<any> | undefined;
setPassword: Stream<boolean> | undefined;
password: Stream<any> | undefined;
groups: {} | undefined;
fields(): ItemList;
activate(): void;
data(): {
relationships: {};
};
nonAdminEditingAdmin(): any;
/**
* @internal
* @protected
*/
protected userIsAdmin(user: any): any;
}
import Modal from "./Modal";
import Stream from "../utils/Stream";
import ItemList from "../utils/ItemList";

View File

@@ -1,13 +0,0 @@
/**
* The `FieldSet` component defines a collection of fields, displayed in a list
* underneath a title. Accepted properties are:
*
* - `className` The class name for the fieldset.
* - `label` The title of this group of fields.
*
* The children should be an array of items to show in the fieldset.
*/
export default class FieldSet extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
}
import Component from "../Component";

View File

@@ -1,4 +0,0 @@
export default class GroupBadge extends Badge {
static initAttrs(attrs: any): void;
}
import Badge from "./Badge";

View File

@@ -1,12 +0,0 @@
/**
* The link component enables both internal and external links.
* It will return a regular HTML link for any links to external sites,
* and it will use Mithril's m.route.Link for any internal links.
*
* Links will default to internal; the 'external' attr must be set to
* `true` for the link to be external.
*/
export default class Link extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
}
import Component from "../Component";

View File

@@ -1,25 +0,0 @@
/**
* The `LinkButton` component defines a `Button` which links to a route.
*
* ### Attrs
*
* All of the attrs accepted by `Button`, plus:
*
* - `active` Whether or not the page that this button links to is currently
* active.
* - `href` The URL to link to. If the current URL `m.route()` matches this,
* the `active` prop will automatically be set to true.
* - `force` Whether the page should be fully rerendered. Defaults to `true`.
*/
export default class LinkButton extends Button<import("./Button").IButtonAttrs> {
static initAttrs(attrs: any): void;
/**
* Determine whether a component with the given attrs is 'active'.
*
* @param {Object} attrs
* @return {Boolean}
*/
static isActive(attrs: Object): boolean;
constructor();
}
import Button from "./Button";

View File

@@ -1,56 +0,0 @@
/// <reference types="mithril" />
import Component, { ComponentAttrs } from '../Component';
export interface LoadingIndicatorAttrs extends ComponentAttrs {
/**
* Custom classes for the loading indicator's container.
*/
className?: string;
/**
* Custom classes for the loading indicator's container.
*/
containerClassName?: string;
/**
* Optional size for the loading indicator.
*/
size?: 'large' | 'medium' | 'small';
/**
* Optional attributes to apply to the loading indicator's container.
*/
containerAttrs?: Partial<ComponentAttrs>;
/**
* Display type of the spinner.
*
* @default 'block'
*/
display?: 'block' | 'inline' | 'unset';
}
/**
* The `LoadingIndicator` component displays a simple CSS-based loading spinner.
*
* To set a custom color, use the CSS `color` property.
*
* To increase spacing around the spinner, use the CSS `height` property on the
* spinner's **container**. Setting the `display` attribute to `block` will set
* a height of `100px` by default.
*
* To apply a custom size to the loading indicator, set the `--size` and
* `--thickness` CSS custom properties on the loading indicator container.
*
* If you *really* want to change how this looks as part of your custom theme,
* you can override the `border-radius` and `border` then set either a
* background image, or use `content: "\<glyph>"` (e.g. `content: "\f1ce"`)
* and `font-family: 'Font Awesome 5 Free'` to set an FA icon if you'd rather.
*
* ### Attrs
*
* - `containerClassName` Class name(s) to apply to the indicator's parent
* - `className` Class name(s) to apply to the indicator itself
* - `display` Determines how the spinner should be displayed (`inline`, `block` (default) or `unset`)
* - `size` Size of the loading indicator (`small`, `medium` or `large`)
* - `containerAttrs` Optional attrs to be applied to the container DOM element
*
* All other attrs will be assigned as attributes on the DOM element.
*/
export default class LoadingIndicator extends Component<LoadingIndicatorAttrs> {
view(): JSX.Element;
}

View File

@@ -1,67 +0,0 @@
/**
* The `Modal` component displays a modal dialog, wrapped in a form. Subclasses
* should implement the `className`, `title`, and `content` methods.
*
* @abstract
*/
export default class Modal extends Component<import("../Component").ComponentAttrs, undefined> {
/**
* Determine whether or not the modal should be dismissible via an 'x' button.
*/
static isDismissible: boolean;
constructor();
/**
* Attributes for an alert component to show below the header.
*
* @type {object}
*/
alertAttrs: object;
/**
* Get the class name to apply to the modal.
*
* @return {String}
* @abstract
*/
className(): string;
/**
* Get the title of the modal dialog.
*
* @return {String}
* @abstract
*/
title(): string;
/**
* Get the content of the modal.
*
* @return {VirtualElement}
* @abstract
*/
content(): any;
/**
* Handle the modal form's submit event.
*
* @param {Event} e
*/
onsubmit(): void;
/**
* Focus on the first input when the modal is ready to be used.
*/
onready(): void;
/**
* Hide the modal.
*/
hide(): void;
/**
* Stop loading.
*/
loaded(): void;
loading: boolean | undefined;
/**
* Show an alert describing an error returned from the API, and give focus to
* the first relevant field.
*
* @param {RequestError} error
*/
onerror(error: any): void;
}
import Component from "../Component";

View File

@@ -1,11 +0,0 @@
/**
* The `ModalManager` component manages a modal dialog. Only one modal dialog
* can be shown at once; loading a new component into the ModalManager will
* overwrite the previous one.
*/
export default class ModalManager extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
animateShow(readyCallback: any): void;
animateHide(): void;
}
import Component from "../Component";

View File

@@ -1,40 +0,0 @@
/**
* The `Navigation` component displays a set of navigation buttons. Typically
* this is just a back button which pops the app's History. If the user is on
* the root page and there is no history to pop, then in some instances it may
* show a button that toggles the app's drawer.
*
* If the app has a pane, it will also include a 'pin' button which toggles the
* pinned state of the pane.
*
* Accepts the following attrs:
*
* - `className` The name of a class to set on the root element.
* - `drawer` Whether or not to show a button to toggle the app's drawer if
* there is no more history to pop.
*/
export default class Navigation extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
/**
* Get the back button.
*
* @return {Object}
* @protected
*/
protected getBackButton(): Object;
/**
* Get the pane pinned toggle button.
*
* @return {Object|String}
* @protected
*/
protected getPaneButton(): Object | string;
/**
* Get the drawer toggle button.
*
* @return {Object|String}
* @protected
*/
protected getDrawerButton(): Object | string;
}
import Component from "../Component";

View File

@@ -1,15 +0,0 @@
import Component from '../Component';
export interface IPageAttrs {
key?: number;
routeName: string;
}
/**
* The `Page` component
*
* @abstract
*/
export default abstract class Page<CustomAttrs extends IPageAttrs = IPageAttrs> extends Component<CustomAttrs> {
oninit(vnode: any): void;
oncreate(vnode: any): void;
onremove(vnode: any): void;
}

View File

@@ -1,12 +0,0 @@
/**
* The `Placeholder` component displays a muted text with some call to action,
* usually used as an empty state.
*
* ### Attrs
*
* - `text`
*/
export default class Placeholder extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
}
import Component from "../Component";

View File

@@ -1,3 +0,0 @@
export default class RequestErrorModal extends Modal {
}
import Modal from "./Modal";

View File

@@ -1,16 +0,0 @@
/**
* The `Select` component displays a <select> input, surrounded with some extra
* elements for styling. It accepts the following attrs:
*
* - `options` A map of option values to labels.
* - `onchange` A callback to run when the selected value is changed.
* - `value` The value of the selected option.
* - `disabled` Disabled state for the input.
* - `wrapperAttrs` A map of attrs to be passed to the DOM element wrapping the `<select>`
*
* Other attributes are passed directly to the `<select>` element rendered to the DOM.
*/
export default class Select extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
}
import Component from "../Component";

View File

@@ -1,13 +0,0 @@
/**
* The `SelectDropdown` component is the same as a `Dropdown`, except the toggle
* button's label is set as the label of the first child which has a truthy
* `active` prop.
*
* ### Attrs
*
* - `caretIcon`
* - `defaultLabel`
*/
export default class SelectDropdown extends Dropdown {
}
import Dropdown from "./Dropdown";

View File

@@ -1,11 +0,0 @@
export default Separator;
/**
* The `Separator` component defines a menu separator item.
*/
declare class Separator extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
}
declare namespace Separator {
const isListItem: boolean;
}
import Component from "../Component";

View File

@@ -1,15 +0,0 @@
/**
* The `SplitDropdown` component is similar to `Dropdown`, but the first child
* is displayed as its own button prior to the toggle button.
*/
export default class SplitDropdown extends Dropdown {
/**
* Get the first child. If the first child is an array, the first item in that
* array will be returned.
*
* @return {*}
* @protected
*/
protected getFirstChild(children: any): any;
}
import Dropdown from "./Dropdown";

View File

@@ -1,8 +0,0 @@
/**
* The `Switch` component is a `Checkbox`, but with a switch display instead of
* a tick/cross one.
*/
export default class Switch extends Checkbox {
static initAttrs(attrs: any): void;
}
import Checkbox from "./Checkbox";

View File

@@ -1,61 +0,0 @@
/**
* The `TextEditor` component displays a textarea with controls, including a
* submit button.
*
* ### Attrs
*
* - `composer`
* - `submitLabel`
* - `value`
* - `placeholder`
* - `disabled`
* - `preview`
*/
export default class TextEditor extends Component<import("../Component").ComponentAttrs, undefined> {
constructor();
/**
* The value of the editor.
*
* @type {String}
*/
value: string | undefined;
/**
* Whether the editor is disabled.
*/
disabled: any;
buildEditorParams(): {
classNames: string[];
disabled: any;
placeholder: any;
value: string | undefined;
oninput: (value: string) => void;
inputListeners: never[];
onsubmit: () => void;
};
buildEditor(dom: any): BasicEditorDriver;
/**
* Build an item list for the text editor controls.
*
* @return {ItemList}
*/
controlItems(): ItemList;
/**
* Build an item list for the toolbar controls.
*
* @return {ItemList}
*/
toolbarItems(): ItemList;
/**
* Handle input into the textarea.
*
* @param {String} value
*/
oninput(value: string): void;
/**
* Handle the submit button being clicked.
*/
onsubmit(): void;
}
import Component from "../Component";
import BasicEditorDriver from "../utils/BasicEditorDriver";
import ItemList from "../utils/ItemList";

View File

@@ -1,14 +0,0 @@
/**
* The `TextEditorButton` component displays a button suitable for the text
* editor toolbar.
*
* Automatically creates tooltips using the Tooltip component and provided text.
*
* ## Attrs
* - `title` - Tooltip for the button
*/
export default class TextEditorButton extends Button<import("./Button").IButtonAttrs> {
static initAttrs(attrs: any): void;
constructor();
}
import Button from "./Button";

View File

@@ -1,116 +0,0 @@
import Component from '../Component';
import type Mithril from 'mithril';
export interface TooltipAttrs extends Mithril.CommonAttributes<TooltipAttrs, Tooltip> {
/**
* Tooltip textual content.
*
* String arrays, like those provided by the translator, will be flattened
* into strings.
*/
text: string | string[];
/**
* Manually show tooltip. `false` will show based on cursor events.
*
* Default: `false`.
*/
tooltipVisible?: boolean;
/**
* Whether to show on focus.
*
* Default: `true`.
*/
showOnFocus?: boolean;
/**
* Tooltip position around element.
*
* Default: `'top'`.
*/
position?: 'top' | 'bottom' | 'left' | 'right';
/**
* Whether HTML content is allowed in the tooltip.
*
* **Warning:** this is a possible XSS attack vector. This option shouldn't
* be used wherever possible, and may not work when we migrate to another
* tooltip library. Be prepared for this to break in Flarum stable.
*
* Default: `false`.
*
* @deprecated
*/
html?: boolean;
/**
* Sets the delay between a trigger state occurring and the tooltip appearing
* on-screen.
*
* **Warning:** this option may be removed when switching to another tooltip
* library. Be prepared for this to break in Flarum stable.
*
* Default: `0`.
*
* @deprecated
*/
delay?: number;
/**
* Used to disable the warning for passing text to the `title` attribute.
*
* Tooltip text should be passed to the `text` attribute.
*/
ignoreTitleWarning?: boolean;
}
/**
* The `Tooltip` component is used to create a tooltip for an element. It
* requires a single child element to be passed to it. Passing multiple
* children or fragments will throw an error.
*
* You should use this for any tooltips you create to allow for backwards
* compatibility when we switch to another tooltip library instead of
* Bootstrap tooltips.
*
* If you need to pass multiple children, surround them with another element,
* such as a `<span>` or `<div>`.
*
* **Note:** this component will overwrite the `title` attribute of the first
* child you pass to it, as this is how the current tooltip system works in
* Flarum. This shouldn't be an issue if you're using this component correctly.
*
* @example <caption>Basic usage</caption>
* <Tooltip text="You wish!">
* <Button>
* Click for free money!
* </Button>
* </Tooltip>
*
* @example <caption>Use of `position` and `showOnFocus` attrs</caption>
* <Tooltip text="Woah! That's cool!" position="bottom" showOnFocus>
* <span>3 replies</span>
* </Tooltip>
*
* @example <caption>Incorrect usage</caption>
* // This is wrong! Surround the children with a <span> or similar.
* <Tooltip text="This won't work">
* Click
* <a href="/">here</a>
* </Tooltip>
*/
export default class Tooltip extends Component<TooltipAttrs> {
private firstChild;
private childDomNode;
private oldText;
private oldVisibility;
private shouldRecreateTooltip;
private shouldChangeTooltipVisibility;
view(vnode: Mithril.Vnode<TooltipAttrs, this>): Mithril.ChildArray;
oncreate(vnode: Mithril.VnodeDOM<TooltipAttrs, this>): void;
onupdate(vnode: Mithril.VnodeDOM<TooltipAttrs, this>): void;
private recreateTooltip;
private updateVisibility;
private createTooltip;
private getRealText;
/**
* Checks if the tooltip DOM node has changed.
*
* If it has, it updates `this.childDomNode` to the new node, and sets
* `shouldRecreateTooltip` to `true`.
*/
private checkDomNodeChanged;
}

View File

@@ -1,54 +0,0 @@
/**
* Extend an object's method by running its output through a mutating callback
* every time it is called.
*
* The callback accepts the method's return value and should perform any
* mutations directly on this value. For this reason, this function will not be
* effective on methods which return scalar values (numbers, strings, booleans).
*
* Care should be taken to extend the correct object in most cases, a class'
* prototype will be the desired target of extension, not the class itself.
*
* @example <caption>Example usage of extending one method.</caption>
* extend(Discussion.prototype, 'badges', function(badges) {
* // do something with `badges`
* });
*
* @example <caption>Example usage of extending multiple methods.</caption>
* extend(IndexPage.prototype, ['oncreate', 'onupdate'], function(vnode) {
* // something that needs to be run on creation and update
* });
*
* @param {object} object The object that owns the method
* @param {string|string[]} methods The name or names of the method(s) to extend
* @param {function} callback A callback which mutates the method's output
*/
export function extend(object: object, methods: string | string[], callback: Function): void;
/**
* Override an object's method by replacing it with a new function, so that the
* new function will be run every time the object's method is called.
*
* The replacement function accepts the original method as its first argument,
* which is like a call to `super`. Any arguments passed to the original method
* are also passed to the replacement.
*
* Care should be taken to extend the correct object in most cases, a class'
* prototype will be the desired target of extension, not the class itself.
*
* @example <caption>Example usage of overriding one method.</caption>
* override(Discussion.prototype, 'badges', function(original) {
* const badges = original();
* // do something with badges
* return badges;
* });
*
* @example <caption>Example usage of overriding multiple methods.</caption>
* extend(Discussion.prototype, ['oncreate', 'onupdate'], function(original, vnode) {
* // something that needs to be run on creation and update
* });
*
* @param {object} object The object that owns the method
* @param {string|string[]} method The name or names of the method(s) to override
* @param {function} newMethod The method to replace it with
*/
export function override(object: object, methods: any, newMethod: Function): void;

View File

@@ -1,12 +0,0 @@
export default class Model {
constructor(type: any, model?: any);
type: any;
attributes: any[];
hasOnes: any[];
hasManys: any[];
model: any;
attribute(name: any): Model;
hasOne(type: any): Model;
hasMany(type: any): Model;
extend(app: any, extension: any): void;
}

View File

@@ -1,5 +0,0 @@
export default class PostTypes {
postComponents: {};
add(name: any, component: any): PostTypes;
extend(app: any, extension: any): void;
}

View File

@@ -1,5 +0,0 @@
export default class Routes {
routes: {};
add(name: any, path: any, component: any): Routes;
extend(app: any, extension: any): void;
}

Some files were not shown because too many files have changed in this diff Show More