Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 158 additions & 36 deletions functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -2702,28 +2702,51 @@ function send_theme_version()

//解析短代码
function register_shortcodes() {
add_shortcode('task', function($attr, $content = '') {
return '<div class="task shortcodestyle"><i class="fa-solid fa-clipboard-list"></i>' . $content . '</div>';
});
// 提示块
function iro_render_notice($type, $content = '') {

$map = [
'task' => ['fa-solid fa-clipboard-list', 'task'],
'warning' => ['fa-solid fa-triangle-exclamation', 'warning'],
'noway' => ['fa-solid fa-square-xmark', 'noway'],
'buy' => ['fa-solid fa-square-check', 'buy'],
];

add_shortcode('warning', function($attr, $content = '') {
return '<div class="warning shortcodestyle"><i class="fa-solid fa-triangle-exclamation"></i>' . $content . '</div>';
});
if (!isset($map[$type])) {
return '';
}

add_shortcode('noway', function($attr, $content = '') {
return '<div class="noway shortcodestyle"><i class="fa-solid fa-square-xmark"></i>' . $content . '</div>';
});
[$icon, $class] = $map[$type];

add_shortcode('buy', function($attr, $content = '') {
return '<div class="buy shortcodestyle"><i class="fa-solid fa-square-check"></i>' . $content . '</div>';
});
return sprintf(
'<div class="shortcodestyle %s">
<i class="%s"></i>
<span>%s</span>
</div>',
esc_attr($class),
esc_attr($icon),
wp_kses_post($content)
);
}

add_shortcode('ghcard', function($attr, $content = '') {
//获取内容
$atts = shortcode_atts(array("path" => "mirai-mamori/Sakurairo"), $attr);
add_shortcode('task', fn($a,$c='') => iro_render_notice('task',$c));
add_shortcode('warning', fn($a,$c='') => iro_render_notice('warning',$c));
add_shortcode('noway', fn($a,$c='') => iro_render_notice('noway',$c));
add_shortcode('buy', fn($a,$c='') => iro_render_notice('buy',$c));

$path = trim($atts['path']);
register_block_type('sakurairo/notice', [
'render_callback' => 'iro_render_notice_block',
]);
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR changes block names from the previous sakurairo/*-block identifiers to new names like sakurairo/notice/sakurairo/showcard/sakurairo/conversation. Existing posts using the old block names will become "unsupported" unless the old block types remain registered (with deprecated/transforms or a server-side alias). Please add backward-compat registration/migration for the old block names.

Suggested change
]);
]);
// Backward compatibility for the old block name used in existing posts.
register_block_type('sakurairo/notice-block', [
'render_callback' => 'iro_render_notice_block',
]);

Copilot uses AI. Check for mistakes.
function iro_render_notice_block($attributes, $content) {

Comment on lines 2704 to +2741
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Several named functions (iro_render_notice, iro_render_notice_block, etc.) are declared inside register_shortcodes(). In PHP this can fatally error with "Cannot redeclare" if register_shortcodes() is invoked more than once in a request (e.g., if the init hook gets added twice or the function is called directly). Consider moving these helper functions to file scope or wrapping them with function_exists() guards.

Copilot uses AI. Check for mistakes.
$type = $attributes['type'] ?? 'task';
$text = $attributes['content'] ?? '';

return iro_render_notice($type, $text);
}

// gh卡片
function iro_render_ghcard($path){
if (strpos($path, 'https://github.com/') === 0) {
$path = str_replace('https://github.com/', '', $path);
}
Expand Down Expand Up @@ -2823,50 +2846,135 @@ function register_shortcodes() {
$language,
intval($stars)
);
}

add_shortcode('ghcard', function($attr, $content = '') {
//获取内容
$atts = shortcode_atts(array("path" => "mirai-mamori/Sakurairo"), $attr);

$path = trim($atts['path']);

return iro_render_ghcard($path);
});

add_shortcode('showcard', function($attr, $content = '') {
$atts = shortcode_atts(array("icon" => "", "title" => "", "img" => "", "color" => ""), $attr);
register_block_type('sakurairo/ghcard', [
'render_callback' => 'iro_render_ghcard_block',
]);
function iro_render_ghcard_block($attributes, $content) {

$path = $attributes['path'] ?? '';

return iro_render_ghcard($path);
}

// 展示卡片
function iro_render_showcard($atts,$content) {

return sprintf(
'<div class="showcard">
<div class="img" alt="Show-Card" style="background:url(%s);background-size:cover;background-position: center;">
<a href="%s"><button class="showcard-button" style="color:%s !important;"><i class="fa-solid fa-angle-right"></i></button></a>
<div class="img" style="background:url(%s);background-size:cover;background-position:center;">
<a href="%s" target="_blank" rel="noopener noreferrer">
<button class="showcard-button" style="color:%s;">
<i class="fa-solid fa-angle-right"></i>
</button>
</a>
</div>
<div class="icon-title">
<i class="%s" style="color:%s !important;"></i>
<i class="%s" style="color:%s;"></i>
<span class="title">%s</span>
</div>
</div>',
$atts['img'],
$content,
esc_attr($atts['color']),
esc_attr($atts['icon']),
esc_attr($atts['color']),
$atts['title'],
esc_url($atts['img'] ?? ''),
esc_url($atts['link'] ?? $content ?? ''),
esc_attr($atts['color'] ?? ''),
esc_attr($atts['icon'] ?? ''),
esc_attr($atts['color'] ?? ''),
wp_kses_post($atts['title'] ?? '')
);
}


add_shortcode('showcard', function($attr, $content = '') {
$atts = shortcode_atts(array("icon" => "", "title" => "", "img" => "", "color" => ""), $attr);
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The showcard shortcode currently cannot accept a link attribute because shortcode_atts(...) only whitelists icon/title/img/color; any provided link attr will be dropped and $atts['link'] will always be unset. Add link to the defaults (or adjust parsing) so [showcard link="..."] works as intended.

Suggested change
$atts = shortcode_atts(array("icon" => "", "title" => "", "img" => "", "color" => ""), $attr);
$atts = shortcode_atts(array("icon" => "", "title" => "", "img" => "", "color" => "", "link" => ""), $attr);

Copilot uses AI. Check for mistakes.
return iro_render_showcard($atts,$content);
});

add_shortcode('conversations', function($attr, $content = '') {
$atts = shortcode_atts(array("avatar" => "", "direction" => "", "username" => ""), $attr);
if (empty($atts['avatar']) && !empty($atts['username'])) {
$user = get_user_by('login', $atts['username']);
register_block_type('sakurairo/showcard', [
'render_callback' => 'iro_render_showcard_block',
]);
function iro_render_showcard_block($attributes, $content) {

$img = $attributes['img'] ?? '';
$link = $attributes['link'] ?? '';
$color = $attributes['color'] ?? '';
$icon = $attributes['icon'] ?? '';
$title = $attributes['title'] ?? '';

return iro_render_showcard([
'img' => $img,
'link' => $link,
'color' => $color,
'icon' => $icon,
'title' => $title,
],'');
}

// 对话
function iro_render_conversations($atts, $content) {
// 基本信息
$username = isset($atts['username']) ? $atts['username'] : '';
$avatar = isset($atts['avatar']) ? $atts['avatar'] : '';
$direction = isset($atts['direction']) && in_array($atts['direction'], ['row', 'row-reverse'])
? $atts['direction']
: 'row';

if (empty($avatar) && !empty($username)) {
$user = get_user_by('login', $username);
if ($user) {
$atts['avatar'] = get_avatar_url($user->ID, 40);
$avatar = get_avatar_url($user->ID, 40);
}
}
$speaker_alt = $atts['username'] ? '<span class="screen-reader-text">' . sprintf(__("%s says: ", "sakurairo"), esc_html($atts['username'])) . '</span>' : "";

$speaker_alt = '';
if (!empty($username)) {
$speaker_alt = '<span class="screen-reader-text">' .
sprintf(__("%s says: ", "sakurairo"), esc_html($username)) .
'</span>';
}

return sprintf(
'<div class="conversations-code" style="flex-direction: %s;">
<img src="%s">
<div class="conversations-code-text">%s%s</div>
Comment on lines 2946 to 2948
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The conversations markup outputs an <img> without an alt attribute, which is an accessibility issue for screen readers. Add an appropriate alt (e.g., the speaker name) or at least alt="" if it's decorative.

Copilot uses AI. Check for mistakes.
</div>',
esc_attr($atts['direction']),
$atts['avatar'],
$direction,
esc_url($avatar),
$speaker_alt,
$content
Comment on lines 2945 to 2953
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The function iro_render_conversations outputs $content directly into the HTML div without any sanitization or escaping, while both the conversations shortcode and the new sakurairo/conversation block pass user-controlled text into this parameter. An attacker with the ability to create or edit posts can craft shortcode or block content (for example via the block editor code view) that includes <script> or malicious HTML in the conversation text, leading to stored XSS when the post is viewed. You should sanitize or escape $content (for example by passing it through wp_kses_post or similar) before including it in the conversations-code-text markup for both the shortcode and block rendering.

Copilot uses AI. Check for mistakes.
);
}

add_shortcode('conversations', function($attr, $content = '') {
$atts = shortcode_atts(array("avatar" => "", "direction" => "", "username" => ""), $attr);
return iro_render_conversations($atts,$content);
});

register_block_type('sakurairo/conversation', [
'render_callback' => 'iro_render_conversations_block',
]);
function iro_render_conversations_block($attributes, $content) {

$avatar = $attributes['avatar'] ?? '';
$direction = $attributes['direction'] ?? '';
$content = $attributes['content'] ?? '';

return iro_render_conversations([
'avatar' => $avatar,
'direction' => $direction,
],$content);
}

// 折叠
add_shortcode('collapse', function($atts, $content = null) {
$atts = shortcode_atts(array("title" => ""), $atts);
ob_start();
Expand All @@ -2883,7 +2991,8 @@ function register_shortcodes() {
return ob_get_clean();
});

add_shortcode('vbilibili', function ($atts, $content = null) {
// bilibili
function iro_render_bilibili($content) {
preg_match_all('/av([0-9]+)/', $content, $av_matches);
preg_match_all('/BV([a-zA-Z0-9]+)/', $content, $bv_matches);
$iframes = '';
Expand All @@ -2908,8 +3017,21 @@ function register_shortcodes() {
}
}
return $iframes;
}

add_shortcode('vbilibili', function ($atts, $content = null) {
return iro_render_bilibili($content);
});

register_block_type('sakurairo/vbilibili', [
'render_callback' => 'iro_render_bilibili_block',
]);
function iro_render_bilibili_block($attributes, $content) {
$bid = $attributes['videoId'] ?? '';

return iro_render_bilibili($bid);
}

add_shortcode('steamuser', function ($atts, $content = null) {
$key = iro_opt('steam_key');
if (empty($key)) {
Expand Down
2 changes: 1 addition & 1 deletion inc/blocks/build/index.asset.php
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-primitives'), 'version' => '7c81915308f122223650');
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-dom-ready', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-primitives'), 'version' => '130bee0fec91c3da0739');
Loading