fix: username color in md mention
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Baoshuo Ren 2023-01-15 11:13:43 +08:00
parent be7510a6bb
commit 6548c2e2b7
Signed by: baoshuo
GPG Key ID: 00CB9680AB29F51A
11 changed files with 78 additions and 108 deletions

View File

@ -49,7 +49,7 @@ UOJGroup::cur()->userCanView(Auth::user(), ['ensure' => true]);
</h2> </h2>
<?php if (UOJGroup::info('announcement')) : ?> <?php if (UOJGroup::info('announcement')) : ?>
<div class="text-break"> <div class="text-break">
<?= HTML::purifier_inline()->purify(HTML::parsedown()->line(UOJGroup::info('announcement'))) ?> <?= HTML::purifier_inline()->purify(HTML::parsedown(['username_with_color' => true])->line(UOJGroup::info('announcement'))) ?>
</div> </div>
<?php else : ?> <?php else : ?>
<div class="text-muted"> <div class="text-muted">

View File

@ -32,7 +32,7 @@ $header_row .= '<th style="width:35em">' . UOJLocale::get('contests::problem sel
$header_row .= '<th style="width:35em">' . UOJLocale::get('contests::contest self review') . '</th>'; $header_row .= '<th style="width:35em">' . UOJLocale::get('contests::contest self review') . '</th>';
$header_row .= '</tr>'; $header_row .= '</tr>';
$parsedown = HTML::parsedown(); $parsedown = HTML::parsedown(['username_with_color' => true]);
$purifier = HTML::purifier_inline(); $purifier = HTML::purifier_inline();
$print_row = function ($row) use ($parsedown, $purifier) { $print_row = function ($row) use ($parsedown, $purifier) {

View File

@ -1009,62 +1009,6 @@ function echoUOJPageFooter($config = array()) {
uojIncludeView('page-footer', $config); uojIncludeView('page-footer', $config);
} }
function echoRanklist($config = []) {
$header_row = '';
$header_row .= '<tr>';
$header_row .= '<th style="width: 5em;">#</th>';
$header_row .= '<th style="width: 14em;">' . UOJLocale::get('username') . '</th>';
$header_row .= '<th style="width: 50em;">' . UOJLocale::get('motto') . '</th>';
$header_row .= '<th style="width: 5em;">' . UOJLocale::get('solved') . '</th>';
$header_row .= '</tr>';
$parsedown = HTML::parsedown();
$purifier = HTML::purifier_inline();
$users = [];
$print_row = function ($user, $now_cnt) use (&$users, $config, $purifier, $parsedown) {
if (!$users) {
if ($now_cnt == 1) {
$rank = 1;
} else {
$rank = DB::selectCount("select count(*) from (select b.username as username, count(*) as accepted from best_ac_submissions a inner join user_info b on a.submitter = b.username group by username) as derived where accepted > {$user['ac_num']}") + 1;
}
} else {
$rank = $now_cnt;
}
$user['rank'] = $rank;
echo '<tr>';
echo '<td>' . $user['rank'] . '</td>';
echo '<td>' . UOJUser::getLink($user['username']) . '</td>';
echo "<td>";
echo $purifier->purify($parsedown->line($user['motto']));
echo "</td>";
echo '<td>' . $user['ac_num'] . '</td>';
echo '</tr>';
$users[] = $user;
};
$from = 'user_info';
$col_names = ['user_info.username as username', 'ac_num', 'motto'];
$cond = '1';
$tail = 'group by user_info.username order by ac_num desc, user_info.username asc';
if (isset($config['group_id'])) {
$group_id = $config['group_id'];
$from = "user_info inner join groups_users on (user_info.username = groups_users.username and groups_users.group_id = {$group_id})";
$config['pagination_cond'] = "group_id = {$group_id}";
}
if (isset($config['top10'])) {
$tail .= ' limit 10';
}
$config['get_row_index'] = '';
echoLongTable($col_names, $from, $cond, $tail, $header_row, $print_row, $config);
}
// ===== uoj.ac ===== // ===== uoj.ac =====
function echoJudgmentDetails($raw_details, $styler, $name) { function echoJudgmentDetails($raw_details, $styler, $name) {

View File

@ -436,7 +436,11 @@ class HTML {
$def->addElement('footer', 'Block', 'Flow', 'Common'); $def->addElement('footer', 'Block', 'Flow', 'Common');
$extra_allowed_html = [ $extra_allowed_html = [
'span' => ['data-realname' => 'Text', 'data-uoj-username' => 'Number'], 'span' => [
'class' => 'Enum#uoj-username',
'data-realname' => 'Text',
'data-color' => 'Color',
],
'img' => ['width' => 'Text'], 'img' => ['width' => 'Text'],
]; ];
@ -463,7 +467,11 @@ class HTML {
'small' => [], 'small' => [],
'del' => [], 'del' => [],
'br' => [], 'br' => [],
'span' => ['data-realname' => 'Text', 'data-uoj-username' => 'Number'], 'span' => [
'class' => 'Enum#uoj-username',
'data-realname' => 'Text',
'data-color' => 'Color',
],
]; ];
$allowed_elements = []; $allowed_elements = [];
@ -490,8 +498,8 @@ class HTML {
return new HTMLPurifier($config); return new HTMLPurifier($config);
} }
public static function parsedown() { public static function parsedown($config = []) {
return new UOJMarkdown([ return new UOJMarkdown($config + [
'math' => [ 'math' => [
'enabled' => true, 'enabled' => true,
'matchSingleDollar' => true 'matchSingleDollar' => true

View File

@ -1,10 +1,12 @@
<?php <?php
class UOJMarkdown extends ParsedownMath { class UOJMarkdown extends ParsedownMath {
public function __construct($options = '') { public function __construct($options = '') {
if (method_exists(get_parent_class(),"__construct")) { if (method_exists(get_parent_class(), "__construct")) {
parent::__construct($options); parent::__construct($options);
} }
$this->options['username_with_color'] = $options['username_with_color'] ?: false;
// https://gist.github.com/ShNURoK42/b5ce8baa570975db487c // https://gist.github.com/ShNURoK42/b5ce8baa570975db487c
$this->InlineTypes['@'][] = 'UserMention'; $this->InlineTypes['@'][] = 'UserMention';
$this->inlineMarkerList .= '@'; $this->inlineMarkerList .= '@';
@ -54,16 +56,24 @@ class UOJMarkdown extends ParsedownMath {
// https://gist.github.com/ShNURoK42/b5ce8baa570975db487c // https://gist.github.com/ShNURoK42/b5ce8baa570975db487c
protected function inlineUserMention($Excerpt) { protected function inlineUserMention($Excerpt) {
if (preg_match('/^@([^\s]+)/', $Excerpt['text'], $matches)) { if (preg_match('/^@([^\s]+)/', $Excerpt['text'], $matches)) {
if (($user = UOJUser::query($matches[1])) && $user['usergroup'] != 'B') { $mentioned_user = UOJUser::query($matches[1]);
if ($mentioned_user) {
$color = '#0d6efd';
if ($this->options['username_with_color']) {
$color = UOJUser::getUserColor($mentioned_user);
}
return [ return [
'extent' => strlen($matches[0]), 'extent' => strlen($matches[0]),
'element' => [ 'element' => [
'name' => 'span', 'name' => 'span',
'text' => '@' . $user['username'], 'text' => '@' . $mentioned_user['username'],
'attributes' => [ 'attributes' => [
'class' => 'uoj-username', 'class' => 'uoj-username',
'data-realname' => $user['realname'], 'data-realname' => UOJUser::getRealname($mentioned_user),
'data-uoj-username' => 1, 'data-color' => $color,
], ],
], ],
]; ];

View File

@ -22,7 +22,7 @@ class UOJRanklist {
} }
$last_user = null; $last_user = null;
$parsedown = HTML::parsedown(); $parsedown = HTML::parsedown(['username_with_color' => true]);
$purifier = HTML::purifier_inline(); $purifier = HTML::purifier_inline();
$print_row = function ($user, $now_cnt) use (&$last_user, &$conds, &$parsedown, &$purifier) { $print_row = function ($user, $now_cnt) use (&$last_user, &$conds, &$parsedown, &$purifier) {
if ($last_user === null) { if ($last_user === null) {
@ -138,7 +138,7 @@ class UOJRanklist {
$header_row .= '</tr>'; $header_row .= '</tr>';
$last_user = null; $last_user = null;
$parsedown = HTML::parsedown(); $parsedown = HTML::parsedown(['username_with_color' => true]);
$purifier = HTML::purifier_inline(); $purifier = HTML::purifier_inline();
$print_row = function ($user, $now_cnt) use (&$last_user, &$conds, &$parsedown, &$purifier) { $print_row = function ($user, $now_cnt) use (&$last_user, &$conds, &$parsedown, &$purifier) {
if ($last_user === null) { if ($last_user === null) {

View File

@ -210,6 +210,16 @@ class UOJUser {
} }
} }
public static function getRealname($user) {
$realname = $user['realname'];
if ($user['usertype'] == 'teacher') {
$realname .= '老师';
}
return $realname;
}
public static function getUserColor($user) { public static function getUserColor($user) {
$extra = UOJUser::getExtra($user); $extra = UOJUser::getExtra($user);
@ -248,12 +258,9 @@ class UOJUser {
} }
} }
$realname = $user['realname']; $realname = UOJUser::getRealname($user);
if ($user['usertype'] == 'teacher') {
$realname .= '老师';
}
// 未登录不可查看真实姓名
if (!Auth::check()) { if (!Auth::check()) {
$realname = ''; $realname = '';
} }
@ -261,7 +268,6 @@ class UOJUser {
return HTML::tag('span', [ return HTML::tag('span', [
'class' => 'uoj-username', 'class' => 'uoj-username',
'data-color' => UOJUser::getUserColor($user), 'data-color' => UOJUser::getUserColor($user),
// 未登录不可查看真实姓名
'data-realname' => trim(HTML::escape($realname)), 'data-realname' => trim(HTML::escape($realname)),
], $user['username']); ], $user['username']);
} }

View File

@ -19,6 +19,8 @@ class Parsedown
const version = '1.7.4'; const version = '1.7.4';
protected $options = [];
# ~ # ~
function text($text) function text($text)

View File

@ -1,7 +1,7 @@
<?php <?php
$reviews = []; $reviews = [];
$parsedown = HTML::parsedown(); $parsedown = HTML::parsedown(['username_with_color' => true]);
$purifier = HTML::purifier_inline(); $purifier = HTML::purifier_inline();
foreach ($contest_data['people'] as $person) { foreach ($contest_data['people'] as $person) {

View File

@ -1,6 +1,6 @@
<?php <?php
$purifier = HTML::purifier_inline(); $purifier = HTML::purifier_inline();
$parsedown = HTML::parsedown(); $parsedown = HTML::parsedown(['username_with_color' => true]);
?> ?>
<?php if (Auth::check()) : ?> <?php if (Auth::check()) : ?>

View File

@ -21,7 +21,7 @@
</span> </span>
</h3> </h3>
<div class="card-text"> <div class="card-text">
<?= HTML::purifier_inline()->purify(HTML::parsedown()->line($user['motto'])) ?> <?= HTML::purifier_inline()->purify(HTML::parsedown(['username_with_color' => true])->line($user['motto'])) ?>
</div> </div>
</div> </div>
<ul class="list-group list-group-flush"> <ul class="list-group list-group-flush">