HTMLを綺麗に、色んなテスト関係関数の修正

This commit is contained in:
2025-11-20 22:39:28 +09:00
parent 8513c530f5
commit 4f70e6d4e4
11 changed files with 145 additions and 71 deletions

View File

@@ -56,7 +56,7 @@ $[audio/ogg](https://ass.technicalsuwako.moe/砕月着信音.ogg)\
##### ケロケロ
[076スタジオ合同会社](https://076.moe/)\
<諏訪子>(すわこ)\
`int i = 0;`\
`int i = 0;`
###### ケロケロ
1. アセンブリ言語

View File

@@ -69,7 +69,7 @@ class DiffViewer {
// 各ファイルにHTMLの出力の作成
$html = '';
foreach ($fileDiffs as $fileName => $diff) {
$html .= "<h2>ファイル: ".htmlspecialchars($fileName)."</h2>\n";
$html .= "\n <h2>ファイル: ".htmlspecialchars($fileName)."</h2>\n";
$html .= $this->generateHtml($diff['leftLines'], $diff['rightLines']);
}
@@ -106,25 +106,25 @@ class DiffViewer {
}
private function generateHtml(array $leftLines, array $rightLines): string {
$html = '<table class="diff-table">';
$html .= '<tr class="diff-header"><th colspan="2">前</th><th colspan="2">新</th></tr>';
$html = " <p>\n <table class=\"diff-table\">\n";
$html .= " <tr class=\"diff-header\"><th colspan=\"2\">前</th><th colspan=\"2\">新</th></tr>\n";
$maxLines = max(count($leftLines), count($rightLines));
for ($i = 0; $i < $maxLines; $i++) {
$left = isset($leftLines[$i]) ? $leftLines[$i] : ['content' => '', 'type' => 'empty', 'line' => ''];
$right = isset($rightLines[$i]) ? $rightLines[$i] : ['content' => '', 'type' => 'empty', 'line' => ''];
$html .= '<tr>';
$html .= " <tr>\n";
// 左(変更前)
$html .= '<td class="line-number">' . ($left['line'] ?: '&nbsp;') . '</td>';
$html .= '<td class="' . $left['type'] . '">' . ($left['content'] ?: '&nbsp;') . '</td>';
$html .= " <td class=\"line-number\">".($left['line'] ?: '&nbsp;')."</td>\n";
$html .= " <td class=\"{$left['type']}\">".($left['content'] ?: '&nbsp;')."</td>\n";
// 右(変更後)
$html .= '<td class="line-number">' . ($right['line'] ?: '&nbsp;') . '</td>';
$html .= '<td class="' . $right['type'] . '">' . ($right['content'] ?: '&nbsp;') . '</td>';
$html .= '</tr>';
$html .= " <td class=\"line-number\">".($right['line'] ?: '&nbsp;')."</td>\n";
$html .= " <td class=\"{$right['type']}\">".($right['content'] ?: '&nbsp;')."</td>\n";
$html .= " </tr>\n";
}
$html .= '</table>';
$html .= " </table>\n </p>\n";
return $html;
}
}

View File

@@ -98,7 +98,7 @@ class Markdown {
if (preg_match('/^```(\w*)$/', $line, $matches)) {
if (!$this->inCodeBlock) {
if (!empty($currentParagraph)) {
$this->html[] = " <p>".implode("", $currentParagraph)."</p>";
$this->html[] = " <p>\n ".implode("", $currentParagraph)."\n </p>";
$currentParagraph = [];
}
$this->inCodeBlock = true;
@@ -121,7 +121,7 @@ class Markdown {
// テーブルの処理
if (preg_match('/^\|(.+)\|$/', $line)) {
if (!empty($currentParagraph)) {
$this->html[] = " <p>".implode("", $currentParagraph)."</p>";
$this->html[] = " <p>\n ".implode("", $currentParagraph)."\n </p>";
$currentParagraph = [];
}
$cells = array_map('trim', explode('|', trim($line, '|')));
@@ -145,17 +145,17 @@ class Markdown {
// 水平線の処理
if (preg_match('/^([\-\*\_])\1{2,}$/', $line)) {
if (!empty($currentParagraph)) {
$this->html[] = " <p>".implode("", $currentParagraph)."</p>";
$this->html[] = " <p>\n ".implode("", $currentParagraph)."\n </p>";
$currentParagraph = [];
}
$this->html[] = "<hr>";
$this->html[] = " <hr />\n";
continue;
}
// 引用ブロックの処理
if (preg_match('/^>\s(.+)/', $line, $matches)) {
if (!empty($currentParagraph)) {
$this->html[] = " <p>".implode("", $currentParagraph)."</p>";
$this->html[] = " <p>\n ".implode("", $currentParagraph)."\n </p>";
$currentParagraph = [];
}
$inBlockquote = true;
@@ -176,7 +176,7 @@ class Markdown {
$inList = false;
}
if (!empty($currentParagraph)) {
$this->html[] = " <p>".implode("", $currentParagraph)."</p>";
$this->html[] = " <p>\n ".implode("", $currentParagraph)."\n </p>";
$currentParagraph = [];
}
@@ -191,19 +191,19 @@ class Markdown {
$inList = false;
}
if (!empty($currentParagraph)) {
$this->html[] = " <p>".implode("", $currentParagraph)."</p>";
$this->html[] = " <p>\n ".implode("", $currentParagraph)."\n </p>";
$currentParagraph = [];
}
$level = strlen($m[1]);
$this->html[] = "<h{$level}>".$this->parseInline($m[2])."</h{$level}>";
$this->html[] = " <h{$level}>".$this->parseInline($m[2])."</h{$level}>";
continue;
}
// 箇条書きリスト
if (preg_match('/^(\s*)([\*\-])\s(.+)/', $line, $m)) {
if (!empty($currentParagraph)) {
$this->html[] = " <p>".implode("", $currentParagraph)."</p>";
$this->html[] = " <p>\n ".implode("", $currentParagraph)."\n </p>";
$currentParagraph = [];
}
$inList = true;
@@ -221,7 +221,7 @@ class Markdown {
// 番号付きリスト
if (preg_match('/^(\s*)\d+\.\s(.+)/', $line, $m)) {
if (!empty($currentParagraph)) {
$this->html[] = " <p>".implode("", $currentParagraph)."</p>";
$this->html[] = " <p>\n ".implode("", $currentParagraph)."\n </p>";
$currentParagraph = [];
}
$inList = true;
@@ -246,7 +246,7 @@ class Markdown {
$parsedLine = $this->parseInline($line);
$currentParagraph[] = $parsedLine;
if ($hasBR) {
$currentParagraph[] = "<br />";
$currentParagraph[] = "<br />\n ";
}
}
@@ -254,7 +254,7 @@ class Markdown {
if ($inBlockquote) $this->html[] = $this->createBlockquote($blockquoteContent);
if ($inTable) $this->html[] = $this->createTable($tableHeaders, $tableRows);
if (!empty($currentParagraph))
$this->html[] = " <p>".implode("", $currentParagraph)."</p>";
$this->html[] = " <p>\n ".implode("", $currentParagraph)."\n </p>";
return implode("\n", $this->html);
}
@@ -456,11 +456,11 @@ class Markdown {
$currentType = $item['type'];
}
$html .= "<{$currentType}>\n";
$html .= " <p>\n <{$currentType}>\n";
foreach ($items as $item) {
$html .= str_repeat(' ', $currentLevel)." <li>".$item['content']."</li>\n";
$html .= str_repeat(' ', $currentLevel)." <li>".$item['content']."</li>\n";
}
$html .= "</{$currentType}>";
$html .= " </{$currentType}>\n </p>";
while (!empty($listStack)) {
$html .= str_repeat(' ', $currentLevel)."</".array_pop($listStack).">\n";
@@ -478,7 +478,7 @@ class Markdown {
private function createCodeBlock(): string {
$code = htmlspecialchars(implode("\n", $this->codeBlockContent));
$class = $this->codeBlockLanguage ? " class=\"language-{$this->codeBlockLanguage}\"" : '';
return "<pre><code{$class}>{$code}</code></pre>";
return " <p>\n <pre><code{$class}>{$code}</code></pre>";
// $raw = implode("\n", $this->codeBlockContent);
// $lang = $this->codeBlockLanguage ?: 'txt';
// $class = $lang === 'txt' ? '' : " class=\"language-{$lang}\"";
@@ -487,7 +487,7 @@ class Markdown {
}
private function createBlockquote(array $content): string {
return "<blockquote>\n <p>".implode("</p>\n <p>", $content)."</p>\n</blockquote>";
return " <p>\n <blockquote>\n ".implode("<br />\n ", $content)."\n </blockquote>\n </p>";
}
/**
@@ -498,31 +498,31 @@ class Markdown {
* @return string HTMLのテーブル
*/
private function createTable(array $headers, array $rows): string {
$html = "<table>\n";
$html = " <p>\n <table>\n";
// ヘッダーを追加
if (!empty($headers)) {
$html .= " <thead>\n <tr>\n";
$html .= " <thead>\n <tr>\n";
foreach ($headers as $header) {
$html .= " <th>".$this->parseInline($header)."</th>\n";
$html .= " <th>".$this->parseInline($header)."</th>\n";
}
$html .= " </tr>\n </thead>\n";
$html .= " </tr>\n </thead>\n";
}
// 行を追加
if (!empty($rows)) {
$html .= " <tbody>\n";
$html .= " <tbody>\n";
foreach ($rows as $row) {
$html .= " <tr>\n";
$html .= " <tr>\n";
foreach ($row as $cell) {
$html .= " <td>".$this->parseInline($cell)."</td>\n";
$html .= " <td>".$this->parseInline($cell)."</td>\n";
}
$html .= " </tr>\n";
$html .= " </tr>\n";
}
$html .= " </tbody>\n";
$html .= " </tbody>\n";
}
$html .= "</table>";
$html .= " </table>\n </p>";
return $html;
}

View File

@@ -81,7 +81,7 @@ class Mysql {
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if ($this->socket === false) {
$msg = 'ソケットの作成に失敗: '.socket_strerror(socket_last_error());
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -89,7 +89,7 @@ class Mysql {
if ($res === false) {
$msg = 'ソケットに接続に失敗: '
.socket_strerror(socket_last_error($this->socket));
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -102,7 +102,7 @@ class Mysql {
$code = unpack('v', substr($response, 1, 2))[1];
$mes = substr($response, 3);
$msg = "認証応答に失敗: {$code} - {$mes}";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -151,7 +151,7 @@ class Mysql {
$code = unpack('v', substr($res, 1, 2))[1];
$mes = substr($res, 3);
$msg = "データベースの選択に失敗: {$code} - {$mes}";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -179,7 +179,7 @@ class Mysql {
$code = unpack('v', substr($res, 1, 2))[1];
$mes = substr($res, 3);
$msg = "準備に失敗: {$code} - {$mes}";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -236,14 +236,14 @@ class Mysql {
if (!isset($this->prepared[$statementId])) {
$msg = "不正なステートメントID: {$statementId}";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
$stmtInfo = $this->prepared[$statementId];
if (count($params) != $stmtInfo['num_params']) {
$msg = "パラメータ数が一致しません: 期待 {$stmtInfo['num_params']}, 取得 ".count($params);
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -341,7 +341,7 @@ class Mysql {
$code = unpack('v', substr($res, 1, 2))[1];
$mes = substr($res, 3);
$msg = "実行に失敗: {$code} - {$mes}";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -389,7 +389,7 @@ class Mysql {
$code = unpack('v', substr($res, 1, 2))[1];
$mes = substr($res, 3);
$msg = "クエリに失敗: {$code} - {$mes}";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -402,7 +402,7 @@ class Mysql {
// @todo LOCAL INFILEリクエストの処理を実装
if (ord($res[0]) === 0xFB) {
$msg = "LOCAL INFOリクエストは未対応です";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -490,7 +490,7 @@ class Mysql {
$mes = substr($res, 3);
$this->close();
$msg = "認証に失敗: {$code} - {$mes}";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -518,7 +518,7 @@ class Mysql {
$eofPacket = $this->readPacket();
if (ord($eofPacket[0]) !== 0xFE) {
$msg = "フィールド説明の後にEOFパケットが期待されます";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -664,7 +664,7 @@ class Mysql {
private function parseOkPacket(string $packet): array {
if (strlen($packet) < 2) {
$msg = "OKパケットが短すぎます: ".strlen($packet)."バイト";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -678,7 +678,7 @@ class Mysql {
if (strlen($packet) < $pos + 2) {
$msg = "OKパケットにサーバーステータス用のデータが不足しています";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
$serverStatus = unpack('v', substr($packet, $pos, 2))[1];
@@ -686,7 +686,7 @@ class Mysql {
if (strlen($packet) < $pos + 2) {
$msg = "OKパケットに警告カウント用のデータが不足しています";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
$warningCount = unpack('v', substr($packet, $pos, 2))[1];
@@ -712,7 +712,7 @@ class Mysql {
$bytesRead = socket_recv($this->socket, $header, 4, MSG_WAITALL);
if ($bytesRead !== 4) {
$msg = "パケットヘッダーの読み込みに失敗: 期待 4 バイト, 取得 {$bytesRead}";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -738,7 +738,7 @@ class Mysql {
if ($bytesRead === false) {
$msg = "パケット内容の読み込みに失敗: エラー "
.socket_strerror(socket_last_error($this->socket));
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -811,7 +811,7 @@ class Mysql {
$sent = socket_write($this->socket, $header, 4);
if ($sent !== 4) {
$msg = "パケットヘッダーの送信に失敗";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}
@@ -819,7 +819,7 @@ class Mysql {
$sent = socket_write($this->socket, $data, $len);
if ($sent !== $len) {
$msg = "パケットデータの送信に失敗";
logger(\LogType::MySQL, $msg);
\logger(\LogType::MySQL, $msg);
throw new \Exception($msg);
}

View File

@@ -19,6 +19,7 @@ class Tester {
private bool $colorOutput = true;
private bool $verboseOutput = true;
private bool $stopOnFailure = false;
private bool $skipCurrentDescribe = false;
private array $beforeEachCallbacks = [];
private array $afterEachCallbacks = [];
private array $beforeAllCallbacks = [];
@@ -119,6 +120,7 @@ class Tester {
*/
public function describe(string $description, callable $callback): Tester {
$this->currentTestCase = $description;
$this->skipCurrentDescribe = false;
$this->output($this->colorize('bold', "テストケース: {$description}"));
try {
@@ -149,6 +151,11 @@ class Tester {
* @return Tester このインスタンス
*/
public function it(string $description, callable $callback): Tester {
if ($this->skipCurrentDescribe) {
$this->skip($description, 'skipAll() が呼び出されました');
return $this;
}
$this->currentTest = $description;
$this->testCount++;
@@ -435,7 +442,42 @@ class Tester {
}
/**
* Print a summary of the test results
* コレクションが指定された要素数を持つ事
*
* @param int $expoected 期待される要素数
* @param iterable $collection 配列または Traversable
* @param string|null $message 失敗時のカスタムメッセージ
* @return Tester
*
* @throws AssertionFailedException
*/
public function assertCount(int $expected, iterable $collection, ?string $message = null): Tester {
$actual = is_countable($collection) ? count($collection) : iterator_count($collection);
if ($actual !== $expected) {
$message ??= "要素数が {$expected} であることを期待しましたが、{$actual} でした";
throw new AssertionFailedException($message);
}
return $this;
}
/**
* 現在の describe ブロック内の残りすべての it() をスキップ
*
* @param string $reason スキップ理由(出力に表示)
* @return void
*/
public function skipAll(string $reason = 'このテストケースはスキップされました'): void {
$this->skipCurrentDescribe = true;
if ($this->verboseOutput) {
$this->output($this->colorize('cyan', " スキップAll: {$reason}"));
}
}
/**
* テスト結果の詳細を表示する
*
* @return Tester
*/

View File

@@ -61,4 +61,6 @@ $test->describe('プリペアドステートメント', function($test): void {
} catch (\Exception $e) {
echo 'エラー: '.$e->getMessage()."\n";
}
});
});
$test->printSummary();

View File

@@ -1,5 +1,7 @@
<?php
require_once __DIR__.DIRECTORY_SEPARATOR.'/autoload.php';
define('ROOT', realpath(__DIR__));
require_once __DIR__.DIRECTORY_SEPARATOR.'/config/config.php';
$testDir = __DIR__.DIRECTORY_SEPARATOR.'src/Site/Test';
$testFiles = glob($testDir.'/*.php');

View File

@@ -61,3 +61,33 @@ function logger(LogType $section, mixed $arg): void {
file_put_contents($logfile, $arg."\n", FILE_APPEND);
}
}
function to_money($amount, $lang) {
$amount = floatval($amount);
switch (strtolower($lang)) {
case 'ja':
if ($amount >= 100000000) {
$oku = $amount / 100000000;
return $oku.'億円';
} else if ($amount >= 10000) {
$man = $amount / 10000;
return $man.'万円';
}
return number_format($amount, 0).'円';
case 'en':
if ($amount >= 1000000000) {
$billion = $amount / 1000000000;
return '¥ '.$billion.' billion';
} else if ($amount >= 1000000) {
$million = $amount / 1000000;
return '¥ '.$million.' million';
} else if ($amount >= 1000) {
$thousand = $amount / 1000;
return '¥ '.$thousand.' thousand';
}
return '¥ '.number_format($amount, 0);
default:
return '¥ '.number_format($amount, 0);
}
}

View File

@@ -1,6 +1,5 @@
{@ include(common/header) @}
{@ include(common/search) @}
<div class="news-article">
{@ if (isset($meta->thumbnail) && $meta->thumbnail != '') @}
<div class="thumbnail{{ isset($meta->thumborient) && $meta->thumborient != 'center' ? ' '.$meta->thumborient : '' }}">
@@ -12,16 +11,11 @@
<div class="meta-author">{{ $meta->author }}</div>
{@ if (isset($meta->category) && !empty($meta->category) && $meta->category[0] !== '') @}
{@ foreach ($meta->category as $cat) @}
<div class="meta-category">
{{ $cat }}
</div>
<div class="meta-category">{{ $cat }}</div>
{@ endforeach @}
{@ endif @}
</div>
<h1 class="title">{{{ $meta->title }}}</h1>
{{{ $article }}}
{{{ $article."\n" }}}
</div>
{@ include(common/footer) @}
{@ include(common/footer) @}

View File

@@ -1,7 +1,9 @@
</main>
<footer>
<address>Copyright{{ defined('COPYRIGHT_YEAR') ? ' '.COPYRIGHT_YEAR : '' }} © <a href="https://076.moe/">076スタジオ合同会社</a></address><br />
<address>
Copyright{{ defined('COPYRIGHT_YEAR') ? ' '.COPYRIGHT_YEAR : '' }} © <a href="https://076.moe/">076スタジオ合同会社</a><br />
Powered By <a href="https://technicalsuwako.moe/littlebeast">Little Beast</a>
</address>
</footer>
</div>
</body>

View File

@@ -12,13 +12,15 @@
{@ endforeach @}
{@ endif @}
{@ if (isset($meta)) @}
{@ if (isset($meta->author)) @}
<meta name="author" content="{{ $meta->author }}" />
{@ endif @}
{@ if (isset($meta->thumbnail)) @}
<meta name="thumbnail" content="/static/{{ $meta->thumbnail }}" />
{@ endif @}
{@ endif @}
<meta name="description" content="{{ $description }}" />
<meta name="keywords" content="{{ SITEINFO['tags'].',' }}{@ if (isset($meta)) @}{@ foreach ($meta->category as $cat) @}{{ $cat.',' }}{@ endforeach @}{@ endif @}" />
<meta name="keywords" content="{{ SITEINFO['tags'].(isset($meta->category) ? ',' : '') }}{@ if (isset($meta) && isset($meta->category)) @}{@ foreach ($meta->category as $k => $cat) @}{{ $cat.($k === array_key_last($meta->category) ? '' : ',') }}{@ endforeach @}{@ endif @}" />
<meta property="og:title" content="{{ SITEINFO['title'] }}: {{ $pagetit }}" />
<meta property="og:description" content="{{ $description }}" />
@@ -46,7 +48,7 @@
<div class="container">
<header>
<div class="logo">
{{ SITEINFO['title'] }}
{{ SITEINFO['title'] }}{{ "\n" }}
</div>
<nav>
{@ foreach ($menu as $m) @}