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 .= '' . ($left['line'] ?: ' ') . ' ';
- $html .= '' . ($left['content'] ?: ' ') . ' ';
+ $html .= " ".($left['line'] ?: ' ')." \n";
+ $html .= " ".($left['content'] ?: ' ')." \n";
// 右(変更後)
- $html .= '' . ($right['line'] ?: ' ') . ' ';
- $html .= '' . ($right['content'] ?: ' ') . ' ';
- $html .= ' ';
+ $html .= " ".($right['line'] ?: ' ')." \n";
+ $html .= " ".($right['content'] ?: ' ')." \n";
+ $html .= " \n";
}
- $html .= '
';
+ $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 .= "{$currentType}>";
+ $html .= " {$currentType}>\n ";
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 "{$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 .= " ".$this->parseInline($header)." \n";
+ $html .= " ".$this->parseInline($header)." \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 .= " ".$this->parseInline($cell)." \n";
+ $html .= " ".$this->parseInline($cell)." \n";
}
- $html .= " \n";
+ $html .= " \n";
}
- $html .= " \n";
+ $html .= " \n";
}
- $html .= "
";
+ $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 != '') @}
-
{{{ $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 @@
- Copyright{{ defined('COPYRIGHT_YEAR') ? ' '.COPYRIGHT_YEAR : '' }} © 076スタジオ合同会社
+
+ Copyright{{ defined('COPYRIGHT_YEAR') ? ' '.COPYRIGHT_YEAR : '' }} © 076スタジオ合同会社
Powered By Little Beast
+