<?php if (!defined('PmWiki')) exit();
/** footnote2.php
 *	Handle footnotes in a page.
 *
 *  Various modifications by Said Achmiz (2017–2025).
 *
 *	AWColley 2007-08-05 -- created footnote.php
 *	Extracted from extendmarkup.php Version 2.0.59
 *	(see http://www.pmwiki.org/wiki/Cookbook/MarkupExtensions)
 *
 *	Copyright 2007 A. W. Colley
 *	You may use this file however you see fit. I don't care.
 *
 *	Modified by Randy Brown to work with PHP 5.5 and to omit the blue line if no 
 *	footnote is on the page. This allows a group footer to include [^#^] to show 
 *	any footnotes present, without showing a blue line if there are none.
 *
 *	ExtendedMarkup.php Copyright 2004-2006 John Rankin (john.rankin@affinity.co.nz)
 *	This program is free software; you can redistribute it and/or modify
 *	it under the terms of the GNU General Public License as published
 *	by the Free Software Foundation; either version 2 of the License, or
 *	(at your option) any later version.
 *
 *	THIS SOFTWARE IS PROVIDED AS IS WITHOUT ANY GUARANTEES FOR SUITABLILITY FOR
 *	ANY PURPOSE. THE COPYRIGHT HOLDERS ARE NOT RESPONSIBLE FOR ANY DAMAGES, WHETHER
 *	DIRECT, INDIRECT, OR TOTALLY UNRELATED THAT MAY ACCOMPANY, RESULT FROM, OR FOR
 *	ANY REASON OCCUR AFTER THE USE OF, PERUSAL OF, OR THINKING ABOUT THIS SOFTWARE.
 *
 *	If you don’t like the thin blue line, change it in the 
 *  `div.footnotes-with-start-line` style below; or, to disable it entirely,
 *  set $FootnoteBlockStartLine to false; or use the [^@^] alternate markup.
 *
 *  See https://www.pmwiki.org/wiki/Cookbook/Footnotes for more information.
 */
$RecipeInfo['Footnotes']['Version'] = '2025-02-16';

$HTMLStylesFmt['Footnotes'] = "
div.footnotes-with-start-line::before {
	content: '';
	display: block;
	width: 12em; 
	border-bottom: 1px solid blue;
	margin-bottom: 0.75em;
}
div.footnote {
	margin: 0;
	padding-left: 2.5em;
	font-size: 0.9em;
	position: relative;
}
div.footnote .footnote-number {
	position: absolute;
	left: 0;
	width: 2em;
	text-align: right;
}
div.footnote .footnote-number::after {
	content: '.';
}
";

SDV($FootnoteBacklinkCharacter, '&uArr;');
SDV($FootnoteRegExp, '/\[\^(.*?)\^\]/s');
SDV($FootnoteBlockStartLine, true);

## [^footnote text^] or [^#1 footnote text^] or [^#1^] / [^#1 footnote text^]
## [^#^] to list footnotes with blue line, or [^@^] to list them without
Markup('[^', '<split', $FootnoteRegExp, 'Footnote');

function Footnote($m) {
	global $FootnoteBacklinkCharacter, $FootnoteBlockStartLine;

	static $fngroup = 1, $fncount = 0, $fntext = [ ];

	$fn_str = $m[1];
	if ($fn_str == "#" || $fn_str == "@") {
		/*	Print all defined footnotes.
		 */
		if ($fncount > 0) {
			$fntext = array_filter($fntext, function ($fn) { return ($fn != '#'); });
			ksort($fntext);

			/*	Blue line if ‘#’; no line if ‘@’.
				(Setting $FootnoteBlockStartLine to false disables blue line 
				 even for ‘#’.)
			 */
			$footnotes_class = 'footnotes' 
							 . ($FootnoteBlockStartLine && $fn_str == "#"
							 	? ' footnotes-with-start-line'
							 	: '');
			$out = "<div class='{$footnotes_class}'>\n" 
				 . implode('', $fntext) 
				 . "</div>\n";
		} else {
			/*	If we’re here, then a [^#^] or [^@^] has been encountered before
				any footnotes have been defined. We ignore it.
			 */
			$out = '';
		}

		/*	Clear all defined footnotes, reset footnote numbering, and increment
			footnote group number.
		 */
		$fntext = [ ];
		$fncount = 0;
		$fngroup++;
	} else {
		/*	This branch of the conditional means that we’re processing a 
			footnote reference and/or definition. (Note that no footnotes will
			ever be printed unless we take the other branch at some point.)
		 */
		$fncount++;

		/*	If there’s a footnote number specified explicitly, then set the 
			number of the current footnote to that number.

			If there is, additionally, footnote text provided with the number, 
			then set the footnote text to that (i.e., chop off the number
			prefix). (If there’s only a number and no text, then this is either
			a reference to a numbered footnote previously defined inline, OR a 
			reference to a numbered footnote that will later be defined 
			non-inline).
		 */
		if (preg_match('/^#([0-9]+)(\s+(.+))?$/s', $fn_str, $fn_str_parts)) {
			$fncount = $fn_str_parts[1];
			$fn_str = (isset($fn_str_parts[2]) ? $fn_str_parts[2] : '');
		}

		/*	The CSS ‘id’ attributes of both the in-text footnote link and the
			footnote block itself include the footnote group and number.
		 */
		$fnid = $fngroup . '_' . $fncount;

		/*	If there’s footnote text provided, AND a footnote number is given,
			AND the footnote of that number has been previously referenced, then 
			output nothing (as this must therefore be a non-inline footnote
			definition). Otherwise, output the footnote link (as this must be
			a numbered footnote use without an inline definition; or the first
			use of a numbered footnote with an an inline definition; or a 
			non-numbered, inline-defined footnote).
		 */
		$out = (   isset($fn_str_parts[2])
				&& isset($fntext[$fncount])
				&& $fntext[$fncount] == '#') 
			   ? '' 
			   : (  "<a class='footnote' id='fnr{$fnid}' href='#fn{$fnid}'><sup>"
			      . $fncount
			      . "</sup></a>");

		if ($fn_str != '') {
			/*	If there’s footnote text provided, then store the text as the 
				definition of the footnote of the current number (which might be 
				either specified explicitly, or computed by incrementing), for 
				later output. (This could be an inline definition, with or 
				without an explicit number, or else a non-inline definition.)
			 */
			$fntext[$fncount] = "<div class='footnote' id='fn$fnid'>\n" 
							  . "<span class='footnote-number'>$fncount</span> "
							  . $fn_str
							  . " <a href='#fnr$fnid'>$FootnoteBacklinkCharacter</a>" 
							  . "\n</div>";
		} else if (!isset($fntext[$fncount])) {
			/*	If there’s no footnote text provided, then record that this 
				footnote number has been referenced. This may be checked later,
				to identify non-inline numbered footnote definitions (see the
				definition of $out, above).
			 */
			$fntext[$fncount] = '#';
		}
	}

	return $out;
}