underlined. * @param $instruction the characters to replace, ex. _ * @param $markup the markup to replace to, ex. "u" to get … * @param &$text where to replace. */ function markupPreg($instruction, $markup, &$text) { $output = $text; # Replaces couples "__word__" into "word". $output = mb_ereg_replace("${instruction}(.+?)${instruction}", "<{$markup}>\\1{$markup}>", $output); # Replaces a remaining __ into "…" to the end of the line. $output = mb_ereg_replace("${instruction}(.+)?", "<{$markup}>\\1{$markup}>", $output); $text = $output; } /** * Adds text attributes sucj as underline, bold, … to $line * @param $line the line to process */ function addTextAttributes(&$line) { markupPreg("__", "u", $line); markupPreg("\*\*", "strong", $line); markupPreg("//", "em", $line); markupPreg("~~", "del", $line); } define("NARROW_NO_BREAK_SPACE", " "); define("DASHES" ,"‒" # U+2012 Figure Dash ."–" # U+2013 En Dash ."—" # U+2014 Em Dash ."⸺" # U+2E3A Two-Em Dash ."⸻" # U+2E3B Three-Em Dash (Three times larger than a single char) ); /** * Prepares the raw text to be displayed in HTML environment: * * Escapes the HTML entities yet contained in the Gemtext. * * Puts thin unbrakable spaces before some characters. * @param $text1, $text2 texts to process */ function htmlPrepare(&$text) { $text = htmlspecialchars($text, ENT_HTML5|ENT_NOQUOTES, "UTF-8", false); $text = mb_ereg_replace("\ ([?!:;»€$])", NARROW_NO_BREAK_SPACE."\\1", $text); $text = mb_ereg_replace("([«])\ ", "\\1".NARROW_NO_BREAK_SPACE, $text); # Espace fine insécable # Warning: using a monospace font editor may not display dashes as they should be! # Adds no-break spaces to stick the (EM/EN dashes) to words : aaaaaa – bb – ccccc ==> aaaaaa –$bb$– ccccc $text = mb_ereg_replace("([".DASHES."]) ([^".DASHES.".]+) ([".DASHES."])", "\\1".NARROW_NO_BREAK_SPACE."\\2".NARROW_NO_BREAK_SPACE."\\3", $text); # Adds no-break space to stick the (EM/EN dashes) to words : aaaaaa – bb. ==> aaaaaa –$bb. $text = mb_ereg_replace("([—–]) ([^.]+).", "\\1".NARROW_NO_BREAK_SPACE."\\2.", $text); } ob_start(); $mode = null; $mode_textAttributes = true; foreach ($fileLines as $line) { $reDoCount = 0; $mode_textAttributes_temp = false; while (true) { if ($reDoCount>2) { error_log("Too many loops, mode == '$mode'"); $mode = null; $reDoCount = 0; break; } $reDoCount += 1; $line1 = substr($line, 0, 1); // $line can be modified $line2 = substr($line, 0, 2); // in the meantime. $line3 = substr($line, 0, 3); if (is_null($mode)) { if (empty($line)) { echo "
\n"; } elseif ('^^^' == $line3) { $mode_textAttributes = !$mode_textAttributes; } elseif ('^' == $line1) { if (preg_match("/^\^\s*(.*)$/", $line, $parts)) { $line = $parts[1]; $mode_textAttributes_temp = true; } else { $mode = "raw"; } continue; } elseif ("#" == $line1) { preg_match("/^(#{1,3})\s*(.*)/", $line, $sharps); $h_level = strlen($sharps[1]); $text = $sharps[2]; htmlPrepare($text); switch ($h_level) { case 1: echo "
\n"; } elseif (">" == $line1) { $mode = "quote"; preg_match("/^>\s*(.*)$/", $line, $quoteParts); $quote = $quoteParts[1]; echo "\n"; $mode = null; } else { htmlPrepare($line); echo $line."\n"; } } elseif ("quote"==$mode) { if (">" == $line1) { preg_match("/^>\s*(.*)$/", $line, $quoteParts); $quote = $quoteParts[1]; if (empty($quote)) echo "\n"; if (empty($quote)) echo "\n"; else htmlPrepare($quote); if ($mode_textAttributes xor $mode_textAttributes_temp) addTextAttributes($line); echo "
".$quote."
\n"; } elseif ("* " == $line2) { echo "\n"; $mode = "ul"; continue; } else { $mode = "raw"; continue; } } else { if ("raw"==$mode) { htmlPrepare($line); if ($mode_textAttributes xor $mode_textAttributes_temp) addTextAttributes($line); if (empty($line)) $line = " "; echo "
$line
\n"; $mode = null; } elseif ("pre"==$mode) { if ("```" == $line3) { echo "
\n"; else htmlPrepare($quote); echo "
".$quote."
\n"; } else { echo "\n"; $mode = null; continue; } } elseif ("ul"==$mode) { if ("* " == $line2) { preg_match("/^\*\s*(.*)$/", $line, $ulParts); $li = $ulParts[1]; if (empty($li)) { echo "