Compare commits

..

36 Commits

Author SHA1 Message Date
8c981130e8 新增一点 2025-12-21 20:47:07 +08:00
df8c73a68e Merge remote-tracking branch 'origin/web' into lin_sh
分支合并
2025-12-21 20:45:14 +08:00
26f3beb031 综合上传 2025-12-21 20:27:44 +08:00
3dbe393220 更新 README.md 2025-12-20 19:10:34 +00:00
0ad1069e65 新增网页导航表 sitemap.xml 2025-12-12 02:08:54 +08:00
1a11fa4ab9 修改主页docker-reistry的间距 2025-12-06 06:24:59 +08:00
96582b0822 修改主页 2025-12-01 12:11:09 +08:00
e289c2fb59 上传目前修改,暂时网了哪些 2025-11-23 23:29:55 +08:00
432ea17e40 记录当前修改 2025-11-04 23:34:46 +08:00
7ebaa73415 修改README.md 2025-11-03 09:46:01 +08:00
c63bb3e6ad 修改README.md 2025-11-03 09:45:15 +08:00
45f3cf0474 2025.11.03
修改部分
改善部分问题
修改排版
解决已知问题
未知的正在查找

**署名**
SkimrMe
2025-11-03 09:40:54 +08:00
b40c68063c 删除md文件夹 2025-11-02 15:15:36 +08:00
0c70b66966 2025.11.02
日志以及文章完善了数据库存储
接下来就是完成上传数据库的前端与后端的融合了

**署名**
SkimrMe

 # 修改部分
 Changes to be committed:
	modified:   public/blog/index.php
	modified:   public/blog/logs.php
	new file:   public/blog/post/index.php
	new file:   public/blog/post/s/index.php
	deleted:    public/blog/read_file.php
	modified:   public/index.php
	deleted:    public/request/posts.php
	deleted:    src/views/index.php
	deleted:    src/views/post.php
	deleted:    src/views/posts.php
2025-11-02 14:54:04 +08:00
7727a97e4a 完成日志数据库化迁移 2025-10-31 19:44:42 +08:00
eb2d2778d4 主路由配置 2025-08-25 22:28:56 +08:00
ee17bf5edd 域名跳转 ./blog/ 2025-08-25 22:26:22 +08:00
9510f7320c 新增新规划,记录状态更替列表 2025-08-25 22:19:43 +08:00
21810fe3ae 冲突处理 2025-08-22 16:18:37 +08:00
6e79e2ee40 新建一次合并、继续重构 2025-08-22 11:00:35 +08:00
e62ae0968d 防止冲突,备份 2025-08-19 13:12:25 +08:00
bb58c12208 防止冲突,备份 2025-08-19 13:10:29 +08:00
9a0a900d2e 重构打包 2025-08-19 07:01:59 +08:00
14fceea63c 小修改主页,新增fake page 2025-08-12 17:53:50 +08:00
11ac279c88 删除merge、建立web,并合并 2025-08-12 11:59:21 +08:00
ef2c204bae 修改主页日志日期问题 2025-08-05 03:01:02 +08:00
c25ae6bdca 修改/md/ 2025-07-31 00:22:21 +08:00
skimrme
2882260a48 修改太多,先提交 2025-07-31 00:02:22 +08:00
7b3eec0af9 测试提交 2025-07-29 10:18:53 +08:00
skimrme
06145e7c59 我都不知道我这次修改了什么,反正每周定期合并的时间到了,晚安啦xdm 2025-07-28 00:05:38 +08:00
skimrme
be322b86a9 video.js和video.css逻辑全忘记了,已经删掉了,有空重新配置,当年找文心一言配置的,但是现在我还是看不懂啊,大悲,不过现在我应该可以在genmini的帮助下搞定了吧,css我想没问题的,不过js好难啊 2025-07-27 22:26:48 +08:00
skimrme
8f6e09cf0f 再次完善页面缩放比例问题,放大了也不会发生奇怪的错位了 2025-07-27 20:49:18 +08:00
skimrme
3ee0131b0e 添加页面等比例缩放 2025-07-26 20:07:01 +08:00
skimrme
11b8592abf 测试提交 2025-07-26 07:29:32 +08:00
1eff2ea4d7 更新 README.md
Signed-off-by: open_ww3_project <ww3masster@1win.eu.org>
2025-07-25 23:09:12 +00:00
skimrme
8388cf5925 一些修改,删除api页面,逐渐完善弹幕留言,主页日志更新 2025-07-26 07:05:08 +08:00
46 changed files with 7468 additions and 271 deletions

22
.gitignore vendored Normal file → Executable file
View File

@@ -1,2 +1,22 @@
#### 忽略目录
# 数据库
databases/*
src/*
public/*.sql
public/*.db
##### 博客文档
# 图片
src/image/*
public/image/*
# 可能未知
public/message/static/src/video/*
# 管理员面板
public/blog/admin/*
# 临时区
public/blog/md0/*
# 临时区

0
LICENSE Normal file → Executable file
View File

11
README.md Normal file → Executable file
View File

@@ -1,10 +1,15 @@
### 2025.7.20
<a href="https://ww3.tw/">点击访问</a>
## 2025.7.20
open-ww3-project-ww3-tw
个人博客地址(预计)
---
<br>
# 感谢列表:
- 感谢谷歌Genmini的指导
- 感谢互联网
- 感谢自己
**署名**
skimrme
<a href="https://wiki.ww3.tw/doku.php?id=zh_cn:skimrme">skimrme</a>

13
public/blog/about/index.html Executable file
View File

@@ -0,0 +1,13 @@
<html>
<head>
<title>不想写了</title>
<meta charset="utf-8" lang="zh-CN">
</head>
<body>
忘记写了
<br>
所以暂时就不写了
<p>2025.08.05</p>
<p>over</p>
</body>
</html>

View File

@@ -0,0 +1 @@
google-site-verification: google02f6a3f6004a32c6.html

View File

@@ -1,107 +0,0 @@
<html>
<head>
<title>首页 | ww3</title>
<meta charset="utf-8" lang="zh-CN">
<link rel="icon" type="image/x-icon" href="./icon/original.ico">
</head>
<body>
<div id="navbar1">
<table border="0">
<tbody>
<tr>
<td id="td_navbar_40px"><b><a href="https://ww3.tw/" id="url_">首页</a></b></td>
<td id="td_navbar_40px"><b><a href="https://ww3.tw/about/" id="url_">关于</a></b></td>
<td id="td_navbar_75px"><b><a href="https://ww3.tw/jumping-message/" id="url_">弹幕留言</a></b></td>
<td id="td_navbar_75px"><b><a href="https://ww3.tw/short-url/" id="url_">短链生成</a></b></td>
<td id="td_navbar_52px"><b><a href="https://gitea.ww3.tw/skimrme/" id="url_">gitea</a></b></td>
<td id="td_navbar_135px"><b><a href="https://ww3.tw/docker-registry/" id="url_">docker-registry</a></b></td>
<td id="td_navbar_40px"><b><a href="https://ww3.tw/api/" id="url_">api</a></b></td>
</tr>
</tbody>
</table>
</div>
<!-- 屑站日志 -->
<div id="logs">
<h3>屑站日志:<br></h3>
<font size="3.2">
<table border="0">
<tbody>
<tr>
<td id="td_logs">2025.07.20</td>
<td id="td_logs_content">新增<a href="https://gitea.ww3.tw/skimrme">gitea</a><a href="https://ww3.tw/docker-registry/">docker-registry</a>页面</td>
</tr>
<tr>
<td id="td_logs">2025.07.09</td>
<td id="td_logs_content">建立页面</td>
</tr>
</tbody>
</table>
</font>
</div>
<!-- 屑站日志 -->
<div id="js_date"></div>
<script>
</script>
</body>
</html>
<style>
body
{
background-color: rgba(147, 185, 255, 0.644);
}
#url_
{
text-decoration: none;
color: black;
}
#logs
{
height: 220px;
width: 450px;
overflow: auto;
background: #ffffff;
/* up、right、down、left */
margin: 40px 0px 0px 0px;
}
#td_navbar_40px
{
width: 40px;
}
#td_navbar_52px
{
width: 52px;;
}
#td_navbar_75px
{
width: 75px;
}
#td_navbar_135px
{
width: 135px;
}
#td_logs
{
width: 75px;
padding-bottom: 5px;
}
#td_logs_content
{
color: rgb(132, 132, 132);
padding-left: 10px;
padding-bottom: 5px;
}
#js_date{
color: rgb(55, 0, 255);
font-size: 200%;
}
</style>

245
public/blog/index.php Normal file
View File

@@ -0,0 +1,245 @@
<!-- 主页 -->
<html>
<head>
<title>首页 | ww3</title>
<meta charset="utf-8" lang="zh-CN">
<link rel="icon" type="image/x-icon" href="./icon/original.ico">
<!-- 引入页面蓝图css -->
<link rel="stylesheet" type="text/css" href="./src/css/main.css">
</head>
<body>
<div id="app-canvas">
<header>
<h1 style="margin: 80px 0 0 0; color:aqua;">open-ww3-project</h1>
</header>
<!-- 导航栏 -->
<div id="navbar1">
<table border="0" style="background-color: rgba(147, 185, 255, 0.644);">
<tbody>
<tr>
<td id="td_navbar_40px"><b><a href="https://ww3.tw/" id="url_">首页</a></b></td>
<td id="td_navbar_40px"><b><a href="https://ww3.tw/blog/about/" id="url_">关于</a></b></td>
<td id="td_navbar_40px"><b><a href="https://ww3.tw/blog/post/" id="url_">文章</a></b></td>
<td id="td_navbar_75px"><b><a href="https://ww3.tw/jumping-message/" id="url_">弹幕留言</a></b></td>
<td id="td_navbar_78px"><b><a href="https://ww3.tw/short-url/" id="url_">短链生成</a></b></td>
<td id="td_navbar_52px"><b><a href="https://gitea.ww3.tw/skimrme/" id="url_">gitea</a></b></td>
<td id="td_navbar_160px"><b><a href="https://ww3.tw/docker-registry/" id="url_">docker-registry</a></b></td>
<td id="td_navbar_40px"><b><a href="https://api.ww3.tw/" id="url_">api</a></b></td>
<td id="td_navbar_40px"><b><a href="https://wiki.ww3.tw/" id="url_">wiki</a></b></td>
</tr>
</tbody>
</table>
</div>
<!-- 倒过来的箱子 真不明白为什么我会称呼箱子为open-ww3-project-->
<div style="margin: 80px -30px -100px 180px;">
<img id="open-ww3-project-img" width="10%" src="./src/img/open-ww3-project.png" alt="open-ww3-project-img">
</div>
<!-- gitea 图标 -->
<a style="background-color: blueviolet; position: absolute;" href="https://gitea.ww3.tw/skimrme/open-ww3-project-ww3-tw">
<img id="gitea-img" src="https://gitea.ww3.tw/assets/img/logo.svg" width="150px" alt="gitea" >
</a>
<!-- 导航栏 -->
<div id="content-area">
<!-- 屑站日志 -->
<h3 style="margin: 70px 0 30px -50px;">屑站日志:<br></h3>
<div id="logs">
<font size="3.2">
<table border="0">
<tbody>
<?php
// 引入数据库 sqlite
include "./logs.php.text";
?>
</tbody>
</table>
</font>
</div>
<!-- 屑站日志 -->
<div id="post_content">
<?php
//include "post/index.php";
// 设定数据库路径
$db_path = '/var/www/owp/open-ww3-project-ww3-tw/databases/sqlite/owp.db';
try {
// 连接数据库
$db = new SQLite3($db_path);
// 连接成功输出连接成功
echo "<!--数据库连接成功-->";
// 如果连接成功,但是内部状态有问题
if ($db->lastErrorCode() !==0) {
// 依旧显示为连接失败
die("数据库连接失败");
}
// 内容区
// 执行sql命令 查询表单
$select_id_date_title_from_posts_btos /*查询posts表单中的id date title id从大到小排列*/ = $db->query('SELECT id, date, title FROM posts ORDER BY id DESC'); // 执行查询posts表单中的id date title id从大到小排列的命令
// 循环 写入
echo "<center><b><h2>全部文章</h2></b></center>";
echo "<br>";
echo "文章如下↓";
echo "<br>";
echo "<br>";
while ($row = $select_id_date_title_from_posts_btos->fetchArray(SQLITE3_ASSOC)) {
echo "文章id: " . $row['id'] . "<br>";
echo $row['date'] . "&nbsp;&nbsp;&nbsp;" . "文章标题: " . $row['title'] . "<br>";
echo "<a href='https://ww3.tw/blog/post/s/?id=" . $row['id'] . "'>页面跳转</a><br><br>";
}
// 关闭数据库连接
$db->close();
// 捕获php报错
} catch (Exception $e) {
// 依旧显示为连接失败
die("数据库连接失败");
// 关闭数据库连接
$db->close();
}
?>
</div>
</div>
<!-- 私の娘 -->
<div id="my_girl" style="margin: -40px 0 0 1100px;"></div>
<!-- 私の娘 -->
</div>
</body>
</html>
<!-- css 部分 -->
<style>
#navbar1 {
margin: -160px 0 100px -30px;
}
#url_
{
text-decoration: none;
color: rgb(0, 0, 0);
font-size: 18.8px;
}
#td_navbar_40px
{
width: 40px;
}
#td_navbar_52px
{
width: 52px;;
}
#td_navbar_78px
{
width: 78px;
}
#td_navbar_160px
{
width: 160px;
}
/* 日志 */
#logs
{
height: 220px;
width: 450px;
overflow: auto;
background: #ffffffbc;
/* up、right、down、left */
margin: 115px 0px 0px -280px;
}
#td_logs
{
width: 75px;
padding-top: 1.8px;
vertical-align: top;
}
#td_logs_content
{
color: rgb(132, 132, 132);
padding-left: 10px;
padding-bottom: 5px;
}
/* 日志 */
/* 文章 */
#post_content
{
/*text-align: center;*/
height: 500px;
width: 490px;
color: rgb(202, 202, 202);
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
background-color: rgba(27, 27, 27, 0.010);
overflow: auto;
font-size: 19px;
/* up、right、down、left */
margin: 40px 0 0 0;
}
/* 图标 */
#open-ww3-pro1ject-img
{
overflow: auto;
/* up、right、down、left */
margin: 0 0 0 0;
}
#gitea-img
{
margin: -150px 0 0 1150px;
}
</style>
<!-- js 部分-->
<script src="./src/js/main.js"> 引入js页面蓝图 </script>
<!-- 私の娘 -->
<!-- https://cdn.jsdelivr.net/npm/sakana-widget@2.7.1/lib/sakana.min.css -->
<!-- https://cdn.jsdelivr.net/npm/sakana-widget@2.7.1/lib/sakana.min.js -->
<!-- https://cdnjs.cloudflare.com/ajax/libs/sakana-widget/2.7.1/sakana.min.css -->
<!-- https://cdnjs.cloudflare.com/ajax/libs/sakana-widget/2.7.1/sakana.min.js -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/sakana-widget@2.7.1/lib/sakana.min.css"
/>
<script>
function initSakanaWidget(){
const customImageUrl = 'https://open-ww3-project.ww3.tw/blog/src/img/my_girl.png';
const baseCharacter = SakanaWidget.getCharacter('chisato');
const myCharacter = {
image: customImageUrl,
initialState: baseCharacter.initialState,
};
SakanaWidget.registerCharacter('my_girl', myCharacter);
new SakanaWidget({
character: 'my_girl',
size: 200,
autoFit: true,
controls: true
}).mount('#my_girl');
}
</script>
<script
async
onload="initSakanaWidget()"
src="https://cdn.jsdelivr.net/npm/sakana-widget@2.7.1/lib/sakana.min.js">
</script>
<!-- 私の娘 -->

47
public/blog/logs.php.text Normal file
View File

@@ -0,0 +1,47 @@
<?php
// 设定数据库路径
$db_path = '/var/www/owp/open-ww3-project-ww3-tw/databases/sqlite/owp.db';
try {
// 连接数据库
$db = new SQLite3($db_path);
// 连接成功输出连接成功
echo "<!--数据库连接成功-->";
// 如果连接成功,但是内部状态有问题
if ($db->lastErrorCode() !==0) {
// 依旧显示为连接失败
die("数据库连接失败");
}
// 内容区
// 执行sql命令 查询表单
$select_id_date_content_from_logs_b_to_s /*查询logs表单中的id date content id从大到小排列*/ = $db->query('SELECT id, date, content FROM logs ORDER BY id DESC'); // 执行查询logs表单中的id date content id从大到小排列的命令
// 循环 写入
while ($row = $select_id_date_content_from_logs_b_to_s->fetchArray(SQLITE3_ASSOC)) {
// 设定 '&nbsp;' 占用19个字符
$nbsp_count = 0;
// 设定变量是 换行 加上 空格重复19个
$br_nbsp = '<br>' . str_repeat('&nbsp;',$nbsp_count);
// 设定变量是 修改 && 为 换行 加上19个空格
$alter_br = str_replace('&&', $br_nbsp, $row['content']);
// 输出 date content
echo "<tr>" . "<td id='td_logs'>" . "<a style='font-size: 18px;'>" . $row['date'] . "</a>" . "</td>" . "<td id='td_logs_content'>" . $alter_br . "<br>" . "</tr>";
}
// 关闭数据库连接
$db->close();
// 捕获php报错
} catch (Exception $e) {
// 依旧显示为连接失败
die("数据库连接失败");
// 关闭数据库连接
$db->close();
}
?>

7
public/blog/md0/114514.md Executable file
View File

@@ -0,0 +1,7 @@
## MD介绍页面
顾名思义、本文件夹下使用的基本都是markdown
最后感谢提供php的md插件的开源制作者
[点击跳转](https://ww3.tw/blog/md/src/php-markdown/)

479
public/blog/md0/MD.php Executable file
View File

@@ -0,0 +1,479 @@
<?php
Header('Content:text/html;charset=utf-8');
?>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<style>
body,ol,ul,li,img,p{
padding:0;
margin:0;
border:none;
}
li{
list-style-type: square;
padding:2px;
}
h1,h2,h3,h4,h5,h6{
margin:10px 0 0 0;
}
h1,h2,h3{
border-bottom:solid 1px #ddd;
}
h1{
padding-bottom:12px;
}
h2{
padding-bottom: 6px;
}
h3{
padding-bottom: 2px;
}
body,ul{
padding:10px 20px;
}
body{
max-width:1024px;
margin:0 auto;
}
blockquote{
border-left:solid 4px #bbb;
background-color:#eee;
min-height:24px;
line-height:24px;
padding:0px 10px;
margin:0;
color:#333;
font-size:12px;
font-style: italic;
font-family: consolas,楷体;
}
table{
width:100%;
}
table,td,th{
border:solid 1px #ddd;
border-collapse: collapse;
padding:10px;
font-family: consolas;
font-size:14px;
}
table{
margin:10px 0;
text-align:center;
}
.table-left{
text-align:left;
}
.table-center{
text-align: center;
}
.table-right{
text-align: right;
}
tr:nth-child(even){
background-color:#eee;
}
code,pre{
border-radius:5px;
border:solid 1px #eee;
background-color:#f9f9f9;
font-family: consolas;
font-size:14px;
box-shadow: 1px 2px 3px #ddd;
}
code{
padding:2px 12px;
display: inline-block;
margin:10px 0;
}
pre{
padding:10px 12px;
overflow-x:auto;
}
</style>
<?php
/*
* flag规则:
* h1-h6 标题
* u1,u2 无序列表
* ol 有序列表
* p 普通文本
* code 代码
* table 文本
* check 选择
* uncheck 未选择
* quote 引用
* img 图片
* url 网址
* bold 加粗
* italia 斜体
* el 空行
*
* idel 闲置
*/
class MD{
private $file; //当前文件
private $mdGen; //生成器
private $flag; //当前标志
private $flag_pre; //上一次的flag
private $flag_like; //假定类型
private $line_count; //总行数
private $lines; //所有行
private $buf; //缓存行
public function __construct($filename){
$this->file = $filename; //设置当前文件
$this->mdGen = $this->content($filename); //获取生成器
$this->flag = 'idel'; //闲置
$this->lines = array(); //所有行状态
$this->line_count = 0; //行数归0
}
private function content($file){ //获取生成器
if(file_exists($file)){
$fh = fopen($file,"r");
while(!feof($fh)){
yield fgets($fh);
}
fclose($fh);
}else{
return null;
}
}
//遍历每一个字符
private function every($str){
$l = strlen($str);
for($i=0;$i<$l;$i++)
if(ord($str[$i])<0x80)
yield $str[$i];
else{
yield $str[$i].$str[$i+1].$str[$i+2]; //三个字节
$i+=2;
}
}
//解析
private function parse(){
$ctnt = $this->mdGen; //生成器
$ret=array();
if($ctnt != null){
$ret = array();
foreach($ctnt as $line){
if($this->flag != 'code')
$line=ltrim($line); //删除左边
if(strlen($line)){
$ch = $line[0]; //判断第一个字符
$type=ctype_punct($ch);//标点符号
if($this->flag !== 'code') $line=preg_replace('/\s{2,}$/','<br>',$line); //非代码模式
$ret[] = $this->parseLine($line,$type); //解析行
}else{ //空行
switch($this->flag){
case 'ul':
case 'ol':
$ret[]="</$this->flag>";
$this->flag_pre = $this->flag;
$this->flag = 'idel';
break;
case 'table':
$this->flag = 'idel';
$ret[]='</table>';
break;
default:
if($this->flag != 'el') $ret[] = '<br>';
$this->flag = 'el'; //空行
}
}
}
}
$this->lines = $ret;
return $ret;
}
//生成blockquote
private function genQuote($level,$content){
if($level<=0) return "";
return str_repeat('<blockquote>',$level).$content.str_repeat('</blockquote>',$level);
}
//检查是否处于某个状态,默认检查是否处于代码状态
private function check($value='code'){
return ($this->flag == $value);
}
/**
* 生成一行新的表格列
* $data:需要输入的数据
* $type:生成类型
* $wrap:最快层包裹
* $sep:分隔符
*/
private function genRow($data,$type='td',$wrap='tr',$sep='|'){
$ret='';
$mat = explode($sep,$data);
foreach($mat as $elem)
$ret.="<$type>".$elem."</$type>";
return "<$wrap>".$ret."</$wrap>";
}
/**
* 解析行内元素
* bold,italic,code,link,pic
*/
private function parseInner($str){
$str=preg_replace('/\*\*\*([^\*\n\r]+)\*\*\*/','<b><i>\1</i></b>',$str); //加粗并加斜字体
$str=preg_replace('/\*\*([^\*\n\r]+)\*\*/','<b>\1</b>',$str); //加粗字体
$str=preg_replace('/\*([^\*\n\r]+)\*/','<i>\1</i>',$str); //斜体
$str=preg_replace('/```([^`\n\r]+)```/','<code>\1</code>',$str); //代码
$str=preg_replace('/`([^`\n\r]+)`/','<code>\1</code>',$str); //代码
$str=preg_replace('/!\[([^\]\r\n]+)\]\(([^\)\r\n]+)\)/','<img src="\2" alt="\1" title="\1">',$str); //图片
$str=preg_replace('/\[([^\]\r\n]+)\]\(([^\)\r\n]+)\)/','<a href="\2">\1</a>',$str); //图片
return $str;
}
/**
* 按照给定规则解析字符串:
* type:
* true 符号
* false 文字
* 返回:
* array('type'=>类型,'parts'=>array(...))
*/
private function parseLine($str,$type){
if(strlen($str) == 0){
return array('type'=>'p','parts'=>[]); //返回空段
}
$valid_str = rtrim($str); //去除右边的空格
$str = $valid_str;
$output = ''; //需要输出的字符串
if($type == true){ //标点
$type_str = ''; //类型字符串
$data_str = '';
$flag = 0;
foreach($this->every($str) as $ch){
if(!ctype_punct($ch)){
$flag = 1;
}
if($flag == 0)
$type_str .= $ch;
else
$data_str .= $ch;
}
switch($type_str){
case '#':
$wrap = 'h1';
$this->flag_like = 'h1';
break;
case '##':
$wrap = 'h2';
$this->flag_like = 'h2';
break;
case '###':
$wrap = 'h3';
$this->flag_like = 'h3';
break;
case '####':
$wrap = 'h4';
$this->flag_like = 'h4';
break;
case '#####':
$wrap = 'h5';
$this->flag_like = 'h5';
break;
case '######':
$wrap = 'h6';
$this->flag_like = 'h6';
break;
case '+':
case '-':
$wrap = 'li';
$this->flag_like = 'ul';
if($this->flag != 'code'){
if($this->flag != 'ul'){
$this->flag_pre = $this->flag;
$this->flag = 'ul';
$output.='<ul>';
}
}
break;
case '```': //代码模式,不进行干扰
if($this->flag != 'code'){ //不为code,判断是否为单行代码
$output.='<pre>';
if(preg_match('/^\s*```([^`]+)```([^\s]+)\s*$/',$str,$mat)){ //单行代码
$output.="$mat[1]</pre>$mat[2]";
$str = '';
$data_str = '';
}else{
$this->flag_pre = $this->flag;
$this->flag = 'code'; //代码
}
}else{
$output.='</pre>';
$this->flag_pre = $this->flag;
$this->flag = 'idel'; //闲置
}
break;
case '[':
if(preg_match('/^\[\s\]\s*(.+)$/',$str,$mat)){ //选择
$output.="<label><input type='checkbox' disabled> $mat[1]</label><br>";
$this->flag_like = 'check';
}else if(preg_match('/^\[([^\]]+)\]\(([^\)]+)\)([^\s]+)\s*$/',$str,$mat)){ //未选择
$output.="<a href='$mat[2]'>$mat[1]</a>".$this->parseInner($mat[3]);
$this->flag_like = 'a'; //网址
}else if(preg_match('/^\s*(\[\d+\]\:)\s+([^\s]+)\s+([^\r\n]+)\s*$/',$str,$mat)){ //外部资料
$output.="$mat[1] <a href='$mat[2]'>$mat[3]</a>";
}else{
$output.=$str;
}
break;
case '[-]':
$output.="<label><input type='checkbox' checked disabled>$data_str</label><br>";
$this->flag_like = 'check';
break;
case '![':
if(preg_match('/^!\[([^\]]+)\]\(([^\)]+)\)([^\s]+)\s*$/',$str,$mat)){
$output.="<img src='$mat[2]' alt='$mat[1]'>".$this->parseInner($mat[3]);
$this->flag_like = 'img';
}else{
$this->flag_like = 'p'; //没有模式
$output.="$str";
}
break;
case '*': //斜体
if(preg_match('/^\*(.*)\*([^\s]+)\s*$/',$str,$mat)){
$output.=$this->parseInner($str);
$this->flag_like = 'i';
}else if(preg_match('/^\s*\*\s+(.+)\s*$/',$str,$mat)){
$str=$mat[1];
$wrap = 'li';
$this->flag_like = 'ul';
if($this->flag != 'code'){
if($this->flag != 'ul'){
$this->flag_pre = $this->flag;
$this->flag = 'ul';
$output.='<ul>';
}
}
}
break;
case '**': //粗体
if(preg_match('/^\*\*(.*)\*\*/',$str,$mat)){
$output.=$this->parseInner($str);
$this->flag_like = 'b';
}
break;
case '<':
$output.=$str;
$this->flag_like = 'html';
break;
default:
if(!$this->check()){ //非代码模式
if(preg_match('/^>+$/',$type_str)){ //引用
$level = strlen($type_str);
$this->flag_like = 'quote';
$output.=$this->genQuote($level,$data_str); //引用
}else if(preg_match('/^([^\|\n\r]+)(?:\|[^\|\n\r]+)+$/',$str)){ //表格确定格式---|---|....
if($this->flag == 'table'){
$this->flag_like = 'table';
$output.='<table><thead>'.$this->genRow($this->buf,'th').'</thead><tbody>';
}else{ //非表格格式,上一行没有标题
$this->flag_like = 'p'; //没有格式
$output.=$this->buf;
$this->buf = '';
}
}else if(preg_match('/^\s*(\-{3,})|(\={3,})$/',$type_str)){ //hr
$output.='<hr>';
$this->flag_like = 'hr';
break;
}else{
$this->flag_like = 'p';
$output.=$str.'<br>';
}
}
}
$br = '';
preg_match('/^(.*)(<br\s*\/?>)?$/',$data_str,$mat);
$data_str = htmlspecialchars($mat[1]);
if(!$this->check()){ //代码
if(!empty($wrap)) $output.="<$wrap>$mat[1]</$wrap>".(isset($mat[2])?'<br>':'');
}else if($type_str!='```'){
$output.=htmlspecialchars($str).'<br>';
}
}else{ //首个非空字符不为符号
if($this->flag == 'code'){ //代码,直接输出
$str=str_replace("\t",' ',$str);
$output.=htmlspecialchars($str).'<br>';
}else if(is_numeric($str[0])){ //可能为有序列表,也可能是表格
if(preg_match('/^\s*\d+\.\s+([^\r\n]+)\s*$/',$str)){ //有序列表
$this->flag_like = 'ol';
$output.=$str;
}else{
$this->flag_like = 'idel';
foreach($this->every($str) as $ch){
$output.=$ch;
}
}
$output.='<br>';
}else if(preg_match('/^([^\|\n\r]+)(?:\|[^\|\n\r]+)+$/',$str)){ //表格
$mat = explode('|',$str);
if($this->flag!='table'){ //进入表格
$this->buf = $str;
$this->flag_like = 'table';
$wrap = '';
}else{
$output.=$this->genRow($str);
}
//echo $mat[0].'<br>';
//var_dump($mat);
}else{ //其他
$this->flag = 'p';
$output.=$str;
}
}
if(!$this->check()){ //不为代码,设置flag
$this->flag_pre = $this->flag;
$this->flag = $this->flag_like;
if($this->flag_pre == 'table' && $this->flag != 'table')
$output='</table>'.$output;
else if($this->flag_pre == 'ul' && $this->flag != 'ul'){
$output='</ul>'.$output;
}
}
return $this->parseInner($output); //输出需要输出的内容
}
//获取输出内容
public function output(){
$this->parse();
echo implode('',$this->lines);
}
}

5
public/blog/md0/index.php Executable file
View File

@@ -0,0 +1,5 @@
<?php
require './MD.php';
$md=new MD('114514.md');
$md->output();

View File

@@ -0,0 +1,479 @@
<?php
Header('Content:text/html;charset=utf-8');
?>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<style>
body,ol,ul,li,img,p{
padding:0;
margin:0;
border:none;
}
li{
list-style-type: square;
padding:2px;
}
h1,h2,h3,h4,h5,h6{
margin:10px 0 0 0;
}
h1,h2,h3{
border-bottom:solid 1px #ddd;
}
h1{
padding-bottom:12px;
}
h2{
padding-bottom: 6px;
}
h3{
padding-bottom: 2px;
}
body,ul{
padding:10px 20px;
}
body{
max-width:1024px;
margin:0 auto;
}
blockquote{
border-left:solid 4px #bbb;
background-color:#eee;
min-height:24px;
line-height:24px;
padding:0px 10px;
margin:0;
color:#333;
font-size:12px;
font-style: italic;
font-family: consolas,楷体;
}
table{
width:100%;
}
table,td,th{
border:solid 1px #ddd;
border-collapse: collapse;
padding:10px;
font-family: consolas;
font-size:14px;
}
table{
margin:10px 0;
text-align:center;
}
.table-left{
text-align:left;
}
.table-center{
text-align: center;
}
.table-right{
text-align: right;
}
tr:nth-child(even){
background-color:#eee;
}
code,pre{
border-radius:5px;
border:solid 1px #eee;
background-color:#f9f9f9;
font-family: consolas;
font-size:14px;
box-shadow: 1px 2px 3px #ddd;
}
code{
padding:2px 12px;
display: inline-block;
margin:10px 0;
}
pre{
padding:10px 12px;
overflow-x:auto;
}
</style>
<?php
/*
* flag规则:
* h1-h6 标题
* u1,u2 无序列表
* ol 有序列表
* p 普通文本
* code 代码
* table 文本
* check 选择
* uncheck 未选择
* quote 引用
* img 图片
* url 网址
* bold 加粗
* italia 斜体
* el 空行
*
* idel 闲置
*/
class MD{
private $file; //当前文件
private $mdGen; //生成器
private $flag; //当前标志
private $flag_pre; //上一次的flag
private $flag_like; //假定类型
private $line_count; //总行数
private $lines; //所有行
private $buf; //缓存行
public function __construct($filename){
$this->file = $filename; //设置当前文件
$this->mdGen = $this->content($filename); //获取生成器
$this->flag = 'idel'; //闲置
$this->lines = array(); //所有行状态
$this->line_count = 0; //行数归0
}
private function content($file){ //获取生成器
if(file_exists($file)){
$fh = fopen($file,"r");
while(!feof($fh)){
yield fgets($fh);
}
fclose($fh);
}else{
return null;
}
}
//遍历每一个字符
private function every($str){
$l = strlen($str);
for($i=0;$i<$l;$i++)
if(ord($str[$i])<0x80)
yield $str[$i];
else{
yield $str[$i].$str[$i+1].$str[$i+2]; //三个字节
$i+=2;
}
}
//解析
private function parse(){
$ctnt = $this->mdGen; //生成器
$ret=array();
if($ctnt != null){
$ret = array();
foreach($ctnt as $line){
if($this->flag != 'code')
$line=ltrim($line); //删除左边
if(strlen($line)){
$ch = $line[0]; //判断第一个字符
$type=ctype_punct($ch);//标点符号
if($this->flag !== 'code') $line=preg_replace('/\s{2,}$/','<br>',$line); //非代码模式
$ret[] = $this->parseLine($line,$type); //解析行
}else{ //空行
switch($this->flag){
case 'ul':
case 'ol':
$ret[]="</$this->flag>";
$this->flag_pre = $this->flag;
$this->flag = 'idel';
break;
case 'table':
$this->flag = 'idel';
$ret[]='</table>';
break;
default:
if($this->flag != 'el') $ret[] = '<br>';
$this->flag = 'el'; //空行
}
}
}
}
$this->lines = $ret;
return $ret;
}
//生成blockquote
private function genQuote($level,$content){
if($level<=0) return "";
return str_repeat('<blockquote>',$level).$content.str_repeat('</blockquote>',$level);
}
//检查是否处于某个状态,默认检查是否处于代码状态
private function check($value='code'){
return ($this->flag == $value);
}
/**
* 生成一行新的表格列
* $data:需要输入的数据
* $type:生成类型
* $wrap:最快层包裹
* $sep:分隔符
*/
private function genRow($data,$type='td',$wrap='tr',$sep='|'){
$ret='';
$mat = explode($sep,$data);
foreach($mat as $elem)
$ret.="<$type>".$elem."</$type>";
return "<$wrap>".$ret."</$wrap>";
}
/**
* 解析行内元素
* bold,italic,code,link,pic
*/
private function parseInner($str){
$str=preg_replace('/\*\*\*([^\*\n\r]+)\*\*\*/','<b><i>\1</i></b>',$str); //加粗并加斜字体
$str=preg_replace('/\*\*([^\*\n\r]+)\*\*/','<b>\1</b>',$str); //加粗字体
$str=preg_replace('/\*([^\*\n\r]+)\*/','<i>\1</i>',$str); //斜体
$str=preg_replace('/```([^`\n\r]+)```/','<code>\1</code>',$str); //代码
$str=preg_replace('/`([^`\n\r]+)`/','<code>\1</code>',$str); //代码
$str=preg_replace('/!\[([^\]\r\n]+)\]\(([^\)\r\n]+)\)/','<img src="\2" alt="\1" title="\1">',$str); //图片
$str=preg_replace('/\[([^\]\r\n]+)\]\(([^\)\r\n]+)\)/','<a href="\2">\1</a>',$str); //图片
return $str;
}
/**
* 按照给定规则解析字符串:
* type:
* true 符号
* false 文字
* 返回:
* array('type'=>类型,'parts'=>array(...))
*/
private function parseLine($str,$type){
if(strlen($str) == 0){
return array('type'=>'p','parts'=>[]); //返回空段
}
$valid_str = rtrim($str); //去除右边的空格
$str = $valid_str;
$output = ''; //需要输出的字符串
if($type == true){ //标点
$type_str = ''; //类型字符串
$data_str = '';
$flag = 0;
foreach($this->every($str) as $ch){
if(!ctype_punct($ch)){
$flag = 1;
}
if($flag == 0)
$type_str .= $ch;
else
$data_str .= $ch;
}
switch($type_str){
case '#':
$wrap = 'h1';
$this->flag_like = 'h1';
break;
case '##':
$wrap = 'h2';
$this->flag_like = 'h2';
break;
case '###':
$wrap = 'h3';
$this->flag_like = 'h3';
break;
case '####':
$wrap = 'h4';
$this->flag_like = 'h4';
break;
case '#####':
$wrap = 'h5';
$this->flag_like = 'h5';
break;
case '######':
$wrap = 'h6';
$this->flag_like = 'h6';
break;
case '+':
case '-':
$wrap = 'li';
$this->flag_like = 'ul';
if($this->flag != 'code'){
if($this->flag != 'ul'){
$this->flag_pre = $this->flag;
$this->flag = 'ul';
$output.='<ul>';
}
}
break;
case '```': //代码模式,不进行干扰
if($this->flag != 'code'){ //不为code,判断是否为单行代码
$output.='<pre>';
if(preg_match('/^\s*```([^`]+)```([^\s]+)\s*$/',$str,$mat)){ //单行代码
$output.="$mat[1]</pre>$mat[2]";
$str = '';
$data_str = '';
}else{
$this->flag_pre = $this->flag;
$this->flag = 'code'; //代码
}
}else{
$output.='</pre>';
$this->flag_pre = $this->flag;
$this->flag = 'idel'; //闲置
}
break;
case '[':
if(preg_match('/^\[\s\]\s*(.+)$/',$str,$mat)){ //选择
$output.="<label><input type='checkbox' disabled> $mat[1]</label><br>";
$this->flag_like = 'check';
}else if(preg_match('/^\[([^\]]+)\]\(([^\)]+)\)([^\s]+)\s*$/',$str,$mat)){ //未选择
$output.="<a href='$mat[2]'>$mat[1]</a>".$this->parseInner($mat[3]);
$this->flag_like = 'a'; //网址
}else if(preg_match('/^\s*(\[\d+\]\:)\s+([^\s]+)\s+([^\r\n]+)\s*$/',$str,$mat)){ //外部资料
$output.="$mat[1] <a href='$mat[2]'>$mat[3]</a>";
}else{
$output.=$str;
}
break;
case '[-]':
$output.="<label><input type='checkbox' checked disabled>$data_str</label><br>";
$this->flag_like = 'check';
break;
case '![':
if(preg_match('/^!\[([^\]]+)\]\(([^\)]+)\)([^\s]+)\s*$/',$str,$mat)){
$output.="<img src='$mat[2]' alt='$mat[1]'>".$this->parseInner($mat[3]);
$this->flag_like = 'img';
}else{
$this->flag_like = 'p'; //没有模式
$output.="$str";
}
break;
case '*': //斜体
if(preg_match('/^\*(.*)\*([^\s]+)\s*$/',$str,$mat)){
$output.=$this->parseInner($str);
$this->flag_like = 'i';
}else if(preg_match('/^\s*\*\s+(.+)\s*$/',$str,$mat)){
$str=$mat[1];
$wrap = 'li';
$this->flag_like = 'ul';
if($this->flag != 'code'){
if($this->flag != 'ul'){
$this->flag_pre = $this->flag;
$this->flag = 'ul';
$output.='<ul>';
}
}
}
break;
case '**': //粗体
if(preg_match('/^\*\*(.*)\*\*/',$str,$mat)){
$output.=$this->parseInner($str);
$this->flag_like = 'b';
}
break;
case '<':
$output.=$str;
$this->flag_like = 'html';
break;
default:
if(!$this->check()){ //非代码模式
if(preg_match('/^>+$/',$type_str)){ //引用
$level = strlen($type_str);
$this->flag_like = 'quote';
$output.=$this->genQuote($level,$data_str); //引用
}else if(preg_match('/^([^\|\n\r]+)(?:\|[^\|\n\r]+)+$/',$str)){ //表格确定格式---|---|....
if($this->flag == 'table'){
$this->flag_like = 'table';
$output.='<table><thead>'.$this->genRow($this->buf,'th').'</thead><tbody>';
}else{ //非表格格式,上一行没有标题
$this->flag_like = 'p'; //没有格式
$output.=$this->buf;
$this->buf = '';
}
}else if(preg_match('/^\s*(\-{3,})|(\={3,})$/',$type_str)){ //hr
$output.='<hr>';
$this->flag_like = 'hr';
break;
}else{
$this->flag_like = 'p';
$output.=$str.'<br>';
}
}
}
$br = '';
preg_match('/^(.*)(<br\s*\/?>)?$/',$data_str,$mat);
$data_str = htmlspecialchars($mat[1]);
if(!$this->check()){ //代码
if(!empty($wrap)) $output.="<$wrap>$mat[1]</$wrap>".(isset($mat[2])?'<br>':'');
}else if($type_str!='```'){
$output.=htmlspecialchars($str).'<br>';
}
}else{ //首个非空字符不为符号
if($this->flag == 'code'){ //代码,直接输出
$str=str_replace("\t",' ',$str);
$output.=htmlspecialchars($str).'<br>';
}else if(is_numeric($str[0])){ //可能为有序列表,也可能是表格
if(preg_match('/^\s*\d+\.\s+([^\r\n]+)\s*$/',$str)){ //有序列表
$this->flag_like = 'ol';
$output.=$str;
}else{
$this->flag_like = 'idel';
foreach($this->every($str) as $ch){
$output.=$ch;
}
}
$output.='<br>';
}else if(preg_match('/^([^\|\n\r]+)(?:\|[^\|\n\r]+)+$/',$str)){ //表格
$mat = explode('|',$str);
if($this->flag!='table'){ //进入表格
$this->buf = $str;
$this->flag_like = 'table';
$wrap = '';
}else{
$output.=$this->genRow($str);
}
//echo $mat[0].'<br>';
//var_dump($mat);
}else{ //其他
$this->flag = 'p';
$output.=$str;
}
}
if(!$this->check()){ //不为代码,设置flag
$this->flag_pre = $this->flag;
$this->flag = $this->flag_like;
if($this->flag_pre == 'table' && $this->flag != 'table')
$output='</table>'.$output;
else if($this->flag_pre == 'ul' && $this->flag != 'ul'){
$output='</ul>'.$output;
}
}
return $this->parseInner($output); //输出需要输出的内容
}
//获取输出内容
public function output(){
$this->parse();
echo implode('',$this->lines);
}
}

View File

@@ -0,0 +1,5 @@
<?php
require '../MD.php';
$md=new MD('test.md');
$md->output();

View File

@@ -0,0 +1,81 @@
# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题
*斜体*
**粗体**
- 项目1
- 项目2
- 项目3
- 项目4
+ 项目5
+ 项目6
+ 项目7
1. apple
2. boy
3. cat
[ ] 选择1
[-] 选择2
[-] 选择3
[ ] 选择4
---
```c
#include<stdio.h>
void test();
int main(){
printf("Hello,World!\n");
return 0;
}
void test(){
printf("Hello,World!");
}
```
[百度](https://www.baidu.com)
![图片](https://www.baidu.com/favicon.ico)
**blockquote使用方法**
>引言,这是一句引言
>Hello,World!
>>二级引言
>>>三级引言
apple|boy|cat
---|---|---
a|b|c
d|e|f
<table>
<thead>
<tr>
<th>Apple</th>
<th>Boy</th>
<th>Cat</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
</tr>
<tr>
<td>d</td>
<td>e</td>
<td>f</td>
</tr>
</tbody>
</table>
> I o u
> This is just a test...
>> Hello
> World

View File

@@ -0,0 +1 @@
<meta http-equiv="refresh" content="0.1;url=https://github.com/ixysoft/php-markdown">

100
public/blog/post/index.php Normal file
View File

@@ -0,0 +1,100 @@
<head>
<link rel="icon" type="image/x-icon" href="https://ww3.tw/blog/icon/original.ico">
<title>文章列表</title> <!-- 标题 -->
</head>
<body id=wallpaper>
<!-- 背景 -->
<div id="div_1">
<?php
// 设定数据库路径
$db_path = '/var/www/owp/open-ww3-project-ww3-tw/databases/sqlite/owp.db';
try {
// 连接数据库
$db = new SQLite3($db_path);
// 连接成功输出连接成功
echo "<!--数据库连接成功-->";
// 如果连接成功,但是内部状态有问题
if ($db->lastErrorCode() !==0) {
// 依旧显示为连接失败
die("数据库连接失败");
}
// 内容区
// 执行sql命令 查询表单
$select_id_date_title_from_posts_btos /*查询posts表单中的id date title id从大到小排列*/ = $db->query('SELECT id, date, title FROM posts ORDER BY id DESC'); // 执行查询posts表单中的id date title id从大到小排列的命令
// 循环 写入
echo "<a href='https://ww3.tw' style='background-color: rgba(147, 185, 255, 0.644);position: absolute;'>返回首页</a>";
echo "<center><b><h2>全部文章</h2></b></center>";
echo "<br>";
echo "文章如下↓";
echo "<br>";
echo "<br>";
echo "<br>";
echo "<div id='content'>"; # 内容排版
while ($row = $select_id_date_title_from_posts_btos->fetchArray(SQLITE3_ASSOC)) {
echo "文章id: " . $row['id'] . "<br>";
echo $row['date'] . "&nbsp;&nbsp;&nbsp;" . "文章标题: " . $row['title'] . "<br>";
echo "<a href='https://ww3.tw/blog/post/s/?id=" . $row['id'] . "'>页面跳转</a><br><br>";
}
echo "</div>"; # 内容排版
// 关闭数据库连接
$db->close();
// 捕获php报错
} catch (Exception $e) {
// 依旧显示为连接失败
die("数据库连接失败");
// 关闭数据库连接
$db->close();
}
// 随机变换图床api
$wallpaper_apis = ['https://www.loliapi.com/acg/pc/', 'https://api.sretna.cn/api/pc.php', 'https://www.api.plus/API/dongman/', 'https://moe.jitsu.top/img/?sort=pc', 'https://www.dmoe.cc/random.php', 'https://api.r10086.com/樱道随机图片api接口.php?图片系列=猫娘1', 'https://api.mtyqx.cn/tapi/random.php', 'https://api.ww3.tw/touhou'];
$suiji_wallpaper = rand(0, count($wallpaper_apis) - 1);
$wallpaper = $wallpaper_apis[$suiji_wallpaper];
// 显示图床url在页面
echo "<div id='wallpaper_url'>图片来源: " . $wallpaper . "</div>";
?>
</div>
</body>
<style>
#wallpaper {
background-image: url(<?php
echo $wallpaper;
?>); /*图片地址*/ /* https://api.sretna.cn/api/pc.php */
background-repeat: no-repeat; /*禁止平铺*/
background-size: 100% 100%; /*图片占满100%*/
margin: 0; /* 外边框为0 */
/*padding: 0;*/
}
#div_1 {
height: 100%;
color: rgb(0, 0, 0);
font-size: 19px;
background-color: rgba(169, 169, 169, 0.48);
}
#content {
/* up、right、down、left */
margin: 0px 0px 0px 100px;
}
#wallpaper_url {
color: rgba(255, 0, 0, 0.354);
/* up、right、down、left */
margin: 20% 0px 0px 75%;
}
</style>

View File

@@ -0,0 +1,100 @@
<?php
// 设置最大接受id
const MAX_ARTICLE_ID = 100000;
// 获取搜索栏url的id
$post_id = $_GET['id'] ?? null;
// 设定数据库路径
$db_path = '/var/www/owp/open-ww3-project-ww3-tw/databases/sqlite/owp.db';
/**
* 2. 严格的输入验证 (健壮性检查)
* 拦截所有非数字、无效范围或为空的输入
*/
if (
empty($post_id) ||
!is_numeric($post_id) ||
(int)$post_id <= 0 ||
(int)$post_id > MAX_ARTICLE_ID
) {
http_response_code(400); // HTTP 400 Bad Request
$error_msg = "错误:文章 ID 格式不正确。ID 必须是 1 到 " . MAX_ARTICLE_ID . " 之间的整数。";
die($error_msg);
}
// 通过检查后,将 ID 强制转换为整数
$post_id = (int)$post_id;
try {
/**
* 3. 连接 SQLite 数据库
* 注意:如果 PHP 运行用户没有读取此路径文件的权限,这里会失败。
*/
$db = new SQLite3($db_path);
/**
* 4. 准备 SQL 查询语句 (核心安全防线:预处理语句)
* 使用占位符 :id 代替用户输入。
*/
$sql = 'SELECT title, content FROM posts WHERE id = :id';
// 准备语句
$stmt = $db->prepare($sql);
// 绑定参数:将 :id 替换为 $post_id 的值,并明确指定它是一个整数类型
$stmt->bindValue(':id', $post_id, SQLITE3_INTEGER);
/**
* 5. 执行查询并获取结果
*/
$result = $stmt->execute();
// 从结果集中获取一行数据
$row = $result->fetchArray(SQLITE3_ASSOC);
/**
* 6. 显示内容或 404 错误
*/
if ($row) {
// 使用 htmlspecialchars() 函数防止 XSS 攻击
$title = $row['title'];
$content = $row['content'];
// --- 页面输出开始 ---
echo "<!DOCTYPE html>";
echo "<html lang='zh-CN'>";
echo "<head><meta charset='UTF-8'><title>{$title}</title></head>";
echo "<body>";
echo "<a href='https://ww3.tw'>返回主页</a>";
echo "<h1>{$title}</h1>";
// nl2br 用于将换行符转换成 <br>
echo "<article>" . nl2br($content) . "</article>";
echo "</body>";
echo "</html>";
// --- 页面输出结束 ---
} else {
// 文章未找到
http_response_code(404); // 404 Not Found
echo "<h1>404 Not Found</h1>";
echo "<p>抱歉ID 为 {$post_id} 的文章不存在。</p>";
}
/**
* 7. 清理资源
*/
$db->close();
//$stmt->close();
} catch (Exception $e) {
// 处理异常
http_response_code(500); // 500 Internal Server Error
error_log("SQLite 错误: " . $e->getMessage());
die("系统错误,请稍后重试。");
}
?>

7
public/blog/robots.txt Normal file
View File

@@ -0,0 +1,7 @@
User-agent: *
Allow: /
Disallow: /admin/
Sitemap: https://open-ww3-project.ww3.tw/blog/sitemap.xml

23
public/blog/sitemap.xml Normal file
View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://open-ww3-project.ww3.tw/blog/</loc>
<lastmod>2025-12-12</lastmod>
<priority>1.0</priority>
</url>
<url>
<loc>https://open-ww3-project.ww3.tw/blog/about/</loc>
<lastmod>2025-12-12</lastmod>
<priority>0.8</priority>
</url>
<url>
<loc>https://open-ww3-project.ww3.tw/blog/post/</loc>
<lastmod>2025-12-12</lastmod>
<priority>0.8</priority>
</url>
<url>
<loc>https://open-ww3-project.ww3.tw/blog/test.html</loc>
<lastmod>2025-12-13</lastmod>
<priority>0.1</priority>
</url>
</urlset>

View File

@@ -0,0 +1,58 @@
/* css页面蓝图 */
/* 外部背景 */
html, body {
height: 100%;
width: 100%;
margin: 0; /*外边框*/
padding: 0; /*内边框*/
overflow: hidden; /* 防止滚动条 */
background-color: #333; /* 背景颜色 */
}
/* 内部容器 */
#app-canvas {
width: 1280px;
height: 800px;
background-color: rgba(147, 185, 255, 0.644);
border: 5px solid #0056b3; /* 定义边框 5px 实线 蓝色 */
/* transform-origin: 0 0; /* 定义缩放起点 左上角 */
position:fixed; /* 固定页面,不滚动 */
left: 50%; /* 调整左边缘位置到中央 */
top: 50%; /* 调整上边缘位置到中央 */
padding: 30px; /* 内部间距 30px */
}
header {
margin-bottom: 30px; /* 外部间距 30px */
text-align: center; /* 文字居中 */
}
h1 {
font-size: 48px;
color: #fff;
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
}
#content-area {
display: flex;
justify-content: space-around;
gap: 40px;
}
/* 自带 */
.box {
width: 500px;
height: 600px;
background-color: #ffffffcc;
border: 1px solid #ccc;
padding: 20px;
font-size: 20px;
text-align: left;
overflow: auto;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

View File

@@ -0,0 +1,29 @@
// js目前不会先靠ai
function resizeCanvas() {
// 定义设计基准尺寸
const designWidth = 1280;
const designHeight = 800;
// 获取当前浏览器视口尺寸
const currentWidth = window.innerWidth;
const currentHeight = window.innerHeight;
const canvas = document.getElementById('app-canvas');
// 计算缩放比例
const scaleX = currentWidth / designWidth;
const scaleY = currentHeight / designHeight;
const scaleFactor = Math.min(scaleX, scaleY);
// 确保元素中心与 left: 50%; top: 50%; 对齐
canvas.style.transform = `translate(-50%, -50%) scale(${scaleFactor})`;
}
// 首次加载时执行
document.addEventListener('DOMContentLoaded', resizeCanvas);
// 监听窗口大小变化时执行,保持动态缩放
window.addEventListener('resize', resizeCanvas);
// 确保在某些情况下也能正确初始化
resizeCanvas();

5033
public/blog/test.html Normal file

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,45 @@
<html>
<head>
<title>推荐网页</title>
<meta charset="utf-8" lang="zh-CN">
</head>
<body>
<center>
<h3>漫画</h3>
<th>
<td id="font_a">
<a href="https://xmanhua.com/">xmanhua</a>
</td>
</th>
<th>
<td id="font_a">
<a href="https://komiic.com/">komiic</a>
</td>
</th>
<th>
<td id="font_a">
<a href="https://mangadex.org/">mangadex</a>
</td>
</th>
<th>
<td id="font_a">
<a href="https://mangabz.com/">mangabz</a>
</td>
</th>
<h3>动漫</h3>
<th>
<td id="font_a">
<a href="https://www.agedm.com">age动漫 | 尽量不要开梯</a>
</td>
</th>
</center>
</body>
</html>
<style>
#font_a {
width: 50px;
}
</style>

1
public/blog/video.html Normal file
View File

@@ -0,0 +1 @@
<iframe src="//player.bilibili.com/player.html?isOutside=true&aid=115578442356850&bvid=BV12CCdBkEL6&cid=34120008494&p=1&autoplay=0" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true" style="width: 100%; height: 100%;"></iframe>

29
public/index.php Normal file
View File

@@ -0,0 +1,29 @@
<!-- 主路由配置 -->
<?php
$request_uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// 定义条件
$found_route = false;
switch($request_uri){
case '/':
include './re_blog.php';
exit(); // 执行成功立即结束
break;
}
// posts 路由
// 整改中
// 所有路由匹配结束后,检查是否找到路由
if (!$found_route) {
// 设置 HTTP 状态码为 404
header("HTTP/1.0 404 Not Found");
// 包含 404 页面文件
//exit();
include "../src/views/error/404.html";
exit(); // 执行成功立即结束
}

29
public/index.php.back Executable file
View File

@@ -0,0 +1,29 @@
<!-- 主路由配置 -->
<?php
$request_uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
// 定义条件
$found_route = false;
switch($request_uri){
case '/':
include './re_blog.php';
exit(); // 执行成功立即结束
break;
}
// posts 路由
// 整改中
// 所有路由匹配结束后,检查是否找到路由
if (!$found_route) {
// 设置 HTTP 状态码为 404
header("HTTP/1.0 404 Not Found");
// 包含 404 页面文件
//exit();
include "../src/views/error/404.html";
exit(); // 执行成功立即结束
}

View File

@@ -1,6 +1,7 @@
<html>
<head>
<meta charset="utf-8" lang="zh-CN">
<meta name="viewport" content="width=1366px, initial-scale=1.0"> <!-- 页面等比例缩小 -->
<link rel="stylesheet" type="text/css" href="./static/css/navbar/body_color.css">
<link rel="icon" type="img/icon" href="./static/icon/original.ico">
</head>
@@ -28,28 +29,20 @@
<a id="back_url" href="https://ww3.tw/"><b>..返回主页</b></a>
</div>
<div id="message_video">
<br>
<br>
<br>
<br>
<br>
<br>
<h1>
暂无视频
</h1>
<video src="./static/src/video/cirno-up-down.mp4" controls width="640" height="360">
您的浏览器不支持视频播放。
</video>
</div>
<div id="message_com">
<br>
<br>
<br>
<br>
<br>
<br>
评论展示区
<div id="message_com_black">
发送区
<div id="push_message">
<label for="message">输入内容 : </label>
<input type="text" id="message" placeholder="qwq">
<button onclick="push_message()">发送弹幕</button>
<br>
<p>弹幕列表</p>
<pre id="get_message"></pre>
</div>
</div>
<div>
</div>
</div>
</body>
@@ -70,57 +63,28 @@
color: rgb(255, 74, 74);
text-align: left;
font-size: 18px;
}
#message_video
{
background-color: blue;
background-color: rgba(0, 0, 0, 0);
color: white;
text-align: center;
width: 60%;
height: 69%;
margin: auto;
position: absolute;
top: 22%;
left: 0;
right: 0;
bottom: 0;
width: 700px;
height: 410px;
/* 页面边距 上、右、下、左 */
margin: 1.89% 0px 0px 0%;
}
#message_com
{
background-color: white;
text-align: center;
width: 33%;
height: 69%;
margin: auto;
position: absolute;
top: 22%;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0);
width: 360px;
height: 410px;
/* 页面边距 上、右、下、左 */
margin: 1.89% 0px 0px 63.8%;
margin: -405px 0px 0px 63.8%;
}
#message_com_black
{
background-color: black;
color: white;
width: 100%;
height: 8%;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
/* 页面边距 上、右、下、左 */
margin: 108% 0px 0px 0%;
}
#back_blok{
/* 返回主页 */
@@ -144,9 +108,66 @@
}
</style>
<!--这里是专属js-->
<script>
//这里是专属js
function push_message() {
const messageInput = document.getElementById('message'); // 获取输入框元素本身
const messageContent = messageInput.value.trim(); // 获取输入框的值
if (messageContent === "") {
alert("弹幕内容不能为空!");
return;
}
messageInput.value = '';
// *** 在这里清空输入框 ***
messageInput.focus();
// 如果你想让输入框在清空后立即获得焦点,方便用户继续输入
}
</script>
<script>
const API_URL = 'https://api.ww3.tw/public/danmu/get.php'; //连接api的地址
// 使用 DOMContentLoaded 事件,确保页面 HTML 结构加载完成后再执行 JavaScript
document.addEventListener('DOMContentLoaded', async () => {
// 获取用于显示内容的 <pre> 元素
const getMessageElement = document.getElementById('get_message');
try {
// 发送 GET 请求到 API
const response = await fetch(API_URL);
// 检查 HTTP 响应状态码。如果不是 2xx成功说明有错误
if (!response.ok) {
// 尝试解析 API 返回的错误信息
let errorDetails;
try {
// 假设 API 错误信息也是 JSON 格式
errorDetails = await response.json();
} catch (e) {
// 如果不是 JSON就作为纯文本处理
errorDetails = await response.text();
}
// 抛出带有详细信息的错误
throw new Error(`HTTP 错误! 状态码: ${response.status} - ${typeof errorDetails === 'object' && errorDetails !== null ? (errorDetails.message || JSON.stringify(errorDetails)) : errorDetails}`);
}
// 你的 PHP API 返回的是 message.txt 的纯文本内容,所以这里使用 .text() 方法解析响应体
const content = await response.text();
// **** 核心修改:将获取到的内容直接赋值给 <pre> 元素的 textContent ****
getMessageElement.textContent = content;
getMessageElement.classList.remove('loading'); // 移除加载提示样式
} catch (error) {
// 如果在请求或处理过程中发生任何错误,捕获并显示
console.error('获取弹幕内容失败:', error);
getMessageElement.textContent = `错误: ${error.message}`;
getMessageElement.classList.remove('loading'); // 移除加载提示样式
getMessageElement.classList.add('error'); // 添加错误样式
}
});
</script>

View File

@@ -1,49 +0,0 @@
<html>
<head>
<meta charset="utf-8" lang="zh-CN">
<link rel="stylesheet" type="text/css" href="./static/css/body_color.css">
</head>
<body>
<?php
$title = "Message | 留言";
// title 变量
echo "<title>" . "$title" . "</title>";
// 页面标题
?>
<body id="body_color">
<div id="message_block">
<div id="content_page">
<?php
echo "<h1>欢迎来到 $title</h1>";
// 欢迎语
echo "感谢您的访问" . " " . "<br>" . "顾名思义" . "$title" . "就是用来记录留言的地方";
// 介绍部分
?>
</div>
</div>
</body>
</body>
</html>
<!-- php 引入 -->
<?php
include "./static/css/navbar/index-css.html";
// 引入navbar-css
?>
<!-- php 引入 -->
<style>
/* 这里是专属css */
#content_page
{
color: rgb(255, 74, 74);
text-align: left;
font-size: 18px;
}
</style>

View File

@@ -1,52 +0,0 @@
<html>
<head>
<meta charset="utf-8" lang="zh-CN">
<!-- 引入css -->
<link rel="stylesheet" type="text/css" href="./static/css/body.css">
<?php
include './static/html/content_message.html';
//css 部分 引用 html
?>
<!-- 引入css -->
</head>
<body>
<?php
$title = "message";
//定义变量 title
echo "<title>$title</title>";
// 设定网站抬头
echo "<div id='init'>";
echo "<h1>欢迎来到 $title</h1>";
// 欢迎语
echo "感谢您的访问" . " " . "<br>" . "顾名思义" . "$title" . "就是用来记录留言的地方";
// 介绍部分
echo "</div>";
?>
<div>
<?php
include './static/php/google_translate.php';
// 引入 谷歌翻译
?>
<div id="content_message_block">
</div>
<div id="content_message_video">
</div>
</div>
</body>
</html>
<style>
#init
{
position: fixed;
/* 页面边距 上、右、下、左 */
margin: 70px 0px 0px 0px;
}
</style>

View File

@@ -2,10 +2,10 @@
#message_block
{
background-color: rgba(0, 0, 0, 0.68);
width: 85%;
position: fixed;
width: 1150px;
height: 100%;
margin: auto;
position: absolute;
top: 0;
left: 0;
right: 0;

View File

@@ -0,0 +1 @@
这是测试

View File

@@ -0,0 +1 @@
测试

View File

@@ -1 +1,2 @@
<!-- 域名跳转 ./blog/ -->
<meta http-equiv="refresh" content="0.1;url=https://open-ww3-project.ww3.tw/blog/">

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -0,0 +1,14 @@
<style>
#black_block
{
background-color: rgba(0, 0, 0, 0.68);
position: fixed;
width: 1150px;
height: 100%;
margin: auto;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
</style>

11
src/md/1.md Executable file
View File

@@ -0,0 +1,11 @@
# 今天、2025.7.30
----
blog 正式 完工
测试
**署名**
<br>
SkimrMe_

479
src/md/MD.php Executable file
View File

@@ -0,0 +1,479 @@
<?php
Header('Content:text/html;charset=utf-8');
?>
<meta name="viewport" content="width=device-width,initial-scale=1" />
<style>
body,ol,ul,li,img,p{
padding:0;
margin:0;
border:none;
}
li{
list-style-type: square;
padding:2px;
}
h1,h2,h3,h4,h5,h6{
margin:10px 0 0 0;
}
h1,h2,h3{
border-bottom:solid 1px #ddd;
}
h1{
padding-bottom:12px;
}
h2{
padding-bottom: 6px;
}
h3{
padding-bottom: 2px;
}
body,ul{
padding:10px 20px;
}
body{
max-width:1024px;
margin:0 auto;
}
blockquote{
border-left:solid 4px #bbb;
background-color:#eee;
min-height:24px;
line-height:24px;
padding:0px 10px;
margin:0;
color:#333;
font-size:12px;
font-style: italic;
font-family: consolas,楷体;
}
table{
width:100%;
}
table,td,th{
border:solid 1px #ddd;
border-collapse: collapse;
padding:10px;
font-family: consolas;
font-size:14px;
}
table{
margin:10px 0;
text-align:center;
}
.table-left{
text-align:left;
}
.table-center{
text-align: center;
}
.table-right{
text-align: right;
}
tr:nth-child(even){
background-color:#eee;
}
code,pre{
border-radius:5px;
border:solid 1px #eee;
background-color:#f9f9f9;
font-family: consolas;
font-size:14px;
box-shadow: 1px 2px 3px #ddd;
}
code{
padding:2px 12px;
display: inline-block;
margin:10px 0;
}
pre{
padding:10px 12px;
overflow-x:auto;
}
</style>
<?php
/*
* flag规则:
* h1-h6 标题
* u1,u2 无序列表
* ol 有序列表
* p 普通文本
* code 代码
* table 文本
* check 选择
* uncheck 未选择
* quote 引用
* img 图片
* url 网址
* bold 加粗
* italia 斜体
* el 空行
*
* idel 闲置
*/
class MD{
private $file; //当前文件
private $mdGen; //生成器
private $flag; //当前标志
private $flag_pre; //上一次的flag
private $flag_like; //假定类型
private $line_count; //总行数
private $lines; //所有行
private $buf; //缓存行
public function __construct($filename){
$this->file = $filename; //设置当前文件
$this->mdGen = $this->content($filename); //获取生成器
$this->flag = 'idel'; //闲置
$this->lines = array(); //所有行状态
$this->line_count = 0; //行数归0
}
private function content($file){ //获取生成器
if(file_exists($file)){
$fh = fopen($file,"r");
while(!feof($fh)){
yield fgets($fh);
}
fclose($fh);
}else{
return null;
}
}
//遍历每一个字符
private function every($str){
$l = strlen($str);
for($i=0;$i<$l;$i++)
if(ord($str[$i])<0x80)
yield $str[$i];
else{
yield $str[$i].$str[$i+1].$str[$i+2]; //三个字节
$i+=2;
}
}
//解析
private function parse(){
$ctnt = $this->mdGen; //生成器
$ret=array();
if($ctnt != null){
$ret = array();
foreach($ctnt as $line){
if($this->flag != 'code')
$line=ltrim($line); //删除左边
if(strlen($line)){
$ch = $line[0]; //判断第一个字符
$type=ctype_punct($ch);//标点符号
if($this->flag !== 'code') $line=preg_replace('/\s{2,}$/','<br>',$line); //非代码模式
$ret[] = $this->parseLine($line,$type); //解析行
}else{ //空行
switch($this->flag){
case 'ul':
case 'ol':
$ret[]="</$this->flag>";
$this->flag_pre = $this->flag;
$this->flag = 'idel';
break;
case 'table':
$this->flag = 'idel';
$ret[]='</table>';
break;
default:
if($this->flag != 'el') $ret[] = '<br>';
$this->flag = 'el'; //空行
}
}
}
}
$this->lines = $ret;
return $ret;
}
//生成blockquote
private function genQuote($level,$content){
if($level<=0) return "";
return str_repeat('<blockquote>',$level).$content.str_repeat('</blockquote>',$level);
}
//检查是否处于某个状态,默认检查是否处于代码状态
private function check($value='code'){
return ($this->flag == $value);
}
/**
* 生成一行新的表格列
* $data:需要输入的数据
* $type:生成类型
* $wrap:最快层包裹
* $sep:分隔符
*/
private function genRow($data,$type='td',$wrap='tr',$sep='|'){
$ret='';
$mat = explode($sep,$data);
foreach($mat as $elem)
$ret.="<$type>".$elem."</$type>";
return "<$wrap>".$ret."</$wrap>";
}
/**
* 解析行内元素
* bold,italic,code,link,pic
*/
private function parseInner($str){
$str=preg_replace('/\*\*\*([^\*\n\r]+)\*\*\*/','<b><i>\1</i></b>',$str); //加粗并加斜字体
$str=preg_replace('/\*\*([^\*\n\r]+)\*\*/','<b>\1</b>',$str); //加粗字体
$str=preg_replace('/\*([^\*\n\r]+)\*/','<i>\1</i>',$str); //斜体
$str=preg_replace('/```([^`\n\r]+)```/','<code>\1</code>',$str); //代码
$str=preg_replace('/`([^`\n\r]+)`/','<code>\1</code>',$str); //代码
$str=preg_replace('/!\[([^\]\r\n]+)\]\(([^\)\r\n]+)\)/','<img src="\2" alt="\1" title="\1">',$str); //图片
$str=preg_replace('/\[([^\]\r\n]+)\]\(([^\)\r\n]+)\)/','<a href="\2">\1</a>',$str); //图片
return $str;
}
/**
* 按照给定规则解析字符串:
* type:
* true 符号
* false 文字
* 返回:
* array('type'=>类型,'parts'=>array(...))
*/
private function parseLine($str,$type){
if(strlen($str) == 0){
return array('type'=>'p','parts'=>[]); //返回空段
}
$valid_str = rtrim($str); //去除右边的空格
$str = $valid_str;
$output = ''; //需要输出的字符串
if($type == true){ //标点
$type_str = ''; //类型字符串
$data_str = '';
$flag = 0;
foreach($this->every($str) as $ch){
if(!ctype_punct($ch)){
$flag = 1;
}
if($flag == 0)
$type_str .= $ch;
else
$data_str .= $ch;
}
switch($type_str){
case '#':
$wrap = 'h1';
$this->flag_like = 'h1';
break;
case '##':
$wrap = 'h2';
$this->flag_like = 'h2';
break;
case '###':
$wrap = 'h3';
$this->flag_like = 'h3';
break;
case '####':
$wrap = 'h4';
$this->flag_like = 'h4';
break;
case '#####':
$wrap = 'h5';
$this->flag_like = 'h5';
break;
case '######':
$wrap = 'h6';
$this->flag_like = 'h6';
break;
case '+':
case '-':
$wrap = 'li';
$this->flag_like = 'ul';
if($this->flag != 'code'){
if($this->flag != 'ul'){
$this->flag_pre = $this->flag;
$this->flag = 'ul';
$output.='<ul>';
}
}
break;
case '```': //代码模式,不进行干扰
if($this->flag != 'code'){ //不为code,判断是否为单行代码
$output.='<pre>';
if(preg_match('/^\s*```([^`]+)```([^\s]+)\s*$/',$str,$mat)){ //单行代码
$output.="$mat[1]</pre>$mat[2]";
$str = '';
$data_str = '';
}else{
$this->flag_pre = $this->flag;
$this->flag = 'code'; //代码
}
}else{
$output.='</pre>';
$this->flag_pre = $this->flag;
$this->flag = 'idel'; //闲置
}
break;
case '[':
if(preg_match('/^\[\s\]\s*(.+)$/',$str,$mat)){ //选择
$output.="<label><input type='checkbox' disabled> $mat[1]</label><br>";
$this->flag_like = 'check';
}else if(preg_match('/^\[([^\]]+)\]\(([^\)]+)\)([^\s]+)\s*$/',$str,$mat)){ //未选择
$output.="<a href='$mat[2]'>$mat[1]</a>".$this->parseInner($mat[3]);
$this->flag_like = 'a'; //网址
}else if(preg_match('/^\s*(\[\d+\]\:)\s+([^\s]+)\s+([^\r\n]+)\s*$/',$str,$mat)){ //外部资料
$output.="$mat[1] <a href='$mat[2]'>$mat[3]</a>";
}else{
$output.=$str;
}
break;
case '[-]':
$output.="<label><input type='checkbox' checked disabled>$data_str</label><br>";
$this->flag_like = 'check';
break;
case '![':
if(preg_match('/^!\[([^\]]+)\]\(([^\)]+)\)([^\s]+)\s*$/',$str,$mat)){
$output.="<img src='$mat[2]' alt='$mat[1]'>".$this->parseInner($mat[3]);
$this->flag_like = 'img';
}else{
$this->flag_like = 'p'; //没有模式
$output.="$str";
}
break;
case '*': //斜体
if(preg_match('/^\*(.*)\*([^\s]+)\s*$/',$str,$mat)){
$output.=$this->parseInner($str);
$this->flag_like = 'i';
}else if(preg_match('/^\s*\*\s+(.+)\s*$/',$str,$mat)){
$str=$mat[1];
$wrap = 'li';
$this->flag_like = 'ul';
if($this->flag != 'code'){
if($this->flag != 'ul'){
$this->flag_pre = $this->flag;
$this->flag = 'ul';
$output.='<ul>';
}
}
}
break;
case '**': //粗体
if(preg_match('/^\*\*(.*)\*\*/',$str,$mat)){
$output.=$this->parseInner($str);
$this->flag_like = 'b';
}
break;
case '<':
$output.=$str;
$this->flag_like = 'html';
break;
default:
if(!$this->check()){ //非代码模式
if(preg_match('/^>+$/',$type_str)){ //引用
$level = strlen($type_str);
$this->flag_like = 'quote';
$output.=$this->genQuote($level,$data_str); //引用
}else if(preg_match('/^([^\|\n\r]+)(?:\|[^\|\n\r]+)+$/',$str)){ //表格确定格式---|---|....
if($this->flag == 'table'){
$this->flag_like = 'table';
$output.='<table><thead>'.$this->genRow($this->buf,'th').'</thead><tbody>';
}else{ //非表格格式,上一行没有标题
$this->flag_like = 'p'; //没有格式
$output.=$this->buf;
$this->buf = '';
}
}else if(preg_match('/^\s*(\-{3,})|(\={3,})$/',$type_str)){ //hr
$output.='<hr>';
$this->flag_like = 'hr';
break;
}else{
$this->flag_like = 'p';
$output.=$str.'<br>';
}
}
}
$br = '';
preg_match('/^(.*)(<br\s*\/?>)?$/',$data_str,$mat);
$data_str = htmlspecialchars($mat[1]);
if(!$this->check()){ //代码
if(!empty($wrap)) $output.="<$wrap>$mat[1]</$wrap>".(isset($mat[2])?'<br>':'');
}else if($type_str!='```'){
$output.=htmlspecialchars($str).'<br>';
}
}else{ //首个非空字符不为符号
if($this->flag == 'code'){ //代码,直接输出
$str=str_replace("\t",' ',$str);
$output.=htmlspecialchars($str).'<br>';
}else if(is_numeric($str[0])){ //可能为有序列表,也可能是表格
if(preg_match('/^\s*\d+\.\s+([^\r\n]+)\s*$/',$str)){ //有序列表
$this->flag_like = 'ol';
$output.=$str;
}else{
$this->flag_like = 'idel';
foreach($this->every($str) as $ch){
$output.=$ch;
}
}
$output.='<br>';
}else if(preg_match('/^([^\|\n\r]+)(?:\|[^\|\n\r]+)+$/',$str)){ //表格
$mat = explode('|',$str);
if($this->flag!='table'){ //进入表格
$this->buf = $str;
$this->flag_like = 'table';
$wrap = '';
}else{
$output.=$this->genRow($str);
}
//echo $mat[0].'<br>';
//var_dump($mat);
}else{ //其他
$this->flag = 'p';
$output.=$str;
}
}
if(!$this->check()){ //不为代码,设置flag
$this->flag_pre = $this->flag;
$this->flag = $this->flag_like;
if($this->flag_pre == 'table' && $this->flag != 'table')
$output='</table>'.$output;
else if($this->flag_pre == 'ul' && $this->flag != 'ul'){
$output='</ul>'.$output;
}
}
return $this->parseInner($output); //输出需要输出的内容
}
//获取输出内容
public function output(){
$this->parse();
echo implode('',$this->lines);
}
}

6
src/md/inite.php Executable file
View File

@@ -0,0 +1,6 @@
<?php
require '/var/www/owp/open-ww3-project-ww3-tw/src/md/MD.php';
$md=new MD('/var/www/owp/open-ww3-project-ww3-tw/src/md/inte.md');
$md->output();

10
src/md/inte.md Executable file
View File

@@ -0,0 +1,10 @@
## MD介绍页面
顾名思义、本文件夹下使用的基本都是markdown
最后感谢提供php的md插件的开源制作者
[点击跳转](https://ww3.tw/blog/md/src/php-markdown/)
日期 2025.07.30

19
src/views/error/404.html Executable file
View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="zh-Hant">
<head>
<meta charset="UTF-8">
<title>404 Not Found</title>
</head>
<body>
<h1 style="font-size: 250%;">到达世界尽头,这里什么都没有哦</h1>
<a style="font-size: 150%;" href="/">返回主页</a>
</body>
</html>
<style>
body{
background-image: url(https://open-ww3-project.ww3.tw/static/error/cirno-image.jpg);
background-repeat:no-repeat;
background-size: cover;
}
</style>