#author("2022-12-28T00:02:41+09:00","","")
* #pcommentでインラインプラグインを書こうとしてセミコロンを忘れると表示が崩れる [#rfc77966]

- ページ: [[BugTrack]]
- 投稿者: [[ぬぺぺ]]
- 優先順位: 普通
- 状態: 提案
- カテゴリー: 本体バグ
- 投稿日: 2022-12-24 (土) 08:45:56
- バージョン: 1.5.4

** メッセージ [#e954d5c6]
タイトルの通りです。

#pcomment()ではコメントでwiki記法を書いてもそのまま反映がされますが、
 &plugin(){~};
とやるところを
 &plugin(){~}
とセミコロンを抜いた記述にすることで、コメントの挿入時に
 &plugin(){~} -- 名無し &new{2022/12/24 (土) 08:44:41};
となり、文末の&newのセミコロンと合体して表示が崩れます。

***対処法 [#qe246570]
うちのwikiでは以下の閉じ忘れ }; 追加関数を追加することで対処することにしました。

 /**
  * wikiソースの末尾にインラインプラグイン閉じ忘れの }; を適切な個数だけ追加する
  * @param  string $wiki_source_line wikiソース(1行)
  * @return string 末尾に }; を追加してもプラグインの範囲が延びないようにしたwikiソース
  */
 function close_forgotten_brace_semicolon($wiki_source_line) {
 	// '&' がなかったらさっさと抜ける
 	if (strpos($wiki_source_line, '&') === false) {
 		return $wiki_source_line;
 	}
 
 	// インラインプラグインのパターン
 	// make_link.php Link_plugin->get_pattern() で定義
 	$pattern = '/&\w+(?:\((?:(?!\)[;{]).)*\))?(?:\{(?:(?R)|(?!};).)*\})?;/u';
 
 	// 最終的に返す文字列の格納用
 	$return_str = $wiki_source_line;
 
 	// プラグイン文字列が変化しなくなるまで }; を末尾に追加する
 	$count1 = preg_match_all($pattern, $return_str, $matches1);
 	while (true) {
 		$count2 = preg_match_all($pattern, $return_str . '};', $matches2);
 
 		// 変化がなければ返す
 		if (
 			$count1 === $count2
 			&& ($count1 === 0 || end($matches1) === end($matches2))
 		) {
 			return $return_str;
 		}
 
 		// 変化があったので追加して継続
 		$return_str .= '};';
 		$count1 = $count2;
 		$matches1 = $matches2;
 	}
 }
 
 // テスト関数(雑)
 function test_close_forgotten_brace_semicolon() {
 	$s = [];
 	$s[] = 'abcabc';
 	$s[] = 'abc&size(12){@@@}abc';
 	$s[] = 'abc&size(12){@@@};abc';
 	$s[] = 'abc&size(12){@@@};abc&color(red){&aname(red){&ruby(red){@@@};abc';
 
 	// ↑の close_forgotten_brace_semicolon() 内定義パターン
 	$pattern = '/&\w+(?:\((?:(?!\)[;{]).)*\))?(?:\{(?:(?R)|(?!};).)*\})?;/u';
 	
 	foreach ($s as $msg1) {
 		// }; を末尾に付加
 		$msg2 = close_forgotten_brace_semicolon($msg1);  // 閉じ忘れ補完
 		$msg3 = $msg2 . '};';  // 1個余分
 
 		// カウント&インラインプラグイン文字列を取得
 		$count1 = preg_match_all($pattern, $msg1, $matches1);
 		$count2 = preg_match_all($pattern, $msg2, $matches2);
 		$count3 = preg_match_all($pattern, $msg3, $matches3);
 
 		// 補完がある場合は補完を1つ減らすと結果が変わることを確認
 		if ($msg1 !== $msg2) {
 			$msg4 = substr($msg2, 0, strlen($msg2) - 2);  // 補完後の }; を1個だけ除去したver
 			$count4 = preg_match_all($pattern, $msg4, $matches4);
 			if (
 				$count4 === $count2
 				&& ($count4 === 0 || end($matches4) === end($matches2))
 			) {
 				throw new Exception(
 					'おかしい: '
 					. json_encode($matches2)
 					. ', ' . json_encode($matches4)
 				);
 			}
 		}
 
 		// 補完を1つ増やしても結果が変わらないことを確認
 		if (
 			$count3 !== $count2
 			|| $count3 > 0 && end($matches3) !== end($matches2)
 		) {
 			throw new Exception(
 				'おかしい: '
 				. json_encode($matches2)
 				. ', ' . json_encode($matches3)
 			);
 		}
 	}
 }
 
 test_close_forgotten_brace_semicolon();

pcomment.inc.php中で
 $date = (! isset($vars['nodate']) || $vars['nodate'] != '1') ?
の前あたりに

 $msg = close_forgotten_brace_semicolon($msg);  // 追加
 
 $date = (! isset($vars['nodate']) || $vars['nodate'] != '1') ?
とやりました

--------
- 例:&color(crimson){1行で済むのがせめてもの救い}←セミコロンが無い -- [[ぬぺぺ]] &new{2022-12-24 (土) 08:49:13};
- なお、&hennna_puraguinmei(){~}というように存在しないプラグイン名だった場合は変換がされないので普通に投稿されます -- [[ぬぺぺ]] &new{2022-12-24 (土) 08:50:15};
- されてなかった。文末のnewも無変換に巻き込まれてますねこれ -- [[ぬぺぺ]] &new{2022-12-24 (土) 08:50:46};
- ありがとうございます。これはちょっと難しいですね。pcommentプラグインに限らないですが、閉じ忘れかどうか、意図的なものか、って機械的には判断できないので、入力をそのまま受け入れて実力の範囲で表示するしかないように思います -- [[umorigu]] &new{2022-12-27 (火) 22:57:19};
- ありがとうございます。確かに、入力を勝手に改変してかっこを閉じるのってちょっと強引な感じしますね… -- [[ぬぺぺ]] &new{2022-12-27 (火) 23:50:44};
- うちのwikiでどう対応するかは悩んだのですが、どちらかと言えば閉じ忘れは閉じた方がコメントプラグインとしては良いのでは、と判断して上記の対応にしました。プラグインを意図的に閉じていないことよりも、意図しない閉じ忘れの方が数は圧倒的に多いんじゃないでしょうか。wikiの記法でセミコロンが無いパターンのところもありますし…(seesaawikiとか) -- [[ぬぺぺ]] &new{2022-12-27 (火) 23:53:05};
- また、あえて開きっぱにするような上級者は投稿結果を見て「閉じ忘れだと判定されて自動で閉じられた」と判断できると思いますし、直接wikiソースを編集することで意図通りのコメントに戻すんじゃないかと思います。 -- [[ぬぺぺ]] &new{2022-12-27 (火) 23:55:29};

#comment

トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Site admin: PukiWiki Development Team

PukiWiki 1.5.4+ © 2001-2022 PukiWiki Development Team. Powered by PHP 8.2.12. HTML convert time: 0.342 sec.

SourceForge