Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add TextFormatter support (attempt 2) #48

Merged
merged 11 commits into from
Jun 25, 2023
33 changes: 21 additions & 12 deletions extend.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,41 @@
namespace FoF\UserBio;

use Flarum\Api\Serializer\UserSerializer;
use Flarum\Extend;
use Flarum\Extend as Flarum;
use Flarum\Settings\Event\Saved;
use Flarum\User\Event\Saving;
use Flarum\User\User;
use FoF\UserBio\Listeners\AddUserBioAttribute;
use FoF\UserBio\Listeners\SaveUserBio;
use s9e\TextFormatter\Configurator;

return [
(new Extend\Frontend('forum'))
(new Flarum\Frontend('forum'))
->js(__DIR__.'/js/dist/forum.js')
->css(__DIR__.'/resources/less/forum.less'),

(new Extend\Frontend('admin'))
(new Flarum\Frontend('admin'))
->js(__DIR__.'/js/dist/admin.js'),

new Extend\Locales(__DIR__.'/resources/locale'),
new Flarum\Locales(__DIR__.'/resources/locale'),

(new Extend\Event())
->listen(Saving::class, SaveUserBio::class),
(new Flarum\Event())
->listen(Saving::class, Listeners\SaveUserBio::class)
->listen(Saved::class, Listeners\ClearFormatterCache::class),

(new Extend\ApiSerializer(UserSerializer::class))
->attributes(AddUserBioAttribute::class),
(new Flarum\ApiSerializer(UserSerializer::class))
->attributes(Listeners\AddUserBioAttribute::class),

(new Extend\Policy())
(new Flarum\Policy())
->modelPolicy(User::class, Access\UserPolicy::class),

(new Extend\Settings())
(new Flarum\Settings())
->serializeToForum('fof-user-bio.maxLength', 'fof-user-bio.maxLength', 'intVal')
->default('fof-user-bio.maxLength', 200),

(new Flarum\ServiceProvider())
->register(Formatter\FormatterServiceProvider::class),

(new Extend\Formatter())
->configure(function (Configurator $configurator) {
$configurator->Censor->add('test');
}),
];
1,015 changes: 433 additions & 582 deletions js/package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
"name": "@fof/user-bio",
"prettier": "@flarum/prettier-config",
"dependencies": {
"autolink-js": "1.0.2",
"@flarum/prettier-config": "^1.0.0",
"autolink-js": "1.0.2",
"flarum-tsconfig": "^1.0.2",
"flarum-webpack-config": "^2.0.0",
"webpack": "^5.76.0",
"webpack-cli": "^4.9.2"
"flarum-webpack-config": "^2.0.2",
"webpack": "^5.88.0",
"webpack-cli": "^5.1.4"
},
"devDependencies": {
"prettier": "^2.6.2"
"prettier": "^2.8.8"
},
"scripts": {
"dev": "webpack --mode development --watch",
Expand Down
6 changes: 6 additions & 0 deletions js/src/admin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,11 @@ app.initializers.add('fof-user-bio', () => {
setting: 'fof-user-bio.maxLength',
type: 'number',
placeholder: 200,
})
.registerSetting({
label: app.translator.trans('fof-user-bio.admin.setting.allowFormatting'),
help: app.translator.trans('fof-user-bio.admin.setting.allowFormatting_help'),
setting: 'fof-user-bio.allowFormatting',
type: 'boolean',
});
});
8 changes: 7 additions & 1 deletion js/src/forum/components/UserBio.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,18 @@ export default class UserBio extends Component {
let subContent;

if (this.loading) {
subContent = <p className="UserBio-placeholder">{LoadingIndicator.component({ size: 'tiny' })}</p>;
subContent = (
<p className="UserBio-placeholder">
<LoadingIndicator />
</p>
);
} else {
const bioHtml = user.bioHtml();

if (bioHtml) {
subContent = m.trust(bioHtml);
} else if (user.bio()) {
subContent = m.trust('<p>' + $('<div/>').text(user.bio()).html().replace(/\n/g, '<br>').autoLink({ rel: 'nofollow ugc' }) + '</p>');
} else if (editable) {
subContent = <p className="UserBio-placeholder">{this.bioPlaceholder}</p>;
}
Expand Down
4 changes: 1 addition & 3 deletions js/src/forum/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ export * from './components';

app.initializers.add('fof-user-bio', () => {
User.prototype.bio = Model.attribute('bio');
User.prototype.bioHtml = computed('bio', (bio) =>
bio ? '<p>' + $('<div/>').text(bio).html().replace(/\n/g, '<br>').autoLink({ rel: 'nofollow ugc' }) + '</p>' : ''
);
User.prototype.bioHtml = Model.attribute('bioHtml');

extend(UserCard.prototype, 'infoItems', function (items) {
let user = this.attrs.user;
Expand Down
5 changes: 5 additions & 0 deletions resources/less/forum.less
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@
font-size: 14px;
resize: none;
}

.LoadingIndicator-container {
color: white;
height: 50px;
}
}

.UserBio-content {
Expand Down
2 changes: 2 additions & 0 deletions resources/locale/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ fof-user-bio:
editAny: Edit any bio
setting:
bioLimit: Bio character limit
allowFormatting: Allow formatting in bio
allowFormatting_help: By design, this formatting is separate from post formatting. If the BBCode and/or Markdown extensions are enabled, they will be available to format the bio. No images or embeds are allowed. Extensions that add to the Flarum formatter must *explicitly* add support for the bio formatter.

forum:
userbioPlaceholder: Write something about yourself
Expand Down
99 changes: 99 additions & 0 deletions src/Extend/Formatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php

/*
* This file is part of fof/user-bio.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FoF\UserBio\Extend;

use Flarum\Extend\Formatter as FlarumFormatter;
use Flarum\Extension\Extension;
use Flarum\Foundation\ContainerUtil;
use FoF\UserBio\Formatter\FormatterServiceProvider;
use Illuminate\Contracts\Container\Container;

class Formatter extends FlarumFormatter
{
protected $configurationCallbacks = [];
protected $parsingCallbacks = [];
protected $unparsingCallbacks = [];
protected $renderingCallbacks = [];

/**
* {@inheritdoc}
*/
public function configure($callback): FlarumFormatter
{
$this->configurationCallbacks[] = $callback;

return $this;
}

/**
* {@inheritdoc}
*/
public function parse($callback): FlarumFormatter
{
$this->parsingCallbacks[] = $callback;

return $this;
}

/**
* {@inheritdoc}
*/
public function unparse($callback): FlarumFormatter
{
$this->unparsingCallbacks[] = $callback;

return $this;
}

/**
* {@inheritdoc}
*/
public function render($callback): FlarumFormatter
{
$this->renderingCallbacks[] = $callback;

return $this;
}

public function onEnable(Container $container, Extension $extension)
{
FormatterServiceProvider::createFormatterInstance($container)->flush();
}

public function onDisable(Container $container, Extension $extension)
{
// do nothing
}

public function extend(Container $container, Extension $extension = null)
{
$container->extend('fof-user-bio.formatter', function ($formatter, $container) {
foreach ($this->configurationCallbacks as $callback) {
$formatter->addConfigurationCallback(ContainerUtil::wrapCallback($callback, $container));
}

foreach ($this->parsingCallbacks as $callback) {
$formatter->addParsingCallback(ContainerUtil::wrapCallback($callback, $container));
}

foreach ($this->unparsingCallbacks as $callback) {
$formatter->addUnparsingCallback(ContainerUtil::wrapCallback($callback, $container));
}

foreach ($this->renderingCallbacks as $callback) {
$formatter->addRenderingCallback(ContainerUtil::wrapCallback($callback, $container));
}

return $formatter;
});
}
}
39 changes: 39 additions & 0 deletions src/Formatter/FormatterServiceProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

/*
* This file is part of fof/user-bio.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FoF\UserBio\Formatter;

use Flarum\Extension\ExtensionManager;
use Flarum\Foundation\AbstractServiceProvider;
use Flarum\Foundation\Paths;
use Illuminate\Cache\Repository;
use Illuminate\Container\Container;

class FormatterServiceProvider extends AbstractServiceProvider
{
public function register(): void
{
$this->container->singleton('fof-user-bio.formatter', function (Container $container) {
return self::createFormatterInstance($container);
});

$this->container->alias('fof-user-bio.formatter', UserBioFormatter::class);
}

public static function createFormatterInstance(Container $container): UserBioFormatter
{
return new UserBioFormatter(
new Repository($container->make('cache.filestore')),
$container[Paths::class]->storage.'/formatter',
$container->make(ExtensionManager::class)
);
}
}
83 changes: 83 additions & 0 deletions src/Formatter/UserBioFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

/*
* This file is part of fof/user-bio.
*
* Copyright (c) FriendsOfFlarum.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace FoF\UserBio\Formatter;

use Flarum\Extension\ExtensionManager;
use Flarum\Formatter\Formatter;
use Illuminate\Cache\Repository;

class UserBioFormatter extends Formatter
{
/**
* @var ExtensionManager
*/
protected $extensions;

public function __construct(Repository $repository, string $cacheDir, ExtensionManager $extensions)
{
parent::__construct($repository, $cacheDir);

$this->extensions = $extensions;
}

/**
* {@inheritdoc}
*/
protected function getComponent($name)
{
$formatter = $this->cache->rememberForever('fof-user-bio.formatter', function () {
return $this->getConfigurator()->finalize();
});

return $formatter[$name];
}

/**
* {@inheritdoc}
*/
protected function getParser($context = null)
{
$parser = parent::getParser($context);

$parser->disableTag('IMG');
$parser->disableTag('IFRAME');
$parser->disableTag('EMBED');

return $parser;
}

/**
* {@inheritdoc}
*/
protected function getConfigurator()
{
$configurator = parent::getConfigurator();

if ($this->extensions->isEnabled('flarum-markdown')) {
$configurator->Litedown;
}

if ($this->extensions->isEnabled('flarum-bbcode')) {
(new \Flarum\BBCode\Configure())($configurator);
}

return $configurator;
}

/**
* {@inheritdoc}
*/
public function flush()
{
$this->cache->forget('fof-user-bio.formatter');
}
}