From 4f70e6d4e4717aa3c3df7466e331b3aea7d9a5f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AB=8F=E8=A8=AA=E5=AD=90?= Date: Thu, 20 Nov 2025 22:39:28 +0900 Subject: [PATCH] =?UTF-8?q?HTML=E3=82=92=E7=B6=BA=E9=BA=97=E3=81=AB?= =?UTF-8?q?=E3=80=81=E8=89=B2=E3=82=93=E3=81=AA=E3=83=86=E3=82=B9=E3=83=88?= =?UTF-8?q?=E9=96=A2=E4=BF=82=E9=96=A2=E6=95=B0=E3=81=AE=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- blog/feature-test.md | 2 +- src/Site/Lib/DiffViewer.php | 20 +++++++------- src/Site/Lib/Markdown.php | 54 ++++++++++++++++++------------------- src/Site/Lib/Mysql.php | 38 +++++++++++++------------- src/Site/Lib/Tester.php | 44 +++++++++++++++++++++++++++++- src/Site/Test/LibMysql.php | 4 ++- tester.php | 2 ++ util.php | 30 +++++++++++++++++++++ view/article.maron | 12 +++------ view/common/footer.maron | 4 ++- view/common/header.maron | 6 +++-- 11 files changed, 145 insertions(+), 71 deletions(-) diff --git a/blog/feature-test.md b/blog/feature-test.md index 737d1ce..ee9ee31 100644 --- a/blog/feature-test.md +++ b/blog/feature-test.md @@ -56,7 +56,7 @@ $[audio/ogg](https://ass.technicalsuwako.moe/砕月着信音.ogg)\ ##### ケロケロ [076スタジオ合同会社](https://076.moe/)\ <諏訪子>(すわこ)\ -`int i = 0;`\ +`int i = 0;` ###### ケロケロ 1. アセンブリ言語 diff --git a/src/Site/Lib/DiffViewer.php b/src/Site/Lib/DiffViewer.php index 07f8b82..e49e0fb 100644 --- a/src/Site/Lib/DiffViewer.php +++ b/src/Site/Lib/DiffViewer.php @@ -69,7 +69,7 @@ class DiffViewer { // 各ファイルにHTMLの出力の作成 $html = ''; foreach ($fileDiffs as $fileName => $diff) { - $html .= "

ファイル: ".htmlspecialchars($fileName)."

\n"; + $html .= "\n

ファイル: ".htmlspecialchars($fileName)."

\n"; $html .= $this->generateHtml($diff['leftLines'], $diff['rightLines']); } @@ -106,25 +106,25 @@ class DiffViewer { } private function generateHtml(array $leftLines, array $rightLines): string { - $html = ''; - $html .= ''; + $html = "

\n

\n"; + $html .= " \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 .= ''; + $html .= " \n"; // 左(変更前) - $html .= ''; - $html .= ''; + $html .= " \n"; + $html .= " \n"; // 右(変更後) - $html .= ''; - $html .= ''; - $html .= ''; + $html .= " \n"; + $html .= " \n"; + $html .= " \n"; } - $html .= '
' . ($left['line'] ?: ' ') . '' . ($left['content'] ?: ' ') . '".($left['line'] ?: ' ')."".($left['content'] ?: ' ')."' . ($right['line'] ?: ' ') . '' . ($right['content'] ?: ' ') . '
".($right['line'] ?: ' ')."".($right['content'] ?: ' ')."
'; + $html .= " \n

\n"; return $html; } } \ No newline at end of file diff --git a/src/Site/Lib/Markdown.php b/src/Site/Lib/Markdown.php index aa8f7fd..ad6c945 100644 --- a/src/Site/Lib/Markdown.php +++ b/src/Site/Lib/Markdown.php @@ -98,7 +98,7 @@ class Markdown { if (preg_match('/^```(\w*)$/', $line, $matches)) { if (!$this->inCodeBlock) { if (!empty($currentParagraph)) { - $this->html[] = "

".implode("", $currentParagraph)."

"; + $this->html[] = "

\n ".implode("", $currentParagraph)."\n

"; $currentParagraph = []; } $this->inCodeBlock = true; @@ -121,7 +121,7 @@ class Markdown { // テーブルの処理 if (preg_match('/^\|(.+)\|$/', $line)) { if (!empty($currentParagraph)) { - $this->html[] = "

".implode("", $currentParagraph)."

"; + $this->html[] = "

\n ".implode("", $currentParagraph)."\n

"; $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[] = "

".implode("", $currentParagraph)."

"; + $this->html[] = "

\n ".implode("", $currentParagraph)."\n

"; $currentParagraph = []; } - $this->html[] = "
"; + $this->html[] = "
\n"; continue; } // 引用ブロックの処理 if (preg_match('/^>\s(.+)/', $line, $matches)) { if (!empty($currentParagraph)) { - $this->html[] = "

".implode("", $currentParagraph)."

"; + $this->html[] = "

\n ".implode("", $currentParagraph)."\n

"; $currentParagraph = []; } $inBlockquote = true; @@ -176,7 +176,7 @@ class Markdown { $inList = false; } if (!empty($currentParagraph)) { - $this->html[] = "

".implode("", $currentParagraph)."

"; + $this->html[] = "

\n ".implode("", $currentParagraph)."\n

"; $currentParagraph = []; } @@ -191,19 +191,19 @@ class Markdown { $inList = false; } if (!empty($currentParagraph)) { - $this->html[] = "

".implode("", $currentParagraph)."

"; + $this->html[] = "

\n ".implode("", $currentParagraph)."\n

"; $currentParagraph = []; } $level = strlen($m[1]); - $this->html[] = "".$this->parseInline($m[2]).""; + $this->html[] = " ".$this->parseInline($m[2]).""; continue; } // 箇条書きリスト if (preg_match('/^(\s*)([\*\-])\s(.+)/', $line, $m)) { if (!empty($currentParagraph)) { - $this->html[] = "

".implode("", $currentParagraph)."

"; + $this->html[] = "

\n ".implode("", $currentParagraph)."\n

"; $currentParagraph = []; } $inList = true; @@ -221,7 +221,7 @@ class Markdown { // 番号付きリスト if (preg_match('/^(\s*)\d+\.\s(.+)/', $line, $m)) { if (!empty($currentParagraph)) { - $this->html[] = "

".implode("", $currentParagraph)."

"; + $this->html[] = "

\n ".implode("", $currentParagraph)."\n

"; $currentParagraph = []; } $inList = true; @@ -246,7 +246,7 @@ class Markdown { $parsedLine = $this->parseInline($line); $currentParagraph[] = $parsedLine; if ($hasBR) { - $currentParagraph[] = "
"; + $currentParagraph[] = "
\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[] = "

".implode("", $currentParagraph)."

"; + $this->html[] = "

\n ".implode("", $currentParagraph)."\n

"; return implode("\n", $this->html); } @@ -456,11 +456,11 @@ class Markdown { $currentType = $item['type']; } - $html .= "<{$currentType}>\n"; + $html .= "

\n <{$currentType}>\n"; foreach ($items as $item) { - $html .= str_repeat(' ', $currentLevel)."

  • ".$item['content']."
  • \n"; + $html .= str_repeat(' ', $currentLevel)."
  • ".$item['content']."
  • \n"; } - $html .= ""; + $html .= " \n

    "; while (!empty($listStack)) { $html .= str_repeat(' ', $currentLevel)."\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 "
    {$code}
    "; + return "

    \n

    {$code}
    "; // $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 "
    \n

    ".implode("

    \n

    ", $content)."

    \n
    "; + return "

    \n

    \n ".implode("
    \n ", $content)."\n
    \n

    "; } /** @@ -498,31 +498,31 @@ class Markdown { * @return string HTMLのテーブル */ private function createTable(array $headers, array $rows): string { - $html = "\n"; + $html = "

    \n

    \n"; // ヘッダーを追加 if (!empty($headers)) { - $html .= " \n \n"; + $html .= " \n \n"; foreach ($headers as $header) { - $html .= " \n"; + $html .= " \n"; } - $html .= " \n \n"; + $html .= " \n \n"; } // 行を追加 if (!empty($rows)) { - $html .= " \n"; + $html .= " \n"; foreach ($rows as $row) { - $html .= " \n"; + $html .= " \n"; foreach ($row as $cell) { - $html .= " \n"; + $html .= " \n"; } - $html .= " \n"; + $html .= " \n"; } - $html .= " \n"; + $html .= " \n"; } - $html .= "
    ".$this->parseInline($header)."".$this->parseInline($header)."
    ".$this->parseInline($cell)."".$this->parseInline($cell)."
    "; + $html .= " \n

    "; return $html; } diff --git a/src/Site/Lib/Mysql.php b/src/Site/Lib/Mysql.php index 381deef..b8ece18 100644 --- a/src/Site/Lib/Mysql.php +++ b/src/Site/Lib/Mysql.php @@ -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); } diff --git a/src/Site/Lib/Tester.php b/src/Site/Lib/Tester.php index 41222ad..193e81a 100644 --- a/src/Site/Lib/Tester.php +++ b/src/Site/Lib/Tester.php @@ -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 */ diff --git a/src/Site/Test/LibMysql.php b/src/Site/Test/LibMysql.php index 1bb1d1f..664a60b 100644 --- a/src/Site/Test/LibMysql.php +++ b/src/Site/Test/LibMysql.php @@ -61,4 +61,6 @@ $test->describe('プリペアドステートメント', function($test): void { } catch (\Exception $e) { echo 'エラー: '.$e->getMessage()."\n"; } -}); \ No newline at end of file +}); + +$test->printSummary(); \ No newline at end of file diff --git a/tester.php b/tester.php index b5568da..b2e81ee 100644 --- a/tester.php +++ b/tester.php @@ -1,5 +1,7 @@ = 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); + } +} \ No newline at end of file diff --git a/view/article.maron b/view/article.maron index dc508c0..5f5ffbf 100644 --- a/view/article.maron +++ b/view/article.maron @@ -1,6 +1,5 @@ {@ include(common/header) @} {@ include(common/search) @} -
    {@ if (isset($meta->thumbnail) && $meta->thumbnail != '') @}
    @@ -12,16 +11,11 @@
    {{ $meta->author }}
    {@ if (isset($meta->category) && !empty($meta->category) && $meta->category[0] !== '') @} {@ foreach ($meta->category as $cat) @} -
    - {{ $cat }} - -
    +
    {{ $cat }}
    {@ endforeach @} {@ endif @}
    -

    {{{ $meta->title }}}

    -{{{ $article }}} - +{{{ $article."\n" }}}
    -{@ include(common/footer) @} +{@ include(common/footer) @} \ No newline at end of file diff --git a/view/common/footer.maron b/view/common/footer.maron index 3f6dd67..d0f012c 100644 --- a/view/common/footer.maron +++ b/view/common/footer.maron @@ -1,7 +1,9 @@ diff --git a/view/common/header.maron b/view/common/header.maron index 696a739..616742a 100644 --- a/view/common/header.maron +++ b/view/common/header.maron @@ -12,13 +12,15 @@ {@ endforeach @} {@ endif @} {@ if (isset($meta)) @} +{@ if (isset($meta->author)) @} +{@ endif @} {@ if (isset($meta->thumbnail)) @} {@ endif @} {@ endif @} - + @@ -46,7 +48,7 @@