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>
<?php if (UOJGroup::info('announcement')) : ?>
<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>
<?php else : ?>
<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 .= '</tr>';
$parsedown = HTML::parsedown();
$parsedown = HTML::parsedown(['username_with_color' => true]);
$purifier = HTML::purifier_inline();
$print_row = function ($row) use ($parsedown, $purifier) {

View File

@ -1009,62 +1009,6 @@ function echoUOJPageFooter($config = array()) {
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 =====
function echoJudgmentDetails($raw_details, $styler, $name) {

View File

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

View File

@ -1,10 +1,12 @@
<?php
class UOJMarkdown extends ParsedownMath {
public function __construct($options = '') {
if (method_exists(get_parent_class(),"__construct")) {
if (method_exists(get_parent_class(), "__construct")) {
parent::__construct($options);
}
$this->options['username_with_color'] = $options['username_with_color'] ?: false;
// https://gist.github.com/ShNURoK42/b5ce8baa570975db487c
$this->InlineTypes['@'][] = 'UserMention';
$this->inlineMarkerList .= '@';
@ -19,18 +21,18 @@ class UOJMarkdown extends ParsedownMath {
}
// https://github.com/taufik-nurrohman/parsedown-extra-plugin/blob/1653418c5a9cf5277cd28b0b23ba2d95d18e9bc4/ParsedownExtraPlugin.php#L347-L358
protected function doGetContent($Element) {
if (isset($Element['text'])) {
return $Element['text'];
}
if (isset($Element['rawHtml'])) {
return $Element['rawHtml'];
}
if (isset($Element['handler']['argument'])) {
return implode("\n", (array) $Element['handler']['argument']);
}
return null;
}
protected function doGetContent($Element) {
if (isset($Element['text'])) {
return $Element['text'];
}
if (isset($Element['rawHtml'])) {
return $Element['rawHtml'];
}
if (isset($Element['handler']['argument'])) {
return implode("\n", (array) $Element['handler']['argument']);
}
return null;
}
// https://github.com/taufik-nurrohman/parsedown-extra-plugin/blob/1653418c5a9cf5277cd28b0b23ba2d95d18e9bc4/ParsedownExtraPlugin.php#L369-L378
protected function doSetAttributes(&$Element, $From, $Args = array()) {
@ -52,27 +54,35 @@ class UOJMarkdown extends ParsedownMath {
}
// https://gist.github.com/ShNURoK42/b5ce8baa570975db487c
protected function inlineUserMention($Excerpt) {
if (preg_match('/^@([^\s]+)/', $Excerpt['text'], $matches)) {
if (($user = UOJUser::query($matches[1])) && $user['usergroup'] != 'B') {
return [
'extent' => strlen($matches[0]),
'element' => [
'name' => 'span',
'text' => '@' . $user['username'],
'attributes' => [
'class' => 'uoj-username',
'data-realname' => $user['realname'],
'data-uoj-username' => 1,
],
],
];
}
protected function inlineUserMention($Excerpt) {
if (preg_match('/^@([^\s]+)/', $Excerpt['text'], $matches)) {
$mentioned_user = UOJUser::query($matches[1]);
return [
'extent' => strlen($matches[0]),
'markup' => $matches[0],
];
}
}
if ($mentioned_user) {
$color = '#0d6efd';
if ($this->options['username_with_color']) {
$color = UOJUser::getUserColor($mentioned_user);
}
return [
'extent' => strlen($matches[0]),
'element' => [
'name' => 'span',
'text' => '@' . $mentioned_user['username'],
'attributes' => [
'class' => 'uoj-username',
'data-realname' => UOJUser::getRealname($mentioned_user),
'data-color' => $color,
],
],
];
}
return [
'extent' => strlen($matches[0]),
'markup' => $matches[0],
];
}
}
}

View File

@ -22,7 +22,7 @@ class UOJRanklist {
}
$last_user = null;
$parsedown = HTML::parsedown();
$parsedown = HTML::parsedown(['username_with_color' => true]);
$purifier = HTML::purifier_inline();
$print_row = function ($user, $now_cnt) use (&$last_user, &$conds, &$parsedown, &$purifier) {
if ($last_user === null) {
@ -138,7 +138,7 @@ class UOJRanklist {
$header_row .= '</tr>';
$last_user = null;
$parsedown = HTML::parsedown();
$parsedown = HTML::parsedown(['username_with_color' => true]);
$purifier = HTML::purifier_inline();
$print_row = function ($user, $now_cnt) use (&$last_user, &$conds, &$parsedown, &$purifier) {
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) {
$extra = UOJUser::getExtra($user);
@ -248,12 +258,9 @@ class UOJUser {
}
}
$realname = $user['realname'];
if ($user['usertype'] == 'teacher') {
$realname .= '老师';
}
$realname = UOJUser::getRealname($user);
// 未登录不可查看真实姓名
if (!Auth::check()) {
$realname = '';
}
@ -261,7 +268,6 @@ class UOJUser {
return HTML::tag('span', [
'class' => 'uoj-username',
'data-color' => UOJUser::getUserColor($user),
// 未登录不可查看真实姓名
'data-realname' => trim(HTML::escape($realname)),
], $user['username']);
}

View File

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

View File

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

View File

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

View File

@ -21,7 +21,7 @@
</span>
</h3>
<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>
<ul class="list-group list-group-flush">