]*)(\\s)class=(['\"])([^>]*?)\\4)?/",
"
[=',
'/\\$\\[(?>([^\\]]+))\\]/', "cb_expandxlang");
# {$var} substitutions
Markup('{$var}', '>$[phrase]',
'/\\{(\\*|!?[-\\w.\\/\\x80-\\xff]*)(\\$:?\\w[-\\w]*)\\}/',
"MarkupPageVar");
function MarkupPageVar($m){
global $IncludedPages, $Cursor;
extract($GLOBALS["MarkupToHTML"]);
if($m[1] && strpos($m[2], '$:')===0) {
$pn = isset($Cursor[$m[1]]) ? $Cursor[$m[1]] : MakePageName($pagename, $m[1]);
@$IncludedPages[$pn]++;
}
return PRR(PVSE(PageVar($pagename, $m[2], $m[1])));
}
# invisible (:textvar:...:) definition
Markup('textvar:', '([A-Za-z0-9]+|#\\d+|#[xX][A-Fa-f0-9]+));/',
'&$1;');
Markup('&', '<&', '/&/', Keep('&'));
## (:if:)/(:elseif:)/(:else:)
SDV($CondTextPattern,
"/ \\(:if (\d*) (?:end)? \\b[^\n]*?:\\)
.*?
(?: \\(: (?:if\\1|if\\1end) \\s* :\\)
| (?=\\(:(?:if\\1|if\\1end)\\b[^\n]*?:\\) | $)
)
/six");
SDV($CondTextReplacement, "MarkupCondText2");
Markup('if', 'fulltext', $CondTextPattern, $CondTextReplacement);
function MarkupCondText2($m) {
extract($GLOBALS["MarkupToHTML"]);
return CondText2($pagename, $m[0], $m[1]);
}
function CondText2($pagename, $text, $code = '') {
global $Conditions, $CondTextPattern, $CondTextReplacement;
$if = "if$code";
$repl = str_replace('$pagename', "'$pagename'", $CondTextReplacement);
$parts = preg_split("/\\(:(?:{$if}end|$if|else *$if|else$code)\\b\\s*(.*?)\\s*:\\)/",
$text, -1, PREG_SPLIT_DELIM_CAPTURE);
$x = array_shift($parts);
while ($parts) {
list($condspec, $condtext) = array_splice($parts, 0, 2);
if (!preg_match("/^\\s*(!?)\\s*(\\S*)\\s*(.*?)\\s*$/", $condspec, $match)) continue;
list($x, $not, $condname, $condparm) = $match;
if (!isset($Conditions[$condname]))
return preg_replace_callback($CondTextPattern, $repl, $condtext);
$tf = @eval("return ({$Conditions[$condname]});");
if ($tf xor $not)
return preg_replace_callback($CondTextPattern, $repl, $condtext);
}
return '';
}
## (:include:)
Markup('include', '>if',
'/\\(:(include)\\s+(\\S.*?):\\)/i',
"MarkupRedirectInclude");
## (:redirect:)
Markup('redirect', 'include',
'/\\(:(nogroupheader):\\)/i',
"MarkupGroupHeaderFooter");
Markup('nogroupfooter', '>include',
'/\\(:(nogroupfooter):\\)/i',
"MarkupGroupHeaderFooter");
Markup('groupheader', '>nogroupheader',
'/\\(:(groupheader):\\)/i',
"MarkupGroupHeaderFooter");
Markup('groupfooter','>nogroupfooter',
'/\\(:(groupfooter):\\)/i',
"MarkupGroupHeaderFooter");
function MarkupGroupHeaderFooter($m) {
extract($GLOBALS["MarkupToHTML"]);
global $GroupHeaderFmt, $GroupFooterFmt;
switch ($m[1]) {
case 'nogroupheader': return PZZ($GroupHeaderFmt='');
case 'nogroupfooter': return PZZ($GroupFooterFmt='');
case 'groupheader': return PRR(FmtPageName($GroupHeaderFmt,$pagename));
case 'groupfooter': return PRR(FmtPageName($GroupFooterFmt,$pagename));
}
}
## (:nl:)
Markup('nl0','(?:\\(:nl:\\))+)([^\n])/i","$1\n$2");
Markup('nl1','>nl0',"/\\(:nl:\\)/i",'');
## \\$ (end of line joins)
Markup('\\$','>nl1',"/\\\\(?>(\\\\*))\n/", "MarkupEndLineJoin");
function MarkupEndLineJoin($m) { return str_repeat(' ',strlen($m[1])); }
## Remove one <:vspace> after !headings
Markup('!vspace', '>\\$', "/^(!(?>[^\n]+)\n)<:vspace>/m", '$1');
## (:noheader:),(:nofooter:),(:notitle:)...
Markup('noheader', 'directives', '/\\(:noheader:\\)/i', "MarkupTmplDisplay");
Markup('nofooter', 'directives', '/\\(:nofooter:\\)/i', "MarkupTmplDisplay");
Markup('notitle', 'directives', '/\\(:notitle:\\)/i', "MarkupTmplDisplay");
Markup('noleft', 'directives', '/\\(:noleft:\\)/i', "MarkupTmplDisplay");
Markup('noright', 'directives', '/\\(:noright:\\)/i', "MarkupTmplDisplay");
Markup('noaction', 'directives', '/\\(:noaction:\\)/i', "MarkupTmplDisplay");
function MarkupTmplDisplay($m) {
extract($GLOBALS["MarkupToHTML"]);
switch ($markupid) {
case 'noheader': return SetTmplDisplay('PageHeaderFmt',0);
case 'nofooter': return SetTmplDisplay('PageFooterFmt',0);
case 'notitle': return SetTmplDisplay('PageTitleFmt',0);
case 'noleft': return SetTmplDisplay('PageLeftFmt',0);
case 'noright': return SetTmplDisplay('PageRightFmt',0);
case 'noaction': return SetTmplDisplay('PageActionFmt',0);
}
}
## (:spacewikiwords:)
Markup('spacewikiwords', 'directives',
'/\\(:(no)?spacewikiwords:\\)/i',
"MarkupDirectives");
## (:linkwikiwords:)
Markup('linkwikiwords', 'directives',
'/\\(:(no)?linkwikiwords:\\)/i',
"MarkupDirectives");
## (:linebreaks:)
Markup('linebreaks', 'directives',
'/\\(:(no)?linebreaks:\\)/i',
"MarkupDirectives");
## (:messages:)
Markup('messages', 'directives',
'/^\\(:messages( .*)?:\\)/i',
"MarkupDirectives");
function MarkupDirectives($m) {
extract($GLOBALS["MarkupToHTML"]);
switch ($markupid) {
case 'linkwikiwords': return PZZ($GLOBALS['LinkWikiWords']=(@$m[1]!='no'));
case 'spacewikiwords': return PZZ($GLOBALS['SpaceWikiWords']=(@$m[1]!='no'));
case 'linebreaks':
return PZZ($GLOBALS['HTMLPNewline'] = (@$m[1]!='no') ? ' ' : '');
case 'messages':
global $MessagesFmt;
$args = isset($m[1]) ? ParseArgs($m[1]) : array();
if (isset($args['key'])) {
$keys = MatchNames(array_keys($MessagesFmt), $args['key']);
$msg = array();
foreach($keys as $k) $msg[$k] = $MessagesFmt[$k];
if (! $msg) return '';
}
else $msg = $MessagesFmt;
return '<:block>'.Keep(FmtPageName(MergeMessages($msg), $pagename));
}
}
function MergeMessages($msg) {
$out = '';
if (is_array($msg)) foreach($msg as $x) $out .= MergeMessages($x);
else $out .= $msg;
return $out;
}
## (:comment:)
Markup('comment', 'directives', '/\\(:comment .*?:\\)/i', '');
## (:title:) +fix for PITS:00266, 00779
$tmpwhen = IsEnabled($EnablePageTitlePriority, 0) ? ' $title));
return "";
case 'keywords':
return PZZ(SetProperty($pagename, 'keywords', $m[1], ', '));
case 'description':
return PZZ(SetProperty($pagename, 'description', $m[1], '\n'));
}
}
## (:keywords:), (:description:)
Markup('keywords', 'directives', "/\\(:keywords?\\s+(.+?):\\)/i", "MarkupSetProperty");
Markup('description', 'directives', "/\\(:description\\s+(.+?):\\)/i", "MarkupSetProperty");
$HTMLHeaderFmt['meta'] = 'function:PrintMetaTags';
function PrintMetaTags($pagename, $args) {
global $PCache;
foreach(array('keywords', 'description') as $n) {
foreach((array)@$PCache[$pagename]["=p_$n"] as $v) {
$v = str_replace("'", ''', $v);
print " \n";
}
}
}
#### inline markups ####
## ''emphasis''
Markup("''",'inline',"/''(.*?)''/",'$1 ');
## '''strong'''
Markup("'''","<''","/'''(.*?)'''/",'$1 ');
## '''''strong emphasis'''''
Markup("'''''","<'''","/'''''(.*?)'''''/",'$1 ');
## @@code@@
Markup('@@','inline','/@@(.*?)@@/','$1
');
## '+big+', '-small-'
Markup("'+","<'''''","/'\\+(.*?)\\+'/",'$1 ');
Markup("'-","<'''''","/'\\-(.*?)\\-'/",'$1 ');
## '^superscript^', '_subscript_'
Markup("'^","<'''''","/'\\^(.*?)\\^'/",'$1 ');
Markup("'_","<'''''","/'_(.*?)_'/",'$1 ');
## [+big+], [-small-]
Markup('[+','inline','/\\[(([-+])+)(.*?)\\1\\]/',
"MarkupBigSmall");
function MarkupBigSmall($m) {
$size = round(pow(6/5,($m[2]=='-'? -1:1)*strlen($m[1]))*100,0);
return "{$m[3]} ";
}
## {+ins+}, {-del-}
Markup('{+','inline','/\\{\\+(.*?)\\+\\}/','$1 ');
Markup('{-','inline','/\\{-(.*?)-\\}/','$1');
## [[<<]] (break)
Markup('[[<<]]','inline','/\\[\\[<<\\]\\]/'," ");
###### Links ######
function MarkupLinks($m){
extract($GLOBALS["MarkupToHTML"]);
switch ($markupid) {
case '[[':
return Keep(MakeLink($pagename,$m[1],NULL,$m[2]),'L');
case '[[|':
return Keep(MakeLink($pagename,$m[1],$m[2],$m[3]),'L');
case '[[->':
return Keep(MakeLink($pagename,$m[2],$m[1],$m[3]),'L');
case '[[|#':
return Keep(MakeLink($pagename,$m[1],
'['.++$GLOBALS['MarkupFrame'][0]['ref'].']'),'L');
case '[[#':
return Keep(TrackAnchors($m[1]) ? '' : " ", 'L');
case 'urllink':
return Keep(MakeLink($pagename,$m[0],$m[0]),'L');
case 'mailto':
return Keep(MakeLink($pagename,$m[0],$m[1]),'L');
case 'img':
global $LinkFunctions, $ImgTagFmt;
return Keep($LinkFunctions[$m[1]]($pagename,$m[1],$m[2],@$m[4],$m[1].$m[2],
$ImgTagFmt),'L');
}
}
## [[free links]]
Markup('[[','links',"/(?>\\[\\[\\s*(.*?)\\]\\])($SuffixPattern)/", "MarkupLinks");
## [[!Category]]
## Markup '[[!' now processed and indexed in LinkPage()
## with other link formats (PITS:01095, PITS:00447)
SDV($CategoryGroup,'Category');
SDV($LinkCategoryFmt,"\$LinkText ");
# This is a temporary workaround for blank category pages.
# It may be removed in a future release (Pm, 2006-01-24)
if (preg_match("/^$CategoryGroup\\./", $pagename)) {
SDV($DefaultPageTextFmt, '');
SDV($PageNotFoundHeaderFmt, 'HTTP/1.1 200 Ok');
}
## [[target | text]]
Markup('[[|','<[[',
"/(?>\\[\\[([^|\\]]*)\\|\\s*)(.*?)\\s*\\]\\]($SuffixPattern)/",
"MarkupLinks");
## [[text -> target ]]
Markup('[[->','>[[|',
"/(?>\\[\\[([^\\]]+?)\\s*-+>\\s*)(.*?)\\]\\]($SuffixPattern)/",
"MarkupLinks");
## [[#anchor]]
Markup('[[#','<[[','/(?>\\[\\[#([A-Za-z][-.:\\w]*))\\]\\]/', "MarkupLinks");
function TrackAnchors($x) { global $SeenAnchor; return @$SeenAnchor[$x]++; }
## [[target |#]] reference links
Markup('[[|#', '<[[|',
"/(?>\\[\\[([^|\\]]+))\\|\\s*#\\s*\\]\\]/",
"MarkupLinks");
## [[target |+]] title links moved inside LinkPage()
## bare urllinks
Markup('urllink','>[[',
"/\\b(?>(\\L))[^\\s$UrlExcludeChars]*[^\\s.,?!$UrlExcludeChars]/",
"MarkupLinks");
## mailto: links
Markup('mailto','(\\L))([^\\s$UrlExcludeChars]+$ImgExtPattern)(\"([^\"]*)\")?/",
"MarkupLinks");
if (IsEnabled($EnableRelativePageLinks, 1))
SDV($QualifyPatterns['/(\\[\\[(?>[^\\]]+?->)?\\s*)([-\\w\\x80-\\xfe\\s\'()]+([|#?].*?)?\\]\\])/'],
'cb_qualifylinks');
function cb_qualifylinks($m) {
extract($GLOBALS['tmp_qualify']);
return "{$m[1]}$group/{$m[2]}";
}
## bare wikilinks
## v2.2: markup rule moved to scripts/wikiwords.php)
Markup('wikilink', '>urllink');
## escaped `WikiWords
## v2.2: rule kept here for markup compatibility with 2.1 and earlier
Markup('`wikiword', ' markup (after all other block markups)
Markup('^<:','>block','/^(?=\\s*\\S)(<:([^>]+)>)?/',"MarkupBlock");
function MarkupBlock($m) {return Block(@$m[2]);}
## unblocked lines w/block markup become anonymous <:block>
Markup('^!<:', '<^<:',
"/^(?!<:)(?=.*(<\\/?($BlockPattern)\\b)|$KeepToken\\d+B$KeepToken)/",
'<:block>');
## Lines that begin with displayed images receive their own block. A
## pipe following the image indicates a "caption" (generates a linebreak).
Markup('^img', 'block',
"/^((?>(\\s+|%%|%[A-Za-z][-,=:#\\w\\s'\".]*%)*)$KeepToken(\\d+L)$KeepToken)(\\s*\\|\\s?)?(.*)$/",
"ImgCaptionDiv");
function ImgCaptionDiv($m) {
global $KPV;
if (strpos($KPV[$m[3]], '$ret
";
}
## Whitespace at the beginning of lines can be used to maintain the
## indent level of a previous list item, or a preformatted text block.
Markup('^ws', '<^img', '/^\\s+ #1/x', "WSIndent");
function WSIndent($i) {
if(is_array($i)) $i = $i[0];
global $MarkupFrame;
$icol = strlen($i);
for($depth = count(@$MarkupFrame[0]['cs']); $depth > 0; $depth--)
if (@$MarkupFrame[0]['is'][$depth] == $icol) {
$MarkupFrame[0]['idep'] = $depth;
$MarkupFrame[0]['icol'] = $icol;
return '';
}
return $i;
}
## The $EnableWSPre setting uses leading spaces on markup lines to indicate
## blocks of preformatted text.
SDV($EnableWSPre, 1);
Markup('^ ', 'block',
'/^\\s+ #2/x',
"MarkupWSPre");
function MarkupWSPre($m) {
global $EnableWSPre;
return ($EnableWSPre > 0 && strlen($m[0]) >= $EnableWSPre)
? '<:pre,1>'.$m[0] : $m[0];
}
## bullet lists
Markup('^*','block','/^(\\*+)\\s?(\\s*)/','<:ul,$1,$0>$2');
## numbered lists
Markup('^#','block','/^(#+)\\s?(\\s*)/','<:ol,$1,$0>$2');
## indented (->) /hanging indent (-<) text
Markup('^->','block','/^(?>(-+))>\\s?(\\s*)/','<:indent,$1,$1 $2>$2');
Markup('^-<','block','/^(?>(-+))<\\s?(\\s*)/','<:outdent,$1,$1 $2>$2');
## definition lists
Markup('^::','block','/^(:+)(\s*)([^:]+):/','<:dl,$1,$1$2>$2$3 ');
## Q: and A:
Markup('^Q:', 'block', '/^Q:(.*)$/', "<:block,1>$1
");
Markup('^A:', 'block', '/^A:/', Keep(''));
## tables
function MarkupTables($m) {
extract($GLOBALS["MarkupToHTML"]);
switch ($markupid) {
case 'table': return Cells(@$m[1],@$m[2]);
case '^||||': return FormatTableRow($m[0]);
case '^||':
$GLOBALS['BlockMarkups']['table'][0] = '';
return '<:block,1>';
}
}
## ||cell||, ||!header cell||, ||!caption!||
Markup('^||||', 'block',
'/^\\|\\|.*\\|\\|.*$/',
"MarkupTables");
## ||table attributes
Markup('^||','>^||||','/^\\|\\|(.*)$/',
"MarkupTables");
#### (:table:) markup (AdvancedTables)
Markup('table', '>', '><<', '<^>>',
'/^>><</',
'(:divend:)');
Markup('det-summ', '$3$4'); # PITS:01465
function SimpleTableAttr($attr) {
global $SimpleTableDefaultClassName;
$qattr = PQA($attr, true, true);
if(IsEnabled($SimpleTableDefaultClassName) && !preg_match("/(^| )class='.*?' /", $qattr))
$qattr .= "class='$SimpleTableDefaultClassName'";
return $qattr;
}
#### (:table:) markup (AdvancedTables)
function Cells($name,$attr) {
global $MarkupFrame, $EnableTableAutoValignTop;
$attr = PQA($attr, true, true);
$tattr = @$MarkupFrame[0]['tattr'];
$name = strtolower($name);
$key = preg_replace('/end$/', '', $name);
if (preg_match("/^(?:head|cell)(nr)?$/", $name)) $key = 'cell';
$out = '<:block>'.MarkupClose($key);
if (substr($name, -3) == 'end') return $out;
$cf = & $MarkupFrame[0]['closeall'];
if ($name == 'table') $MarkupFrame[0]['tattr'] = $attr;
else if ($key == 'cell') {
if (IsEnabled($EnableTableAutoValignTop, 1) && strpos($attr, "valign=")===false)
$attr .= " valign='top'";
$t = (strpos($name, 'head')===0 ) ? 'th' : 'td';
if (!@$cf['table']) {
$tattr = @$MarkupFrame[0]['tattr'];
$out .= "<$t $attr>";
$cf['table'] = '
';
} else if ( preg_match("/nr$/", $name)) $out .= "<$t $attr>";
else $out .= "<$t $attr>";
$cf['cell'] = "$t>";
} else {
$tag = preg_replace('/\\d+$/', '', $key);
$tmp = "<$tag $attr>";
if ($tag == 'details') {
$tmp = preg_replace("#($2', $tmp);
}
$out .= $tmp;
$cf[$key] = "$tag>";
}
return $out;
}
## headings
Markup('^!', 'block', '/^(!{1,6})\\s?(.*)$/', "MarkupHeadings");
function MarkupHeadings($m) {
$len = strlen($m[1]);
return "<:block,1>$m[2] ";
}
## horiz rule
Markup('^----','>^->','/^----+/','<:block,1> ');
## @2022-01-08T10:07:08Z ->
Markup('', '<@@', '/@\\d{4}-(0[1-9]|1[012])-(0[1-9]|[12]\\d|3[01])'
.'T([01]\\d|2[0-3]):([0-5]\\d)(:([0-5]\\d))?Z?/i', 'FmtDateTimeZ');
#### special stuff ####
## (:markup:) for displaying markup examples
function MarkupMarkup($pagename, $text, $opt = '') {
global $MarkupWordwrapFunction, $MarkupWrapTag;
SDV($MarkupWordwrapFunction, 'IsEnabled');
SDV($MarkupWrapTag, 'pre');
$tag = $MarkupWrapTag;
$MarkupMarkupOpt = array('class' => 'vert');
$opt = array_merge($MarkupMarkupOpt, ParseArgs($opt));
if (@$opt['caption'])
$caption = str_replace("'", ''',
"{$opt['caption']} ");
$class = preg_replace('/[^-\\s\\w]+/', ' ', @$opt['class']);
$sep = '';
if (strpos($class, 'norender') !== false) $markup2 = '';
else {
if (strpos($class, 'horiz') === false) $sep = ' ';
$html = MarkupToHTML($pagename, $text, array('escape' => 0));
$markup2 = "$html ";
}
$pretext = $MarkupWordwrapFunction($text, ($markup2 xor $sep)? 40:75);
$markup1 = @"<$tag>$pretext$tag> ";
return Keep(@"$caption
$markup1$sep$markup2
");
}
Markup('markup', '<[=',
"/\\(:markup(\\s+([^\n]*?))?:\\)[^\\S\n]*\\[([=@])(.*?)\\3\\]/si",
"MarkupMarkupMarkup");
Markup('markupend', '>markup', # $1 only shifts the other matches
"/\\(:(markup)(\\s+([^\n]*?))?:\\)[^\\S\n]*\n(.*?)\\(:markupend:\\)/si",
"MarkupMarkupMarkup");
function MarkupMarkupMarkup($m) { # cannot be joined, $markupid resets
extract($GLOBALS["MarkupToHTML"]); global $MarkupMarkupLevel;
@$MarkupMarkupLevel++;
$x = MarkupMarkup($pagename, $m[4], $m[2]);
$MarkupMarkupLevel--;
return $x;
}
SDV($HTMLStylesFmt['markup'], "
table.markup { border:2px dotted #ccf; width:90%; }
td.markup1, td.markup2 { padding-left:10px; padding-right:10px; }
table.vert td.markup1 { border-bottom:1px solid #ccf; }
table.horiz td.markup1 { width:23em; border-right:1px solid #ccf; }
table.markup caption { text-align:left; }
div.faq p, div.faq pre { margin-left:2em; }
div.faq p.question { margin:1em 0 0.75em 0; font-weight:bold; }
div.faqtoc div.faq * { display:none; }
div.faqtoc div.faq p.question
{ display:block; font-weight:normal; margin:0.5em 0 0.5em 20px; line-height:normal; }
div.faqtoc div.faq p.question * { display:inline; }
td.markup1 pre { white-space: pre-wrap; }
");
#### Special conditions ####
## The code below adds (:if date:) conditions to the markup.
$Conditions['date'] = "CondDate(\$condparm)";
function CondDate($condparm) {
global $Now;
if (!preg_match('/^(\\S*?)(\\.\\.(\\S*))?(\\s+\\S.*)?$/',
trim($condparm), $match))
return false;
if ($match[4] == '') { $x0 = $Now; NoCache(); }
else { list($x0, $x1) = DRange($match[4]); }
if ($match[1] > '') {
list($t0, $t1) = DRange($match[1]);
if ($x0 < $t0) return false;
if ($match[2] == '' && $x0 >= $t1) return false;
}
if ($match[3] > '') {
list($t0, $t1) = DRange($match[3]);
if ($x0 >= $t1) return false;
}
return true;
}
# This pattern enables the (:encrypt :) markup/replace-on-save
# pattern.
SDV($ROSPatterns['/\\(:encrypt\\s+([^\\s:=]+).*?:\\)/'], 'cb_encrypt');
function cb_encrypt($m) { return pmcrypt($m[1]);}
# Table of contents, based on Cookbook:AutoTOC by Petko Yotov
SDVA($PmTOC, array(
'Enable' => 0,
'MaxLevel' => 6,
'MinNumber' => 3,
'ParentElement'=>'',
'NumberedHeadings'=>'',
'EnableBacklinks'=>0,
'EnableQMarkup' => 0,
'contents' => XL('Contents'),
'hide' => XL('hide'),
'show' => XL('show'),
));
if ($action!='browse') $PmTOC['Enable'] = 0;
Markup("PmTOC", 'directives', '/^\\(:[#*]?(?:toc|tdm).*?:\\)\\s*$/im', 'FmtPmTOC');
Markup("noPmTOC", 'directives', '/\\(:(no)(?:toc|tdm).*?:\\)/im', 'FmtPmTOC');
function FmtPmTOC($m) {
if (@$m[1]) return Keep(' ');
return "<:block,1>".Keep("
");
}
SDV($HTMLStylesFmt['PmTOC'], '.noPmTOC, .PmTOCdiv:empty {display:none;}
.PmTOCdiv { display: inline-block; font-size: 13px; overflow: auto; max-height: 500px;}
.PmTOCdiv a { text-decoration: none; display: block; line-height: 1;}
.PmTOCdiv a.pmtoc-indent1 { margin-left: 1em; }
.PmTOCdiv a.pmtoc-indent2 { margin-left: 2em; }
.PmTOCdiv a.pmtoc-indent3 { margin-left: 3em; }
.PmTOCdiv a.pmtoc-indent4 { margin-left: 4em; }
.PmTOCdiv a.pmtoc-indent5 { margin-left: 5em; }
.PmTOCdiv a.pmtoc-indent6 { margin-left: 6em; }
.back-arrow {font-size: .8rem; text-decoration: none; vertical-align: text-top;}
#PmTOCchk + label {cursor: pointer;}
#PmTOCchk {display: none;}
#PmTOCchk:not(:checked) + label > .pmtoc-show {display: none;}
#PmTOCchk:checked + label > .pmtoc-hide {display: none;}
#PmTOCchk:checked + label + div {display: none;}');
SDV($HTMLStylesFmt['PmSortable'], 'table.sortable th { cursor: pointer; }
table.sortable th::after { color: transparent; content: "\00A0\025B8"; }
table.sortable th:hover::after { color: inherit; content: "\00A0\025B8"; }
table.sortable th.dir-u::after { color: inherit; content: "\00A0\025BE"; }
table.sortable th.dir-d::after { color: inherit; content: "\00A0\025B4"; }');
# Helper function for recipes
# Generic Markup directive (:abc params:)...(:abcend:)?
function AutoMarkupDirective($m) { # all, directive, params?, content?
global $MarkupToHTML, $MarkupDirectiveFunctions;
extract($MarkupToHTML); # get $pagename
@list($all, $directive, $params, $content) = $m;
if(!isset($MarkupDirectiveFunctions[$directive])) return Keep($all);
$args = ParseArgs(strval(@$params), '(?>(\\w[-\\w]*)=)');
foreach($args as $k=>&$v) if(is_numeric($v)) $v = floatval($v);
$content = strval(@$content);
return $MarkupDirectiveFunctions[$directive]($pagename, $directive, $args, $content);
}
if(isset($MarkupDirectiveFunctions)) {
$keys = implode('|', array_keys($MarkupDirectiveFunctions));
Markup('anydir2', 'anydir2', "/\\(:($keys)( .*?)?:\\)/", 'AutoMarkupDirective');
}