Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fe1c0f26e | ||
|
|
25cc1ff3dc | ||
|
|
bd6a6a0e0e | ||
|
|
d1e961af90 | ||
|
|
e3bdef645d | ||
|
|
de53b64880 | ||
|
|
d0b62eabe9 | ||
|
|
99ffd36648 | ||
|
|
4028d7d160 | ||
|
|
a30a6c122d | ||
|
|
0d28025bf4 | ||
|
|
8b75782619 | ||
|
|
c5ab9295f0 | ||
|
|
c816efa26e | ||
|
|
7115a30301 | ||
|
|
db5d8694c4 | ||
|
|
2051c040ec | ||
|
|
13282b5b84 | ||
|
|
af281422d3 | ||
|
|
68026e0fbc | ||
|
|
a9fa990124 | ||
|
|
9635a7a0ba | ||
|
|
9396eef2f9 | ||
|
|
cec6b9c62b | ||
|
|
f23e825b95 | ||
|
|
1c3b86fc22 | ||
|
|
540dbb3b21 | ||
|
|
81ad2232bf | ||
|
|
d520a556cf | ||
|
|
77aebcbd0e |
14
.github/ISSUE_TEMPLATE.md
vendored
14
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,14 +0,0 @@
|
||||
### 1. 该问题的重现步骤是什么?
|
||||
|
||||
### 2. 你期待的结果是什么?实际看到的又是什么?
|
||||
|
||||
### 3. 问题出现的环境
|
||||
|
||||
- 操作系统版本:
|
||||
- Apache/NGINX 版本:
|
||||
- 数据库版本:
|
||||
- PHP 版本:
|
||||
- Typecho 版本:
|
||||
- 浏览器版本:
|
||||
|
||||
[//]: # (如有图片请附上截图)
|
||||
42
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
42
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
---
|
||||
name: 上报 BUG
|
||||
about: 报告问题,帮助改进项目
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## 描述这个 Bug
|
||||
|
||||
简明扼要地描述错误是什么。
|
||||
|
||||
|
||||
### 复现方式
|
||||
|
||||
复现的步骤:
|
||||
|
||||
1. 前往 '...'
|
||||
2. 点击 '....'
|
||||
3. 滚动到 '....'
|
||||
4. 看到错误
|
||||
|
||||
|
||||
### 期望的结果
|
||||
|
||||
简明扼要地描述你期望看到的结果。
|
||||
|
||||
|
||||
### 截图
|
||||
|
||||
如果可以的话,请添加截图或视频以帮助解释你的问题。
|
||||
|
||||
|
||||
### 平台
|
||||
|
||||
- 操作系统版本:
|
||||
- Apache/Nginx 版本:
|
||||
- 数据库版本:
|
||||
- PHP 版本:
|
||||
- Typecho 版本:
|
||||
- 浏览器版本:
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: 论坛支持
|
||||
url: https://forum.typecho.org/
|
||||
about: 交流使用心得,使用模板插件,寻求帮助等等
|
||||
23
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/enhancement_request.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: 提改进建议
|
||||
about: 提出改进建议,改进项目现有功能
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## 你的改进是否与某个问题有关?请描述
|
||||
|
||||
简明扼要地描述问题产生的原因。例如:当 [...] 时,我总是很困惑。
|
||||
|
||||
|
||||
## 描述你想要的解决方案
|
||||
|
||||
简明扼要地描述你希望的解决方案。
|
||||
|
||||
|
||||
## 描述你考虑过的替代方案
|
||||
|
||||
简明扼要地描述你考虑过的任何替代解决方案或功能。
|
||||
|
||||
23
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
23
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
name: 新功能提议
|
||||
about: 为项目提出一个想法或可能的新功能
|
||||
title: ''
|
||||
labels: feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## 你的想法是否与某个问题有关?请描述
|
||||
|
||||
简明扼要地描述问题产生的原因。例如:当 [...] 时,我总是很困惑。
|
||||
|
||||
|
||||
## 描述你想要的解决方案
|
||||
|
||||
简明扼要地描述你希望的解决方案。
|
||||
|
||||
|
||||
## 描述你考虑过的替代方案
|
||||
|
||||
简明扼要地描述你考虑过的任何替代解决方案或功能。
|
||||
|
||||
7
.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
vendored
Normal file
7
.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Fixes #
|
||||
|
||||
## Proposed Changes
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
4
.github/workflows/Typecho-dev-Ci.yml
vendored
4
.github/workflows/Typecho-dev-Ci.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
php: ['7.4', '8.0', '8.1', '8.2']
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup PHP only
|
||||
uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
@@ -35,7 +35,7 @@ jobs:
|
||||
- php
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
|
||||
2
.github/workflows/Typecho-release-Ci.yml
vendored
2
.github/workflows/Typecho-release-Ci.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
|
||||
3
SECURITY.md
Normal file
3
SECURITY.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Security Policy
|
||||
|
||||
Vulnerabilities can be reported by emailing security@typecho.org
|
||||
@@ -38,7 +38,7 @@ $(document).ready(function () {
|
||||
preview = $('<div id="wmd-preview" class="wmd-hidetab" />').insertAfter('.editor');
|
||||
let isFullScreen = false;
|
||||
|
||||
const options = {}, isMarkdown = <?php echo intval($content->isMarkdown || !$content->have()); ?>;
|
||||
const options = {}, isMarkdown = <?php echo json_encode(!$content->have() || $content->isMarkdown); ?>;
|
||||
|
||||
options.strings = {
|
||||
bold: '<?php _e('加粗'); ?> <strong> Ctrl+B',
|
||||
|
||||
@@ -176,14 +176,13 @@ $isAllPosts = ('on' == $request->get('__typecho_all_posts') || 'on' == \Typecho\
|
||||
<td class="kit-hidden-mb"><a
|
||||
href="<?php $options->adminUrl('manage-posts.php?__typecho_all_posts=off&uid=' . $posts->author->uid); ?>"><?php $posts->author(); ?></a>
|
||||
</td>
|
||||
<td class="kit-hidden-mb"><?php $categories = $posts->categories;
|
||||
while ($categories->next()): ?>
|
||||
<?php echo '<a href="';
|
||||
$options->adminUrl('manage-posts.php?category=' . $categories->mid
|
||||
<td class="kit-hidden-mb"><?php foreach($posts->categories as $index => $category): ?><!--
|
||||
--><?php echo ($index > 0 ? ', ' : '') . '<a href="';
|
||||
$options->adminUrl('manage-posts.php?category=' . $category['mid']
|
||||
. (isset($request->uid) ? '&uid=' . $request->filter('encode')->uid : '')
|
||||
. (isset($request->status) ? '&status=' . $request->filter('encode')->status : ''));
|
||||
echo '">' . $categories->name . '</a>' . ($categories->sequence < $categories->length - 1 ? ', ' : ''); ?>
|
||||
<?php endwhile; ?>
|
||||
echo '">' . $category['name'] . '</a>'; ?><!--
|
||||
--><?php endforeach; ?>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ('post_draft' == $posts->type || $posts->revision): ?>
|
||||
|
||||
@@ -12,7 +12,7 @@ include 'menu.php';
|
||||
<div class="row typecho-page-main">
|
||||
<div class="col-mb-12 col-tb-8" role="main">
|
||||
<?php if ($attachment->attachment->isImage): ?>
|
||||
<p><img src="<?php $attachment->attachment->url(); ?>"
|
||||
<p><img src="<?php $attachment->attachment->url(); ?>?<?php $attachment->modified(); ?>"
|
||||
alt="<?php $attachment->attachment->name(); ?>" class="typecho-attachment-photo"/></p>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
@@ -79,6 +79,9 @@ $(document).ready(function() {
|
||||
prePopulate : tagsPre,
|
||||
|
||||
onResult : function (result, query, val) {
|
||||
// remove special chars
|
||||
val = val.replace(/<|>|&|"|'/g, '');
|
||||
|
||||
if (!query) {
|
||||
return result;
|
||||
}
|
||||
@@ -184,7 +187,11 @@ $(document).ready(function() {
|
||||
cid = o.cid;
|
||||
draftId = o.draftId;
|
||||
idInput.val(cid);
|
||||
autoSave.text('<?php _e('已保存'); ?>' + ' (' + o.time + ')').effect('highlight', 1000);
|
||||
autoSave.text('<?php _e('已保存'); ?>' + ' (' + o.time + ')');
|
||||
|
||||
if (!$(document.body).hasClass('preview')) {
|
||||
autoSave.effect('highlight', 1000);
|
||||
}
|
||||
|
||||
cb && cb();
|
||||
};
|
||||
|
||||
@@ -44,7 +44,14 @@ while ($parents->next()) {
|
||||
$permalink = ltrim($permalink, '/');
|
||||
$permalink = preg_replace("/\[([_a-z0-9-]+)[^\]]*\]/i", "{\\1}", $permalink);
|
||||
if ($page->have()) {
|
||||
$permalink = str_replace('{cid}', $page->cid, $permalink);
|
||||
$permalink = preg_replace_callback(
|
||||
"/\{(cid)\}/i",
|
||||
function ($matches) use ($page) {
|
||||
$key = $matches[1];
|
||||
return $page->getRouterParam($key);
|
||||
},
|
||||
$permalink
|
||||
);
|
||||
}
|
||||
$input = '<input type="text" id="slug" name="slug" autocomplete="off" value="' . htmlspecialchars($page->slug ?? '') . '" class="mono" />';
|
||||
?>
|
||||
|
||||
@@ -33,11 +33,14 @@ $post = \Widget\Contents\Post\Edit::alloc()->prepare();
|
||||
$permalink = ltrim($permalink, '/');
|
||||
$permalink = preg_replace("/\[([_a-z0-9-]+)[^\]]*\]/i", "{\\1}", $permalink);
|
||||
if ($post->have()) {
|
||||
$permalink = str_replace([
|
||||
'{cid}', '{category}', '{year}', '{month}', '{day}'
|
||||
], [
|
||||
$post->cid, $post->category, $post->year, $post->month, $post->day
|
||||
], $permalink);
|
||||
$permalink = preg_replace_callback(
|
||||
"/\{(cid|category|year|month|day)\}/i",
|
||||
function ($matches) use ($post) {
|
||||
$key = $matches[1];
|
||||
return $post->getRouterParam($key);
|
||||
},
|
||||
$permalink
|
||||
);
|
||||
}
|
||||
$input = '<input type="text" id="slug" name="slug" autocomplete="off" value="' . htmlspecialchars($post->slug ?? '') . '" class="mono" />';
|
||||
?>
|
||||
@@ -95,7 +98,7 @@ $post = \Widget\Contents\Post\Edit::alloc()->prepare();
|
||||
<label class="typecho-label"><?php _e('分类'); ?></label>
|
||||
<?php \Widget\Metas\Category\Rows::alloc()->to($category); ?>
|
||||
<ul>
|
||||
<?php $categories = $post->categories->toArray('mid'); ?>
|
||||
<?php $categories = array_column($post->categories, 'mid'); ?>
|
||||
<?php while ($category->next()): ?>
|
||||
<li><?php echo str_repeat(' ', $category->levels); ?><input
|
||||
type="checkbox" id="category-<?php $category->mid(); ?>"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
'defaultAvatar' => 'identicon'
|
||||
)); ?>
|
||||
|
||||
<?php $comments->pageNav('« 前一页', '后一页 »'); ?>
|
||||
<nav><?php $comments->pageNav(_t('前一页'), _t('后一页'), 3, '...', array('wrapTag' => 'ul', 'itemTag' => 'li')); ?></nav>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
<h5 id="response"><?php _e('你的评论'); ?></h5>
|
||||
|
||||
<form method="post" action="<?php $this->commentUrl() ?>" id="comment-form" role="form">
|
||||
<textarea placeholder="<?php _e('评论内容...'); ?>" rows="4" cols="50" name="text" id="textarea" required><?php $this->remember('text'); ?></textarea>
|
||||
<div class="grid">
|
||||
<textarea placeholder="<?php _e('评论内容...'); ?>" rows="4" cols="300" name="text" id="textarea" required><?php $this->remember('text'); ?></textarea>
|
||||
</div>
|
||||
<?php if ($this->user->hasLogin()): ?>
|
||||
<p>
|
||||
<?php _e('登录身份:'); ?><a href="<?php $this->options->profileUrl(); ?>"><?php $this->user->screenName(); ?></a><span class="mx-2 text-muted">·</span><a href="<?php $this->options->logoutUrl(); ?>"><?php _e('退出'); ?></a>
|
||||
@@ -32,7 +34,7 @@
|
||||
<div class="grid">
|
||||
<input type="text" placeholder="<?php _e('名字'); ?>" name="author" id="author" value="<?php $this->remember('author'); ?>" required/>
|
||||
<input type="email" placeholder="<?php _e('Email'); ?>" name="mail" id="mail" value="<?php $this->remember('mail'); ?>"<?php if ($this->options->commentsRequireMail): ?> required<?php endif; ?> />
|
||||
<input type="url" placeholder="<?php _e('网站 http://'); ?><?php if (!($this->options->commentsRequireUrl)): ?><?php _e('(选填)'); ?><?php endif; ?>" name="url" id="url" placeholder="<?php _e('https://'); ?>" value="<?php $this->remember('url'); ?>"<?php if ($this->options->commentsRequireUrl): ?> required<?php endif; ?> />
|
||||
<input type="url" placeholder="<?php _e('http://网站'); ?><?php if (!$this->options->commentsRequireUrl): ?><?php _e('(选填)'); ?><?php endif; ?>" name="url" id="url" value="<?php $this->remember('url'); ?>"<?php if ($this->options->commentsRequireUrl): ?> required<?php endif; ?> />
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<button type="submit"><?php _e('提交评论'); ?></button>
|
||||
|
||||
@@ -13,18 +13,20 @@ function themeConfig($form)
|
||||
|
||||
$form->addInput($logoUrl->addRule('url', _t('请填写正确的 URL 地址')));
|
||||
|
||||
$themeStyle = new \Typecho\Widget\Helper\Form\Element\Radio(
|
||||
'themeStyle',
|
||||
$colorSchema = new \Typecho\Widget\Helper\Form\Element\Select(
|
||||
'colorSchema',
|
||||
array(
|
||||
'auto' => _t('自动'),
|
||||
null => _t('自动'),
|
||||
'light' => _t('浅色'),
|
||||
'dark' => _t('深色')
|
||||
'dark' => _t('深色'),
|
||||
'customize' => _t('自定义'),
|
||||
),
|
||||
'auto',
|
||||
_t('外观风格')
|
||||
null,
|
||||
_t('外观风格'),
|
||||
_t('如果选择了自定义,主题将使用 theme.css 的样式')
|
||||
);
|
||||
|
||||
$form->addInput($themeStyle);
|
||||
$form->addInput($colorSchema);
|
||||
}
|
||||
|
||||
function postMeta(
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<?php if (!defined('__TYPECHO_ROOT_DIR__')) exit; ?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-Hans" data-theme="<?php $this->options->themeStyle(); ?>">
|
||||
|
||||
<html lang="zh-Hans"<?php if ($this->options->colorSchema): ?> data-theme="<?php $this->options->colorSchema(); ?>"<?php endif; ?>>
|
||||
<head>
|
||||
<meta charset="<?php $this->options->charset(); ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php $this->archiveTitle('', '', ' | '); ?><?php $this->options->title(); ?><?php if ($this->is('index')): ?> | <?php $this->options->description() ?><?php endif; ?></title>
|
||||
|
||||
<link rel="stylesheet" href="<?php $this->options->themeUrl('static/css/style.css'); ?>">
|
||||
|
||||
<?php if ($this->options->colorSchema == 'customize'): ?>
|
||||
<link rel="stylesheet" href="<?php $this->options->themeUrl('theme.css'); ?>">
|
||||
<?php endif; ?>
|
||||
<?php $this->header(); ?>
|
||||
</head>
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<label for="nav-toggler" class="nav-toggler-btn"><img src="<?php $this->options->themeUrl('static/img/menu.svg'); ?>" alt="Menu"></label>
|
||||
<label for="nav-toggler" class="nav-toggler-btn">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12" /><line x1="3" y1="6" x2="21" y2="6" /><line x1="3" y1="18" x2="21" y2="18" /></svg>
|
||||
</label>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
@@ -25,24 +25,20 @@ $this->need('header.php');
|
||||
</h4>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php while ($this->next()): ?>
|
||||
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
|
||||
<?php postMeta($this); ?>
|
||||
|
||||
<div class="entry-content fmt" itemprop="articleBody">
|
||||
<?php $this->content(_t('阅读全文')); ?>
|
||||
</div>
|
||||
</article>
|
||||
<hr class="post-separator">
|
||||
<?php endwhile; ?>
|
||||
<?php while ($this->next()): ?>
|
||||
<article class="post" itemscope itemtype="http://schema.org/BlogPosting">
|
||||
<?php postMeta($this); ?>
|
||||
|
||||
<div class="entry-content fmt" itemprop="articleBody">
|
||||
<?php $this->content(_t('阅读全文')); ?>
|
||||
</div>
|
||||
</article>
|
||||
<hr class="post-separator">
|
||||
<?php endwhile; ?>
|
||||
|
||||
<nav><?php $this->pageNav(_t('前一页'), _t('后一页'), 2, '...', array('wrapTag' => 'ul', 'itemTag' => 'li')); ?></nav>
|
||||
</div>
|
||||
|
||||
<!-- <div class="text-center">
|
||||
<a href="#">« Older Posts</a>
|
||||
<span class="mx-2 text-muted">·</span>
|
||||
<a href="#">Newer Posts »</a>
|
||||
</div> -->
|
||||
<?php $this->pageNav('← ' . _t('前一页'), _t('后一页') . ' →'); ?>
|
||||
</main>
|
||||
|
||||
<?php $this->need('footer.php'); ?>
|
||||
|
||||
@@ -12,14 +12,12 @@
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<div class="grid post-next">
|
||||
<div>
|
||||
← <?php $this->thePrev('%s', _t('没有了')); ?>
|
||||
</div>
|
||||
<div class="text-end">
|
||||
<?php $this->theNext('%s', _t('没有了')); ?> →
|
||||
</div>
|
||||
</div>
|
||||
<nav class="post-nav">
|
||||
<ul class="page-navigator">
|
||||
<li class="prev"><?php $this->thePrev('%s', _t('没有了')); ?></li>
|
||||
<li class="next"><?php $this->theNext('%s', _t('没有了')); ?></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<?php $this->need('comments.php'); ?>
|
||||
</div>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 13 KiB |
File diff suppressed because one or more lines are too long
@@ -1,15 +0,0 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#fff"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<line x1="3" y1="12" x2="21" y2="12" />
|
||||
<line x1="3" y1="6" x2="21" y2="6" />
|
||||
<line x1="3" y1="18" x2="21" y2="18" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 324 B |
@@ -1,14 +0,0 @@
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#fff"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<circle cx="11" cy="11" r="8" />
|
||||
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 284 B |
@@ -3,7 +3,7 @@
|
||||
* Licensed under MIT
|
||||
*/
|
||||
|
||||
// Config
|
||||
// Customize
|
||||
// $enable-responsive-typography: false;
|
||||
|
||||
// Grey
|
||||
@@ -19,53 +19,18 @@ $grey-800: #1e293b;
|
||||
$grey-900: #0f172a;
|
||||
|
||||
// Blue
|
||||
$primary-50: #E9F2FC;
|
||||
$primary-100: #D1E5FB;
|
||||
$primary-200: #9BCCFD;
|
||||
$primary-300: #51B4FF;
|
||||
$primary-400: #029AE8;
|
||||
$primary-500: #017FC0;
|
||||
$primary-600: #02659A;
|
||||
$primary-700: #014C75;
|
||||
$primary-800: #033452;
|
||||
$primary-900: #061E2F;
|
||||
|
||||
// Amber
|
||||
$amber-50: #fffbeb;
|
||||
$amber-100: #fef3c7;
|
||||
$amber-200: #fde68a;
|
||||
$amber-300: #fcd34d;
|
||||
$amber-400: #fbbf24;
|
||||
$amber-500: #f59e0b;
|
||||
$amber-600: #d97706;
|
||||
$amber-700: #b45309;
|
||||
$amber-800: #92400e;
|
||||
$amber-900: #78350f;
|
||||
|
||||
// Green
|
||||
$green-50: #f0fdf4;
|
||||
$green-100: #dcfce7;
|
||||
$green-200: #bbf7d0;
|
||||
$green-300: #86efac;
|
||||
$green-400: #4ade80;
|
||||
$green-500: #22c55e;
|
||||
$green-600: #16a34a;
|
||||
$green-700: #15803d;
|
||||
$green-800: #166534;
|
||||
$green-900: #14532d;
|
||||
|
||||
// Red
|
||||
$red-50: #fef2f2;
|
||||
$red-100: #fee2e2;
|
||||
$red-200: #fecaca;
|
||||
$red-300: #fca5a5;
|
||||
$red-400: #f87171;
|
||||
$red-500: #ef4444;
|
||||
$red-600: #dc2626;
|
||||
$red-700: #b91c1c;
|
||||
$red-800: #991b1b;
|
||||
$red-900: #7f1d1d;
|
||||
$primary-50: #d6f0ff;
|
||||
$primary-100: #b5e7ff;
|
||||
$primary-200: #83d9ff;
|
||||
$primary-300: #48c3ff;
|
||||
$primary-400: #1ea2ff;
|
||||
$primary-500: #0683ff;
|
||||
$primary-600: #0064e6;
|
||||
$primary-700: #0855c5;
|
||||
$primary-800: #0d4b9b;
|
||||
$primary-900: #0e2e5d;
|
||||
|
||||
// Config
|
||||
@import "../../../../../tools/node_modules/@picocss/pico/scss/variables";
|
||||
|
||||
// Theming
|
||||
|
||||
@@ -7,37 +7,32 @@
|
||||
|
||||
body {
|
||||
cursor: auto;
|
||||
text-underline-offset: 0.2rem;
|
||||
}
|
||||
|
||||
// Theme
|
||||
[data-theme="light"],
|
||||
:root:not([data-theme="dark"]) {
|
||||
--primary: #{$primary-500};
|
||||
--primary-hover: #{$primary-600};
|
||||
--muted-border-color: #{$grey-200};
|
||||
--level-odd-color: #{$grey-50};
|
||||
}
|
||||
|
||||
@media only screen and (prefers-color-scheme: dark) {
|
||||
:root:not([data-theme]) {
|
||||
--background-color: #{$grey-900};
|
||||
--muted-border-color: #{$grey-700};
|
||||
--level-odd-color: #{$grey-800};
|
||||
}
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--primary: #{$primary-500};
|
||||
--primary-hover: #{$primary-400};
|
||||
--muted-border-color: #{$grey-800};
|
||||
|
||||
.site-navbar {
|
||||
background-color: #{$primary-600};
|
||||
}
|
||||
|
||||
.comment-level-odd {
|
||||
background-color: #{$grey-900};
|
||||
}
|
||||
--background-color: #{$grey-900};
|
||||
--muted-border-color: #{$grey-700};
|
||||
--level-odd-color: #{$grey-800};
|
||||
}
|
||||
|
||||
// Content
|
||||
h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
// h1 { --font-size: 2.5rem; }
|
||||
// h2 { --font-size: 2rem; }
|
||||
// h3 { --font-size: 1.75rem; }
|
||||
// h4 { --font-size: 1.5rem; }
|
||||
// h5 { --font-size: 1.25rem; }
|
||||
|
||||
// Icon Size
|
||||
.is-sm {
|
||||
@@ -131,12 +126,9 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
.site-navbar {
|
||||
padding-top: .25rem;
|
||||
padding-bottom: .25rem;
|
||||
background-color: var(--primary);
|
||||
|
||||
a {
|
||||
color: var(--primary-inverse);
|
||||
// color: rgba(255, 255, 255);
|
||||
// &:hover { text-decoration: underline; }
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.site-name {
|
||||
@@ -146,10 +138,14 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
.brand {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
|
||||
img {
|
||||
max-height: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
.desc {
|
||||
color: rgba(255, 255, 255, .5);
|
||||
color: var(--muted-color);
|
||||
display: none;
|
||||
@if map-get($breakpoints, "sm") {
|
||||
@media (min-width: map-get($breakpoints, "sm")) {
|
||||
@@ -171,6 +167,10 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
}
|
||||
}
|
||||
|
||||
.nav-toggler-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
// Dropdown Menu
|
||||
.nav-menu {
|
||||
display: none;
|
||||
@@ -185,14 +185,7 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
|
||||
input[type=search] {
|
||||
height: 50px;
|
||||
background-image: url("../img/search.svg");
|
||||
background-size: auto;
|
||||
background-color: inherit;
|
||||
color: var(--primary-inverse);
|
||||
|
||||
&:focus {
|
||||
--form-element-focus-color: rgba(255, 255, 255, .5);
|
||||
}
|
||||
|
||||
&:not(:focus) {
|
||||
padding: 0;
|
||||
@@ -200,19 +193,14 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
width: 30px;
|
||||
padding-inline-start: 0;
|
||||
background-position: center center;
|
||||
background-color: inherit;
|
||||
color: transparent;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-toggler-btn {
|
||||
margin: calc(var(--spacing) * -1) calc(var(--spacing) * -0.5);
|
||||
padding: var(--spacing) calc(var(--spacing) * 0.5);
|
||||
color: rgba(255, 255, 255, 1.0);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@if map-get($breakpoints, "lg") {
|
||||
@media (min-width: map-get($breakpoints, "lg")) {
|
||||
.site-navbar .container-inner,
|
||||
@@ -279,13 +267,13 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
}
|
||||
}
|
||||
|
||||
.post-next {
|
||||
.post-nav {
|
||||
border-top: 1px solid var(--muted-border-color);
|
||||
padding-top: calc(var(--spacing) * 1.5);
|
||||
padding-top: var(--spacing);
|
||||
margin: var(--block-spacing-vertical) 0;
|
||||
|
||||
|
||||
a {
|
||||
color: var(--h5-color);
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,11 +295,10 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
.comment-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
// padding-left: calc(var(--spacing) * 4);
|
||||
}
|
||||
|
||||
.comment-level-odd {
|
||||
background-color: #{$grey-50};
|
||||
background-color: var(--level-odd-color);
|
||||
}
|
||||
.comment-level-even {
|
||||
background-color: var(--background-color);
|
||||
@@ -385,9 +372,9 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
margin-bottom: calc(var(--spacing) * -1);
|
||||
}
|
||||
|
||||
.comment-by-author {
|
||||
// background-color: var(--mark-background-color);
|
||||
}
|
||||
// .comment-by-author {
|
||||
// background-color: var(--mark-background-color);
|
||||
// }
|
||||
|
||||
#response {
|
||||
margin-bottom: var(--spacing);
|
||||
@@ -395,11 +382,14 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
|
||||
#cancel-comment-reply-link {
|
||||
font-size: .875em;
|
||||
color: var(--del-color);
|
||||
}
|
||||
|
||||
.comment-body .respond {
|
||||
margin-top: var(--spacing);
|
||||
.respond {
|
||||
margin-top: calc(var(--spacing) * 1.5);
|
||||
|
||||
.comment-body & {
|
||||
margin-top: var(--spacing);
|
||||
}
|
||||
}
|
||||
|
||||
#comment-form textarea {
|
||||
@@ -408,18 +398,27 @@ h1, h2, h3, h4, h5 { line-height: 1.25; }
|
||||
|
||||
// page nav
|
||||
.page-navigator {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
flex: 1;
|
||||
|
||||
li {
|
||||
display: inline;
|
||||
margin-left: calc(var(--spacing) / 2);
|
||||
margin-right: calc(var(--spacing) / 2);
|
||||
|
||||
&.current a {
|
||||
font-weight: 700;
|
||||
color: var(--h5-color);
|
||||
.current a {
|
||||
text-decoration: underline;
|
||||
color: inherit;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.prev {
|
||||
margin-right: auto;
|
||||
& a::before {
|
||||
content: "‹";
|
||||
margin-right: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.next {
|
||||
margin-left: auto;
|
||||
& a::after {
|
||||
content: "›";
|
||||
margin-left: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
33
usr/themes/classic-22/theme.css
Normal file
33
usr/themes/classic-22/theme.css
Normal file
@@ -0,0 +1,33 @@
|
||||
/*!
|
||||
* This is an example of a color scheme
|
||||
* You can define your color scheme below
|
||||
*/
|
||||
|
||||
[data-theme="customize"] {
|
||||
--primary: #017FC0 !important;
|
||||
--primary-hover: #02659A !important;
|
||||
--background-color: #fffbeb !important;
|
||||
--muted-border-color: rgba(0, 0, 0, .1) !important;
|
||||
--form-element-border-color: rgba(0, 0, 0, .2) !important;
|
||||
--level-odd-color: rgba(0, 0, 0, .025) !important;
|
||||
--code-background-color: rgba(0, 0, 0, .05) !important;
|
||||
}
|
||||
|
||||
.site-navbar {
|
||||
background-color: var(--primary);
|
||||
}
|
||||
|
||||
.site-navbar a,
|
||||
.site-navbar .nav-toggler-btn,
|
||||
.site-navbar input[type="search"] {
|
||||
color: var(--primary-inverse);
|
||||
}
|
||||
|
||||
.site-navbar .desc {
|
||||
color: rgba(255, 255, 255, .5);
|
||||
}
|
||||
|
||||
.site-navbar input[type="search"] {
|
||||
border-color: rgba(255, 255, 255, .25);
|
||||
--icon-search: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='rgb(255, 255, 255)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
|
||||
}
|
||||
@@ -36,6 +36,7 @@ pre {
|
||||
max-height: 400px;
|
||||
}
|
||||
pre code {
|
||||
display: block;
|
||||
padding: 3px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
@@ -29,9 +29,9 @@ class Error
|
||||
* 构造函数
|
||||
*
|
||||
* @param integer $code 错误代码
|
||||
* @param string|null $message 错误消息
|
||||
* @param string $message 错误消息
|
||||
*/
|
||||
public function __construct(int $code, ?string $message)
|
||||
public function __construct(int $code, string $message)
|
||||
{
|
||||
$this->code = $code;
|
||||
$this->message = $message;
|
||||
|
||||
@@ -40,7 +40,7 @@ class Message
|
||||
|
||||
private array $currentStructName = []; // A stack as well
|
||||
|
||||
private string $currentTagContents;
|
||||
private string $currentTagContents = '';
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
@@ -60,6 +60,25 @@ class Message
|
||||
if (trim($this->message) == '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// remove the DOCTYPE, avoid using a regexp, so we can save memory
|
||||
$count = 0;
|
||||
while (true) {
|
||||
// Fail if there is an endless loop
|
||||
if ($count >= 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$pos = strpos($this->message, '<!DOCTYPE');
|
||||
if ($pos !== false) {
|
||||
$this->message = substr($this->message, 0, $pos)
|
||||
. substr($this->message, strpos($this->message, '>', $pos) + 1);
|
||||
$count ++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$parser = xml_parser_create();
|
||||
// Set XML parser to take the case of tags in to account
|
||||
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false);
|
||||
|
||||
@@ -17,7 +17,7 @@ class Value
|
||||
* @param mixed $data
|
||||
* @param string|null $type
|
||||
*/
|
||||
public function __construct($data, ?string $type)
|
||||
public function __construct($data, ?string $type = null)
|
||||
{
|
||||
$this->data = $data;
|
||||
if (!$type) {
|
||||
|
||||
@@ -493,12 +493,12 @@ EOF;
|
||||
* @access public
|
||||
*
|
||||
* @param string|null $str 需要生成缩略名的字符串
|
||||
* @param string|null $default 默认的缩略名
|
||||
* @param string $default 默认的缩略名
|
||||
* @param integer $maxLength 缩略名最大长度
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function slugName(?string $str, ?string $default = null, int $maxLength = 128): ?string
|
||||
public static function slugName(?string $str, string $default = '', int $maxLength = 128): string
|
||||
{
|
||||
$str = trim($str ?? '');
|
||||
|
||||
@@ -677,6 +677,18 @@ EOF;
|
||||
return $length < $iLength ? ($str . $trim) : $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个字符串是否为空并依次返回
|
||||
*
|
||||
* @param string|null $a
|
||||
* @param string|null $b
|
||||
* @return string|null
|
||||
*/
|
||||
public static function strBy(?string $a, ?string $b = null): ?string
|
||||
{
|
||||
return isset($a) && $a !== '' ? $a : $b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取宽字符串长度函数
|
||||
*
|
||||
|
||||
@@ -187,7 +187,7 @@ class Request
|
||||
}
|
||||
} else {
|
||||
$exists = false;
|
||||
return $default;
|
||||
return $value ?? $default;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,10 +367,7 @@ class Request
|
||||
*/
|
||||
public function getContentType(): ?string
|
||||
{
|
||||
return $this->getServer(
|
||||
'CONTENT_TYPE',
|
||||
$this->getServer('HTTP_CONTENT_TYPE')
|
||||
);
|
||||
return $this->getHeader('Content-Type');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -420,8 +417,14 @@ class Request
|
||||
*/
|
||||
public function getHeader(string $key, ?string $default = null): ?string
|
||||
{
|
||||
$key = 'HTTP_' . strtoupper(str_replace('-', '_', $key));
|
||||
return $this->getServer($key, $default);
|
||||
$key = strtoupper(str_replace('-', '_', $key));
|
||||
|
||||
// Content-Type 和 Content-Length 这两个 header 还需要从不带 HTTP_ 的 key 尝试获取
|
||||
if (in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH'])) {
|
||||
$default = $this->getServer($key, $default);
|
||||
}
|
||||
|
||||
return $this->getServer('HTTP_' . $key, $default);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -542,7 +545,7 @@ class Request
|
||||
$validated = true;
|
||||
foreach ($params as $key => $val) {
|
||||
$param = $this->get($key, null, $exists);
|
||||
$validated = empty($val) ? $exists : ($val == $param);
|
||||
$validated = $val === '' ? $exists : ($val === $param);
|
||||
|
||||
if (!$validated) {
|
||||
break;
|
||||
|
||||
@@ -303,6 +303,24 @@ abstract class Widget
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $column
|
||||
* @return array|mixed|null
|
||||
*/
|
||||
public function toColumn($column)
|
||||
{
|
||||
if (is_array($column)) {
|
||||
$item = [];
|
||||
foreach ($column as $key) {
|
||||
$item[$key] = $this->{$key};
|
||||
}
|
||||
|
||||
return $item;
|
||||
} else {
|
||||
return $this->{$column};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $column
|
||||
* @return array
|
||||
@@ -312,16 +330,7 @@ abstract class Widget
|
||||
$result = [];
|
||||
|
||||
while ($this->next()) {
|
||||
if (is_array($column)) {
|
||||
$item = [];
|
||||
foreach ($column as $key) {
|
||||
$item[$key] = $this->{$key};
|
||||
}
|
||||
|
||||
$result[] = $item;
|
||||
} else {
|
||||
$result[] = $this->{$column};
|
||||
}
|
||||
$result[] = $this->toColumn($column);
|
||||
}
|
||||
|
||||
return $result;
|
||||
@@ -365,6 +374,18 @@ abstract class Widget
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将所有行的值压入堆栈
|
||||
*
|
||||
* @param array $values 所有行的值
|
||||
*/
|
||||
public function pushAll(array $values)
|
||||
{
|
||||
foreach ($values as $value) {
|
||||
$this->push($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据余数输出
|
||||
*
|
||||
@@ -460,7 +481,14 @@ abstract class Widget
|
||||
*/
|
||||
public function __set(string $name, $value)
|
||||
{
|
||||
$this->row[$name] = $value;
|
||||
$method = '___' . $name;
|
||||
$key = '#' . $name;
|
||||
|
||||
if (isset($this->row[$key]) || method_exists($this, $method)) {
|
||||
$this->row[$key] = $value;
|
||||
} else {
|
||||
$this->row[$name] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -471,7 +499,10 @@ abstract class Widget
|
||||
*/
|
||||
public function __isSet(string $name)
|
||||
{
|
||||
return isset($this->row[$name]);
|
||||
$method = '___' . $name;
|
||||
$key = '#' . $name;
|
||||
|
||||
return isset($this->row[$key]) || method_exists($this, $method) || isset($this->row[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -187,6 +187,10 @@ class Archive extends Contents
|
||||
|
||||
/** 用于判断是路由调用还是外部调用 */
|
||||
if (null == $parameter->type) {
|
||||
if (!isset(Router::$current)) {
|
||||
throw new WidgetException('Archive type is not set', 500);
|
||||
}
|
||||
|
||||
$parameter->type = Router::$current;
|
||||
} else {
|
||||
$this->invokeFromOutside = true;
|
||||
@@ -1028,53 +1032,85 @@ class Archive extends Contents
|
||||
if ($this->options->commentsThreaded && $this->is('single')) {
|
||||
if ('' != $allows['commentReply']) {
|
||||
if (1 == $allows['commentReply']) {
|
||||
$header .= "<script type=\"text/javascript\">
|
||||
$header .= <<<EOF
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
window.TypechoComment = {
|
||||
dom : function (id) {
|
||||
return document.getElementById(id);
|
||||
dom : function (sel) {
|
||||
return document.querySelector(sel);
|
||||
},
|
||||
|
||||
visiable: function (el, show) {
|
||||
el.style.display = show ? '' : 'none';
|
||||
},
|
||||
|
||||
create : function (tag, attr) {
|
||||
var el = document.createElement(tag);
|
||||
const el = document.createElement(tag);
|
||||
|
||||
for (var key in attr) {
|
||||
for (const key in attr) {
|
||||
el.setAttribute(key, attr[key]);
|
||||
}
|
||||
|
||||
return el;
|
||||
},
|
||||
|
||||
reply : function (cid, coid) {
|
||||
var comment = this.dom(cid), parent = comment.parentNode,
|
||||
response = this.dom('" . $this->respondId . "'), input = this.dom('comment-parent'),
|
||||
form = 'form' == response.tagName ? response : response.getElementsByTagName('form')[0],
|
||||
textarea = response.getElementsByTagName('textarea')[0];
|
||||
|
||||
if (null == input) {
|
||||
|
||||
inputParent: function (response, coid) {
|
||||
const form = 'form' === response.tagName ? response : response.querySelector('form');
|
||||
let input = form.querySelector('input[name=parent]');
|
||||
|
||||
if (null == input && coid) {
|
||||
input = this.create('input', {
|
||||
'type' : 'hidden',
|
||||
'name' : 'parent',
|
||||
'id' : 'comment-parent'
|
||||
'name' : 'parent'
|
||||
});
|
||||
|
||||
form.appendChild(input);
|
||||
}
|
||||
|
||||
if (coid) {
|
||||
input.setAttribute('value', coid);
|
||||
} else if (input) {
|
||||
input.parentNode.removeChild(input);
|
||||
}
|
||||
},
|
||||
|
||||
getChild: function (root, node) {
|
||||
const parentNode = node.parentNode;
|
||||
|
||||
if (parentNode === null) {
|
||||
return null;
|
||||
} else if (parentNode === root) {
|
||||
return node;
|
||||
} else {
|
||||
return this.getChild(root, parentNode);
|
||||
}
|
||||
},
|
||||
|
||||
input.setAttribute('value', coid);
|
||||
reply : function (htmlId, coid, btn) {
|
||||
const response = this.dom('#{$this->respondId}'),
|
||||
textarea = response.querySelector('textarea[name=text]'),
|
||||
comment = this.dom('#' + htmlId),
|
||||
child = this.getChild(comment, btn);
|
||||
|
||||
if (null == this.dom('comment-form-place-holder')) {
|
||||
var holder = this.create('div', {
|
||||
'id' : 'comment-form-place-holder'
|
||||
this.inputParent(response, coid);
|
||||
|
||||
if (this.dom('#{$this->respondId}-holder') === null) {
|
||||
const holder = this.create('div', {
|
||||
'id' : '{$this->respondId}-holder'
|
||||
});
|
||||
|
||||
response.parentNode.insertBefore(holder, response);
|
||||
}
|
||||
|
||||
if (child) {
|
||||
comment.insertBefore(response, child.nextSibling);
|
||||
} else {
|
||||
comment.appendChild(response);
|
||||
}
|
||||
|
||||
comment.appendChild(response);
|
||||
this.dom('cancel-comment-reply-link').style.display = '';
|
||||
this.visiable(this.dom('#cancel-comment-reply-link'), true);
|
||||
|
||||
if (null != textarea && 'text' == textarea.name) {
|
||||
if (null != textarea) {
|
||||
textarea.focus();
|
||||
}
|
||||
|
||||
@@ -1082,25 +1118,23 @@ class Archive extends Contents
|
||||
},
|
||||
|
||||
cancelReply : function () {
|
||||
var response = this.dom('{$this->respondId}'),
|
||||
holder = this.dom('comment-form-place-holder'), input = this.dom('comment-parent');
|
||||
const response = this.dom('#{$this->respondId}'),
|
||||
holder = this.dom('#{$this->respondId}-holder');
|
||||
|
||||
if (null != input) {
|
||||
input.parentNode.removeChild(input);
|
||||
}
|
||||
this.inputParent(response, false);
|
||||
|
||||
if (null == holder) {
|
||||
if (null === holder) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.dom('cancel-comment-reply-link').style.display = 'none';
|
||||
this.visiable(this.dom('#cancel-comment-reply-link'), false);
|
||||
holder.parentNode.insertBefore(response, holder);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
})();
|
||||
</script>
|
||||
";
|
||||
EOF;
|
||||
} else {
|
||||
$header .= '<script src="' . $allows['commentReply'] . '" type="text/javascript"></script>';
|
||||
}
|
||||
@@ -1111,45 +1145,41 @@ class Archive extends Contents
|
||||
if ($this->options->commentsAntiSpam && $this->is('single')) {
|
||||
if ('' != $allows['antiSpam']) {
|
||||
if (1 == $allows['antiSpam']) {
|
||||
$header .= "<script type=\"text/javascript\">
|
||||
$shuffled = Common::shuffleScriptVar($this->security->getToken($this->request->getRequestUrl()));
|
||||
$header .= <<<EOF
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
var event = document.addEventListener ? {
|
||||
add: 'addEventListener',
|
||||
triggers: ['scroll', 'mousemove', 'keyup', 'touchstart'],
|
||||
load: 'DOMContentLoaded'
|
||||
} : {
|
||||
add: 'attachEvent',
|
||||
triggers: ['onfocus', 'onmousemove', 'onkeyup', 'ontouchstart'],
|
||||
load: 'onload'
|
||||
}, added = false;
|
||||
const events = ['scroll', 'mousemove', 'keyup', 'touchstart'];
|
||||
let added = false;
|
||||
|
||||
document[event.add](event.load, function () {
|
||||
var r = document.getElementById('{$this->respondId}'),
|
||||
input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = '_';
|
||||
input.value = " . Common::shuffleScriptVar($this->security->getToken($this->request->getRequestUrl())) . "
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const response = document.querySelector('#{$this->respondId}');
|
||||
|
||||
if (null != r) {
|
||||
var forms = r.getElementsByTagName('form');
|
||||
if (forms.length > 0) {
|
||||
if (null != response) {
|
||||
const form = 'form' === response.tagName ? response : response.querySelector('form');
|
||||
const input = document.createElement('input');
|
||||
|
||||
input.type = 'hidden';
|
||||
input.name = '_';
|
||||
input.value = {$shuffled};
|
||||
|
||||
if (form) {
|
||||
function append() {
|
||||
if (!added) {
|
||||
forms[0].appendChild(input);
|
||||
form.appendChild(input);
|
||||
added = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < event.triggers.length; i ++) {
|
||||
var trigger = event.triggers[i];
|
||||
document[event.add](trigger, append);
|
||||
window[event.add](trigger, append);
|
||||
for (const event of events) {
|
||||
window.addEventListener(event, append);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>";
|
||||
</script>
|
||||
EOF;
|
||||
} else {
|
||||
$header .= '<script src="' . $allows['antiSpam'] . '" type="text/javascript"></script>';
|
||||
}
|
||||
@@ -1624,14 +1654,19 @@ class Archive extends Contents
|
||||
$this->archiveTitle = $this->title;
|
||||
|
||||
/** 设置关键词 */
|
||||
$this->archiveKeywords = implode(',', $this->tags->toArray('name'));
|
||||
$this->archiveKeywords = implode(',', array_column($this->tags, 'name'));
|
||||
|
||||
/** 设置描述 */
|
||||
$this->archiveDescription = $this->plainExcerpt;
|
||||
}
|
||||
|
||||
/** 设置归档类型 */
|
||||
[$this->archiveType] = explode('_', $this->type);
|
||||
if ($this->parameter->preview && $this->type === 'revision') {
|
||||
$parent = ContentsFrom::allocWithAlias($this->parent, ['cid' => $this->parent]);
|
||||
$this->archiveType = $parent->type;
|
||||
} else {
|
||||
[$this->archiveType] = explode('_', $this->type);
|
||||
}
|
||||
|
||||
/** 设置归档缩略名 */
|
||||
$this->archiveSlug = ('post' == $this->archiveType || 'attachment' == $this->archiveType)
|
||||
|
||||
@@ -79,17 +79,16 @@ class Comments extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
$insertStruct = [
|
||||
'cid' => $rows['cid'],
|
||||
'created' => empty($rows['created']) ? $this->options->time : $rows['created'],
|
||||
'author' => !isset($rows['author']) || strlen($rows['author']) === 0 ? null : $rows['author'],
|
||||
'author' => Common::strBy($rows['author'] ?? null),
|
||||
'authorId' => empty($rows['authorId']) ? 0 : $rows['authorId'],
|
||||
'ownerId' => empty($rows['ownerId']) ? 0 : $rows['ownerId'],
|
||||
'mail' => !isset($rows['mail']) || strlen($rows['mail']) === 0 ? null : $rows['mail'],
|
||||
'url' => !isset($rows['url']) || strlen($rows['url']) === 0 ? null : $rows['url'],
|
||||
'ip' => !isset($rows['ip']) || strlen($rows['ip']) === 0 ? $this->request->getIp() : $rows['ip'],
|
||||
'agent' => !isset($rows['agent']) || strlen($rows['agent']) === 0
|
||||
? $this->request->getAgent() : $rows['agent'],
|
||||
'text' => !isset($rows['text']) || strlen($rows['text']) === 0 ? null : $rows['text'],
|
||||
'type' => empty($rows['type']) ? 'comment' : $rows['type'],
|
||||
'status' => empty($rows['status']) ? 'approved' : $rows['status'],
|
||||
'mail' => Common::strBy($rows['mail'] ?? null),
|
||||
'url' => Common::strBy($rows['url'] ?? null),
|
||||
'ip' => Common::strBy($rows['ip'] ?? null, $this->request->getIp()),
|
||||
'agent' => Common::strBy($rows['agent'] ?? null, $this->request->getAgent()),
|
||||
'text' => Common::strBy($rows['text'] ?? null),
|
||||
'type' => Common::strBy($rows['type'] ?? null, 'comment'),
|
||||
'status' => Common::strBy($rows['status'] ?? null, 'approved'),
|
||||
'parent' => empty($rows['parent']) ? 0 : $rows['parent'],
|
||||
];
|
||||
|
||||
@@ -137,11 +136,11 @@ class Comments extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
|
||||
/** 构建插入结构 */
|
||||
$preUpdateStruct = [
|
||||
'author' => !isset($rows['author']) || strlen($rows['author']) === 0 ? null : $rows['author'],
|
||||
'mail' => !isset($rows['mail']) || strlen($rows['mail']) === 0 ? null : $rows['mail'],
|
||||
'url' => !isset($rows['url']) || strlen($rows['url']) === 0 ? null : $rows['url'],
|
||||
'text' => !isset($rows['text']) || strlen($rows['text']) === 0 ? null : $rows['text'],
|
||||
'status' => empty($rows['status']) ? 'approved' : $rows['status'],
|
||||
'author' => Common::strBy($rows['author'] ?? null),
|
||||
'mail' => Common::strBy($rows['mail'] ?? null),
|
||||
'url' => Common::strBy($rows['url'] ?? null),
|
||||
'text' => Common::strBy($rows['text'] ?? null),
|
||||
'status' => Common::strBy($rows['status'] ?? null, 'approved'),
|
||||
];
|
||||
|
||||
$updateStruct = [];
|
||||
|
||||
@@ -57,8 +57,8 @@ if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
* @property-read Date $date
|
||||
* @property-read string $dateWord
|
||||
* @property-read string[] $directory
|
||||
* @property-read Metas $tags
|
||||
* @property-read Metas $categories
|
||||
* @property-read array[] $tags
|
||||
* @property-read array[] $categories
|
||||
* @property-read string $excerpt
|
||||
* @property-read string $plainExcerpt
|
||||
* @property-read string $summary
|
||||
@@ -95,7 +95,7 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
case 'directory':
|
||||
return implode('/', array_map('urlencode', $this->directory));
|
||||
case 'category':
|
||||
return urlencode($this->categories->slug);
|
||||
return empty($this->categories) ? '' : urlencode($this->categories[0]['slug']);
|
||||
case 'year':
|
||||
return $this->date->year;
|
||||
case 'month':
|
||||
@@ -131,15 +131,15 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
$insertStruct = [
|
||||
'title' => !isset($rows['title']) || strlen($rows['title']) === 0
|
||||
? null : htmlspecialchars($rows['title']),
|
||||
'created' => !isset($rows['created']) ? $this->options->time : $rows['created'],
|
||||
'created' => empty($rows['created']) ? $this->options->time : $rows['created'],
|
||||
'modified' => $this->options->time,
|
||||
'text' => !isset($rows['text']) || strlen($rows['text']) === 0 ? null : $rows['text'],
|
||||
'text' => Common::strBy($rows['text'] ?? null),
|
||||
'order' => empty($rows['order']) ? 0 : intval($rows['order']),
|
||||
'authorId' => $rows['authorId'] ?? $this->user->uid,
|
||||
'template' => empty($rows['template']) ? null : $rows['template'],
|
||||
'type' => empty($rows['type']) ? 'post' : $rows['type'],
|
||||
'status' => empty($rows['status']) ? 'publish' : $rows['status'],
|
||||
'password' => !isset($rows['password']) || strlen($rows['password']) === 0 ? null : $rows['password'],
|
||||
'template' => Common::strBy($rows['template'] ?? null),
|
||||
'type' => Common::strBy($rows['type'] ?? null, 'post'),
|
||||
'status' => Common::strBy($rows['status'] ?? null, 'publish'),
|
||||
'password' => Common::strBy($rows['password'] ?? null),
|
||||
'commentsNum' => empty($rows['commentsNum']) ? 0 : $rows['commentsNum'],
|
||||
'allowComment' => !empty($rows['allowComment']) && 1 == $rows['allowComment'] ? 1 : 0,
|
||||
'allowPing' => !empty($rows['allowPing']) && 1 == $rows['allowPing'] ? 1 : 0,
|
||||
@@ -156,7 +156,7 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
|
||||
/** 更新缩略名 */
|
||||
if ($insertId > 0) {
|
||||
$this->applySlug(!isset($rows['slug']) || strlen($rows['slug']) === 0 ? null : $rows['slug'], $insertId);
|
||||
$this->applySlug(Common::strBy($rows['slug'] ?? null), $insertId, $insertStruct['title']);
|
||||
}
|
||||
|
||||
return $insertId;
|
||||
@@ -167,10 +167,11 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
*
|
||||
* @param string|null $slug 缩略名
|
||||
* @param mixed $cid 内容id
|
||||
* @param string $title 标题
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function applySlug(?string $slug, $cid): string
|
||||
public function applySlug(?string $slug, $cid, string $title = ''): string
|
||||
{
|
||||
if ($cid instanceof Query) {
|
||||
$cid = $this->db->fetchObject($cid->select('cid')
|
||||
@@ -178,6 +179,10 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
}
|
||||
|
||||
/** 生成一个非空的缩略名 */
|
||||
if ((!isset($slug) || strlen($slug) === 0) && preg_match_all("/\w+/", $title, $matches)) {
|
||||
$slug = implode('-', $matches[0]);
|
||||
}
|
||||
|
||||
$slug = Common::slugName($slug, $cid);
|
||||
$result = $slug;
|
||||
|
||||
@@ -185,11 +190,10 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
$draft = $this->db->fetchObject($this->db->select('type', 'parent')
|
||||
->from('table.contents')->where('cid = ?', $cid));
|
||||
|
||||
if ('_draft' == substr($draft->type, - 6) && $draft->parent) {
|
||||
if (preg_match("/_draft$/", $draft->type) && $draft->parent) {
|
||||
$result = '@' . $result;
|
||||
}
|
||||
|
||||
|
||||
/** 判断是否在数据库中已经存在 */
|
||||
$count = 1;
|
||||
while (
|
||||
@@ -226,11 +230,11 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
'title' => !isset($rows['title']) || strlen($rows['title']) === 0
|
||||
? null : htmlspecialchars($rows['title']),
|
||||
'order' => empty($rows['order']) ? 0 : intval($rows['order']),
|
||||
'text' => !isset($rows['text']) || strlen($rows['text']) === 0 ? null : $rows['text'],
|
||||
'template' => empty($rows['template']) ? null : $rows['template'],
|
||||
'type' => empty($rows['type']) ? 'post' : $rows['type'],
|
||||
'status' => empty($rows['status']) ? 'publish' : $rows['status'],
|
||||
'password' => empty($rows['password']) ? null : $rows['password'],
|
||||
'text' => Common::strBy($rows['text'] ?? null),
|
||||
'template' => Common::strBy($rows['template'] ?? null),
|
||||
'type' => Common::strBy($rows['type'] ?? null, 'post'),
|
||||
'status' => Common::strBy($rows['status'] ?? null, 'publish'),
|
||||
'password' => Common::strBy($rows['password'] ?? null),
|
||||
'allowComment' => !empty($rows['allowComment']) && 1 == $rows['allowComment'] ? 1 : 0,
|
||||
'allowPing' => !empty($rows['allowPing']) && 1 == $rows['allowPing'] ? 1 : 0,
|
||||
'allowFeed' => !empty($rows['allowFeed']) && 1 == $rows['allowFeed'] ? 1 : 0,
|
||||
@@ -461,13 +465,11 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
*/
|
||||
public function category(string $split = ',', bool $link = true, ?string $default = null)
|
||||
{
|
||||
$categories = $this->categories;
|
||||
|
||||
if ($categories->have()) {
|
||||
if (!empty($this->categories)) {
|
||||
$result = [];
|
||||
|
||||
while ($categories->next()) {
|
||||
$result[] = $link ? $categories->template('<a href="{permalink}">{name}</a>') : $categories->name;
|
||||
foreach ($this->categories as $category) {
|
||||
$result[] = $link ? "<a href=\"{$category['permalink']}\">{$category['name']}</a>" : $category['name'];
|
||||
}
|
||||
|
||||
echo implode($split, $result);
|
||||
@@ -513,13 +515,11 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
*/
|
||||
public function tags(string $split = ',', bool $link = true, ?string $default = null)
|
||||
{
|
||||
$tags = $this->tags;
|
||||
|
||||
if ($tags->have()) {
|
||||
if (!empty($this->tags)) {
|
||||
$result = [];
|
||||
|
||||
while ($tags->next()) {
|
||||
$result[] = $link ? $tags->template('<a href="{permalink}">{name}</a>') : $tags->name;
|
||||
foreach ($this->tags as $tag) {
|
||||
$result[] = $link ? "<a href=\"{$tag['permalink']}\">{$tag['name']}</a>" : $tag['name'];
|
||||
}
|
||||
|
||||
echo implode($split, $result);
|
||||
@@ -658,32 +658,32 @@ class Contents extends Base implements QueryInterface, RowFilterInterface, Prima
|
||||
{
|
||||
$directory = [];
|
||||
|
||||
$category = $this->categories;
|
||||
|
||||
if ($category->have()) {
|
||||
$directory = Rows::alloc()->getAllParentsSlug($category->mid);
|
||||
$directory[] = $category->slug;
|
||||
if (!empty($this->categories)) {
|
||||
$directory = Rows::alloc()->getAllParentsSlug($this->categories[0]['mid']);
|
||||
$directory[] = $this->categories[0]['slug'];
|
||||
}
|
||||
|
||||
return $directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Metas
|
||||
* @return array
|
||||
*/
|
||||
protected function ___categories(): Metas
|
||||
protected function ___categories(): array
|
||||
{
|
||||
return CategoryRelated::allocWithAlias($this->cid, ['cid' => $this->cid]);
|
||||
return CategoryRelated::allocWithAlias($this->cid, ['cid' => $this->cid])
|
||||
->toArray(['mid', 'name', 'slug', 'description', 'order', 'parent', 'count', 'permalink']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将tags取出
|
||||
*
|
||||
* @return Metas
|
||||
* @return array
|
||||
*/
|
||||
protected function ___tags(): Metas
|
||||
protected function ___tags(): array
|
||||
{
|
||||
return TagRelated::allocWithAlias($this->cid, ['cid' => $this->cid]);
|
||||
return TagRelated::allocWithAlias($this->cid, ['cid' => $this->cid])
|
||||
->toArray(['mid', 'name', 'slug', 'description', 'count', 'permalink']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -414,7 +414,7 @@ class Archive extends Comments
|
||||
if (!$plugged) {
|
||||
echo '<a href="' . substr($this->permalink, 0, - strlen($this->theId) - 1) . '?replyTo=' . $this->coid .
|
||||
'#' . $this->parameter->respondId . '" rel="nofollow" onclick="return TypechoComment.reply(\'' .
|
||||
$this->theId . '\', ' . $this->coid . ');">' . $word . '</a>';
|
||||
$this->theId . '\', ' . $this->coid . ', this);">' . $word . '</a>';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class Admin extends Contents
|
||||
protected function ___parentPost(): Config
|
||||
{
|
||||
return new Config($this->db->fetchRow(
|
||||
$this->select()->where('table.contents.cid = ?', $this->parentId)->limit(1)
|
||||
$this->select()->where('table.contents.cid = ?', $this->parent)->limit(1)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ class Edit extends Contents implements ActionInterface
|
||||
|
||||
/** 取出数据 */
|
||||
$input = $this->request->from('name', 'slug', 'description');
|
||||
$input['slug'] = Common::slugName(empty($input['slug']) ? $input['name'] : $input['slug']);
|
||||
$input['slug'] = Common::slugName(Common::strBy($input['slug'] ?? null, $input['name']));
|
||||
|
||||
$attachment['title'] = $input['name'];
|
||||
$attachment['slug'] = $input['slug'];
|
||||
@@ -313,7 +313,7 @@ class Edit extends Contents implements ActionInterface
|
||||
|
||||
if ($this->isWriteable(clone $condition) && $this->delete($condition)) {
|
||||
/** 删除文件 */
|
||||
Upload::deleteHandle($row);
|
||||
Upload::deleteHandle($this->toColumn(['cid', 'attachment', 'parent']));
|
||||
|
||||
/** 删除评论 */
|
||||
$this->db->query($this->db->delete('table.comments')
|
||||
|
||||
@@ -577,13 +577,14 @@ trait EditTrait
|
||||
$realId = 0;
|
||||
|
||||
/** 是否是从草稿状态发布 */
|
||||
$isDraftToPublish = preg_match("/_draft$/", $this->type);
|
||||
|
||||
$isBeforePublish = ('publish' == $this->status);
|
||||
$isAfterPublish = ('publish' == $contents['status']);
|
||||
$isDraftToPublish = false;
|
||||
$isBeforePublish = false;
|
||||
$isAfterPublish = 'publish' === $contents['status'];
|
||||
|
||||
/** 重新发布现有内容 */
|
||||
if ($this->have()) {
|
||||
$isDraftToPublish = preg_match("/_draft$/", $this->type);
|
||||
$isBeforePublish = 'publish' === $this->status;
|
||||
|
||||
/** 如果它本身不是草稿, 需要删除其草稿 */
|
||||
if (!$isDraftToPublish && $this->draft) {
|
||||
|
||||
@@ -44,17 +44,17 @@ class Admin extends Contents
|
||||
$this->parameter->setDefault('ignoreRequest=0');
|
||||
|
||||
if ($this->parameter->ignoreRequest) {
|
||||
$this->stack = $this->getRows($this->orders, $this->parameter->ignore);
|
||||
$this->pushAll($this->getRows($this->orders, $this->parameter->ignore));
|
||||
} elseif ($this->request->is('keywords')) {
|
||||
$select = $this->select('table.contents.cid')
|
||||
->where('table.contents.type = ? OR table.contents.type = ?', 'page', 'page_draft');
|
||||
$this->searchQuery($select);
|
||||
|
||||
$ids = array_column($this->db->fetchAll($select), 'cid');
|
||||
$this->stack = $this->getRows($ids);
|
||||
$this->pushAll($this->getRows($ids));
|
||||
} else {
|
||||
$this->parentId = $this->request->filter('int')->get('parent', 0);
|
||||
$this->stack = $this->getRows($this->getChildIds($this->parentId));
|
||||
$this->pushAll($this->getRows($this->getChildIds($this->parentId)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ class Rows extends Contents
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$this->stack = $this->getRows($this->orders, $this->parameter->ignore);
|
||||
$this->pushAll($this->getRows($this->orders, $this->parameter->ignore));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -75,7 +75,7 @@ class Edit extends Contents implements ActionInterface
|
||||
|
||||
/** 发送ping */
|
||||
$trackback = array_filter(
|
||||
array_unique(preg_split("/(\r|\n|\r\n)/", trim($this->request->get('trackback'))))
|
||||
array_unique(preg_split("/(\r|\n|\r\n)/", trim($this->request->get('trackback', ''))))
|
||||
);
|
||||
Service::alloc()->sendPing($this, $trackback);
|
||||
|
||||
|
||||
@@ -126,14 +126,14 @@ trait PrepareEditTrait
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Metas
|
||||
* @return array
|
||||
*/
|
||||
protected function ___categories(): Metas
|
||||
protected function ___categories(): array
|
||||
{
|
||||
return $this->have() ? parent::___categories()
|
||||
: MetasFrom::allocWithAlias(
|
||||
'category:' . $this->options->defaultCategory,
|
||||
['mid' => $this->options->defaultCategory]
|
||||
);
|
||||
)->toArray(['mid', 'name', 'slug']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@ class Feed extends Contents
|
||||
'link' => $archive->permalink,
|
||||
'author' => $archive->author,
|
||||
'excerpt' => $archive->plainExcerpt,
|
||||
'category' => $archive->categories->toArray(['name', 'permalink']),
|
||||
'category' => $archive->categories,
|
||||
'comments' => $archive->commentsNum,
|
||||
'commentsFeedUrl' => Common::url($archive->path, $feed->getFeedUrl()),
|
||||
'suffix' => $suffix
|
||||
|
||||
@@ -31,7 +31,7 @@ class Admin extends Metas
|
||||
public function execute()
|
||||
{
|
||||
$this->parentId = $this->request->filter('int')->get('parent', 0);
|
||||
$this->stack = $this->getRows($this->getChildIds($this->parentId));
|
||||
$this->pushAll($this->getRows($this->getChildIds($this->parentId)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -133,7 +133,7 @@ class Edit extends Metas implements ActionInterface
|
||||
/** 取出数据 */
|
||||
$category = $this->request->from('name', 'slug', 'description', 'parent');
|
||||
|
||||
$category['slug'] = Common::slugName(empty($category['slug']) ? $category['name'] : $category['slug']);
|
||||
$category['slug'] = Common::slugName(Common::strBy($category['slug'] ?? null, $category['name']));
|
||||
$category['type'] = 'category';
|
||||
$category['order'] = $this->getMaxOrder('category', $category['parent']) + 1;
|
||||
|
||||
@@ -224,7 +224,7 @@ class Edit extends Metas implements ActionInterface
|
||||
$submit->input->setAttribute('class', 'btn primary');
|
||||
$form->addItem($submit);
|
||||
|
||||
if (isset($this->request->mid) && 'insert' != $action) {
|
||||
if ($this->request->is('mid') && 'insert' != $action) {
|
||||
/** 更新模式 */
|
||||
$meta = $this->db->fetchRow($this->select()
|
||||
->where('mid = ?', $this->request->mid)
|
||||
@@ -284,7 +284,7 @@ class Edit extends Metas implements ActionInterface
|
||||
/** 取出数据 */
|
||||
$category = $this->request->from('name', 'slug', 'description', 'parent');
|
||||
$category['mid'] = $this->request->get('mid');
|
||||
$category['slug'] = Common::slugName(empty($category['slug']) ? $category['name'] : $category['slug']);
|
||||
$category['slug'] = Common::slugName(Common::strBy($category['slug'] ?? null, $category['name']));
|
||||
$category['type'] = 'category';
|
||||
$current = $this->db->fetchRow($this->select()->where('mid = ?', $category['mid']));
|
||||
|
||||
|
||||
@@ -33,6 +33,6 @@ class Related extends Metas
|
||||
return $orderA <=> $orderB;
|
||||
});
|
||||
|
||||
$this->stack = $this->getRows($ids);
|
||||
$this->pushAll($this->getRows($ids));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ class Rows extends Metas
|
||||
*/
|
||||
public function execute()
|
||||
{
|
||||
$this->stack = $this->getRows($this->orders, $this->parameter->ignore);
|
||||
$this->pushAll($this->getRows($this->orders, $this->parameter->ignore));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -132,7 +132,7 @@ class Edit extends Metas implements ActionInterface
|
||||
/** 取出数据 */
|
||||
$tag = $this->request->from('name', 'slug');
|
||||
$tag['type'] = 'tag';
|
||||
$tag['slug'] = Common::slugName(empty($tag['slug']) ? $tag['name'] : $tag['slug']);
|
||||
$tag['slug'] = Common::slugName(Common::strBy($tag['slug'] ?? null, $tag['name']));
|
||||
|
||||
/** 插入数据 */
|
||||
$tag['mid'] = $this->insert($tag);
|
||||
@@ -254,7 +254,7 @@ class Edit extends Metas implements ActionInterface
|
||||
/** 取出数据 */
|
||||
$tag = $this->request->from('name', 'slug', 'mid');
|
||||
$tag['type'] = 'tag';
|
||||
$tag['slug'] = Common::slugName(empty($tag['slug']) ? $tag['name'] : $tag['slug']);
|
||||
$tag['slug'] = Common::slugName(Common::strBy($tag['slug'] ?? null, $tag['name']));
|
||||
|
||||
/** 更新数据 */
|
||||
$this->update($tag, $this->db->sql()->where('mid = ?', $this->request->filter('int')->get('mid')));
|
||||
|
||||
@@ -93,7 +93,7 @@ if (!defined('__TYPECHO_ROOT_DIR__')) {
|
||||
* @property int $commentsPostInterval
|
||||
* @property string $commentsHTMLTagAllowed
|
||||
* @property bool $allowRegister
|
||||
* @property bool $allowXmlRpc
|
||||
* @property int $allowXmlRpc
|
||||
* @property int $postsListSize
|
||||
* @property bool $feedFullText
|
||||
* @property int $defaultCategory
|
||||
|
||||
@@ -114,7 +114,8 @@ class Upload extends Contents implements ActionInterface
|
||||
'table.contents.cid = ?',
|
||||
$this->request->filter('int')->get('cid')
|
||||
)
|
||||
->where('table.contents.type = ?', 'attachment'), [$this, 'push']
|
||||
->where('table.contents.type = ?', 'attachment'),
|
||||
[$this, 'push']
|
||||
);
|
||||
|
||||
if (!$this->have()) {
|
||||
@@ -132,7 +133,7 @@ class Upload extends Contents implements ActionInterface
|
||||
$file['name'] = urldecode($file['name']);
|
||||
}
|
||||
|
||||
$result = self::modifyHandle($this->row, $file);
|
||||
$result = self::modifyHandle($this->toColumn(['cid', 'attachment', 'parent']), $file);
|
||||
|
||||
if (false !== $result) {
|
||||
self::pluginHandle()->call('beforeModify', $result);
|
||||
@@ -315,7 +316,7 @@ class Upload extends Contents implements ActionInterface
|
||||
'allowFeed' => 1
|
||||
];
|
||||
|
||||
if (isset($this->request->cid)) {
|
||||
if ($this->request->is('cid')) {
|
||||
$cid = $this->request->filter('int')->get('cid');
|
||||
|
||||
if ($this->isWriteable($this->db->sql()->where('cid = ?', $cid))) {
|
||||
@@ -341,7 +342,6 @@ class Upload extends Contents implements ActionInterface
|
||||
'url' => $this->attachment->url,
|
||||
'permalink' => $this->permalink
|
||||
]]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ use Typecho\Widget;
|
||||
use Typecho\Widget\Exception as WidgetException;
|
||||
use Widget\Base\Comments;
|
||||
use Widget\Base\Contents;
|
||||
use Widget\Contents\Attachment\Unattached;
|
||||
use Widget\Contents\Page\Admin as PageAdmin;
|
||||
use Widget\Contents\Post\Admin as PostAdmin;
|
||||
use Widget\Contents\Attachment\Admin as AttachmentAdmin;
|
||||
@@ -406,17 +407,16 @@ class XmlRpc extends Contents implements ActionInterface, Hook
|
||||
}
|
||||
|
||||
/** 对未归档附件进行归档 */
|
||||
$unattached = $this->db->fetchAll($this->select()->where('table.contents.type = ? AND
|
||||
(table.contents.parent = 0 OR table.contents.parent IS NULL)', 'attachment'), [$this, 'filter']);
|
||||
$unattached = Unattached::alloc();
|
||||
|
||||
if (!empty($unattached)) {
|
||||
foreach ($unattached as $attach) {
|
||||
if (false !== strpos($input['text'], $attach['attachment']->url)) {
|
||||
if ($unattached->have()) {
|
||||
while ($unattached->next()) {
|
||||
if (false !== strpos($input['text'], $unattached->attachment->url)) {
|
||||
if (!isset($input['attachment'])) {
|
||||
$input['attachment'] = [];
|
||||
}
|
||||
|
||||
$input['attachment'][] = $attach['cid'];
|
||||
$input['attachment'][] = $unattached->cid;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -449,9 +449,9 @@ class XmlRpc extends Contents implements ActionInterface, Hook
|
||||
{
|
||||
/** 开始接受数据 */
|
||||
$input['name'] = $category['name'];
|
||||
$input['slug'] = Common::slugName(empty($category['slug']) ? $category['name'] : $category['slug']);
|
||||
$input['slug'] = Common::slugName(Common::strBy($category['slug'] ?? null, $category['name']));
|
||||
$input['parent'] = $category['parent_id'] ?? ($category['parent'] ?? 0);
|
||||
$input['description'] = $category['description'] ?? $category['name'];
|
||||
$input['description'] = Common::strBy($category['description'] ?? null, $category['name']);
|
||||
|
||||
/** 调用已有组件 */
|
||||
$categoryWidget = CategoryEdit::alloc(null, $input, function (CategoryEdit $category) {
|
||||
@@ -1753,7 +1753,7 @@ class XmlRpc extends Contents implements ActionInterface, Hook
|
||||
throw new Exception(_t('请求的地址不存在'), 404);
|
||||
}
|
||||
|
||||
if (isset($this->request->rsd)) {
|
||||
if ($this->request->get('rsd') !== null) {
|
||||
echo
|
||||
<<<EOF
|
||||
<?xml version="1.0" encoding="{$this->options->charset}"?>
|
||||
@@ -1771,7 +1771,7 @@ class XmlRpc extends Contents implements ActionInterface, Hook
|
||||
</service>
|
||||
</rsd>
|
||||
EOF;
|
||||
} elseif (isset($this->request->wlw)) {
|
||||
} elseif ($this->request->get('wlw') !== null) {
|
||||
echo
|
||||
<<<EOF
|
||||
<?xml version="1.0" encoding="{$this->options->charset}"?>
|
||||
|
||||
Reference in New Issue
Block a user