コンテンツの折りたたみと展開をするプラグインを作ってみました。

コンテンツの折り畳みと展開を行うPukiwikiプラグインをリリースします。
http://pigs.sourceforge.jp/wiki/index.php?Pukiwiki%20plugins

Pukiwik本家にコミットするかは未定です。

<?php
/** fold / unfold plugin
 *
 * <code>
 * 	usecase1: inline
 *		#fold(folded message,Hello World!)
 *
 * 	usecase2: with pukiwiki syntax
 *		#fold(**folded message,''Hello World!'')
 *
 *	usecase3: multi line
 *		#fold{{{
 *			folded message
 *			Hello
 *			World!
 *		}}}
 * </code>
 *
 * @version 1.0
 * @author uupaa
 */
define('PLUGIN_FOLD_PLUS_ICON_URL',  'url(image/728.gif)');
define('PLUGIN_FOLD_MINUS_ICON_URL', 'url(image/729.gif)');

function plugin_fold_convert() {
	static $first = 0; // at first call

	$rv = $title = $body = '';
	$args = func_get_args();

	if (!$first++) {
		$rv .= plugin_fold_css() . plugin_fold_js();
	}
	if (func_num_args() > 1) {
		$title = array_shift($args);
		$body = join(',', $args);
	} else {
		$body = str_replace(array(chr(0x0d) . chr(0x0a), chr(0x0d), chr(0x0a)), "\n", $args[0]);
		list($title, $body) = explode("\n", $body, 2);
	}
	return $rv . plugin_fold_contents('plugin_fold_anchor' . $first, convert_html($title), convert_html($body));
}

/** implant contents part */
function plugin_fold_contents($anchor, $title, $body) {
	return <<< EOS
<a name="{$anchor}"></a>
<div class="plugin_fold_title_plus" onclick="return plugin_fold_onclick(this,event,'{$anchor}')">$title</div>
<div class="plugin_fold_body">{$body}</div>
EOS;
}

/** CSS part */
function plugin_fold_css() {
	$plus  = PLUGIN_FOLD_PLUS_ICON_URL;
	$minus = PLUGIN_FOLD_MINUS_ICON_URL;

	return <<< EOS
<style type="text/css">
.plugin_fold_title_plus {
	margin: 0; padding: 0 0 0 17px;
	background: transparent {$plus} no-repeat scroll left top;
}
.plugin_fold_title_minus {
	margin: 0; padding: 0 0 0 17px;
	background: transparent {$minus} no-repeat scroll left top;
}
.plugin_fold_body {
	display: none;
	margin: 0 0 5px 17px; padding: 1em;
	border-top: 1px solid gray;
	border-left: 1px solid gray;
	background-color: #f0f8ff;
}
</style>
EOS;
}

/* JavaScript part */
function plugin_fold_js() {
	return <<< EOS
<script type="text/javascript">
function plugin_fold_onclick(titleElement, event, anchor) {
	var evt = event || window.event;

	if (!evt.altKey && !evt.shiftKey) {
		plugin_fold_toggle(titleElement);
	} else { // all fold / unfold
		plugin_fold_toggleAll(titleElement);
		location.hash = "#" + anchor; // scroll to anchor
	}
	return false;
}
function plugin_fold_toggle(titleElement) {
	var body = plugin_fold_searchBodyElement(titleElement);
	var disp = (body.style.display == "block");
	titleElement.className = (disp) ? "plugin_fold_title_plus" : "plugin_fold_title_minus";
	body.style.display = (disp) ? "none" : "block";
}
function plugin_fold_toggleAll(titleElement) {
	var body;
	var disp = (plugin_fold_searchBodyElement(titleElement).style.display == "block");
	var titles = plugin_fold_enumTitleElement(), i = 0;
	for (; i < titles.length; ++i) {
		body = plugin_fold_searchBodyElement(titles[i]);
		titles[i].className = (disp) ? "plugin_fold_title_plus" : "plugin_fold_title_minus";
		body.style.display = (disp) ? "none" : "block";
	}
}
function plugin_fold_enumTitleElement() {
	var rv = [], n = document.getElementsByTagName("*");
	var rx = new RegExp("(?:^|\\s)plugin_fold_title_(?:plus|minus)(?:\\s|$)"), i;
	for (i in n) {
		if (n[i].className && rx.test(n[i].className)) {
			rv.push(n[i]);
		}
	}
	return rv;
}
function plugin_fold_searchBodyElement(titleElement) {
	var rv = titleElement;
	while (rv) {
		rv = rv.nextSibling;
		if (rv.nodeType == 3) { continue; } // skip text node
		if (rv.className != "plugin_fold_body") { continue; }
		break;
	}
	return rv;
}
</script>
EOS;
}
?>