diff --git a/htmgem.php b/htmgem.php
deleted file mode 100644
index d547081..0000000
--- a/htmgem.php
+++ /dev/null
@@ -1,254 +0,0 @@
-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("HtmGem: 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) {
- if (preg_match("/^\^\^\^\s+(.*)$/", $line)) {
- $mode_textAttributes = !$mode_textAttributes;
- } else {
- $mode = "raw";
- continue;
- }
- } elseif ('^' == $line1 and !$mode_textAttributes_temp) {
- preg_match("/^\^\s*(.*)$/", $line, $parts);
- $line = $parts[1];
- $mode_textAttributes_temp = true;
- 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 "".$text."
\n"; break;
- case 2: echo "".$text."
\n"; break;
- case 3: echo "".$text."
\n"; break;
- }
- } elseif ("=>" == $line2) {
- if (preg_match("/^=>\s*([^\s]+)(?:\s+(.*))?$/", $line, $linkParts)) {
- $url_link = $linkParts[1];
- $url_label = @$linkParts[2];
- preg_match("/^([^:]+):/", $url_link, $matches);
- $url_protocol = @$matches[1];
- if (empty($url_protocol)) $url_protocol = "local";
- if (empty(trim($url_label))) {
- $url_label = $url_link;
- } else {
- // the label is humain-made, apply formatting
- htmlPrepare($url_label);
- }
- echo "$url_label
\n";
- } else {
- $mode = "raw";
- continue;
- }
- } elseif ("```" == $line3) {
- if (preg_match("/^```\s*(.*)$/", $line, $matches)) {
- $alt_text = trim(@$matches[1]);
- if (!(empty($alt_text))) {
- echo "\n";
- } else {
- echo "\n";
- }
- }
- $mode="pre";
- } elseif (">" == $line1) {
- $mode = "quote";
- preg_match("/^>\s*(.*)$/", $line, $quoteParts);
- $quote = $quoteParts[1];
- 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";
- $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";
- 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 "
\n";
- } else {
- htmlPrepare($li);
- if ($mode_textAttributes xor $mode_textAttributes_temp) addTextAttributes($li);
- echo "".$li."\n";
- }
- } else {
- echo "\n";
- $mode = null;
- continue;
- }
- } else {
- die("Unexpected mode: $mode!");
- }
- }
- break; // exits the while(true) as no continue occured
- }
-}
-$body = ob_get_contents();
-ob_clean();
-
-# Gets the page title: the first occurrence with # at the line start
-mb_ereg("#\s*([^\n]+)\n", $fileContents, $matches);
-$page_title = @$matches[1];
-
-#
-echo <<
-
-
-$page_title
-
-
-
-
-EOL;
-
-echo "\n".$body;
-echo "\n\n";
-ob_end_flush();
-
-?>
diff --git a/index.gmi b/index.gmi
new file mode 100644
index 0000000..2f0304d
--- /dev/null
+++ b/index.gmi
@@ -0,0 +1,34 @@
+# HtmGem, voir Gemini à travers HTTP
+Une fois les fichiers copiés dans votre hébergement, par exemple ///htmgem//, il ne reste qu’à ajouter une règle de ré-écriture d’URL (//URL Rewriting//). Si vous pouvez lire ce texte en ayant demandé //htmgem.php// avec le navigateur, il ne reste que cette dernière étape à franchir 😄
+
+### Nginx
+```
+# Ce texte doit être placé dans la configuration du serveur.
+DirectoryIndex index.php index.gmi index.html
+rewrite ^(.+\.gmi)$ htmgem/?url=$1;
+```
+
+### Apache
+```
+# Ce texte peut se placer à la racine du site dans un fichier ".htaccess".
+Index index.php index.gmi index.html
+RewriteEngine on
+RewriteRule ^(.+\.gmi)$ htmgem/?url=$1
+```
+
+Par la suite,
+* Quand un fichier se terminant par //.gmi// sera demandé, HtmGem le traduira à la volée en HTML.
+* Quand seul le répertoire sera demandé (http://site.tld/path) le fichier //index.gmi// sera automatiquement choisi.
+
+## Tester HtmGem
+Il est supposé que HtmGem est installé à la racine du site dans un répertoire //HtmGem//. Sinon, il faudra simplement adapter les liens.
+
+🢂 Appeler cette présente page directement, en cliquant ci-après :
+=> index.gmi
+
+🢂 Enfin, pour vérifier que le fichier //index.gmi// est automatiquement appelé quand le fichier //**.gmi**// n’est pas indiqué :
+=> / Lien vers la racine du site
+
+# Quand tout marche…
+Parmi les fichiers distribués, seuls sont requis :
+* htmgem/index.php
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..778d98f
--- /dev/null
+++ b/index.php
@@ -0,0 +1,272 @@
+
+
+
+
+
+Installation de HtmGem
+
+
+
+
+\n\n";
+ die();
+}
+
+
+$GMI_DIR = $_SERVER['DOCUMENT_ROOT'];
+
+
+$filePath = $GMI_DIR.$url;
+$fileContents = @file_get_contents($filePath);
+if (!$fileContents) {
+ http_response_code(404);
+ die("404: $url");
+}
+
+# Removes the Byte Order Mark
+$fileContents = preg_replace("/\xEF\xBB\xBF/", "", $fileContents);
+
+
+/**
+ * Replaces markups things like __underlined__ to 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);
+}
+
+/**
+ * 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);
+}
+
+function translateGemToHtml($fileContents) {
+ $fileLines = preg_split("/\n/", $fileContents);
+ ob_start();
+ $mode = null;
+ $mode_textAttributes = true;
+ foreach ($fileLines as $line) {
+ $reDoCount = 0;
+ $mode_textAttributes_temp = false;
+ while (true) {
+ if ($reDoCount>2) {
+ error_log("HtmGem: 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) {
+ if (preg_match("/^\^\^\^\s+(.*)$/", $line)) {
+ $mode_textAttributes = !$mode_textAttributes;
+ } else {
+ $mode = "raw";
+ continue;
+ }
+ } elseif ('^' == $line1 and !$mode_textAttributes_temp) {
+ preg_match("/^\^\s*(.*)$/", $line, $parts);
+ $line = $parts[1];
+ $mode_textAttributes_temp = true;
+ 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 "".$text."
\n"; break;
+ case 2: echo "".$text."
\n"; break;
+ case 3: echo "".$text."
\n"; break;
+ }
+ } elseif ("=>" == $line2) {
+ if (preg_match("/^=>\s*([^\s]+)(?:\s+(.*))?$/", $line, $linkParts)) {
+ $url_link = $linkParts[1];
+ $url_label = @$linkParts[2];
+ preg_match("/^([^:]+):/", $url_link, $matches);
+ $url_protocol = @$matches[1];
+ if (empty($url_protocol)) $url_protocol = "local";
+ if (empty(trim($url_label))) {
+ $url_label = $url_link;
+ } else {
+ // the label is humain-made, apply formatting
+ htmlPrepare($url_label);
+ }
+ echo "$url_label
\n";
+ } else {
+ $mode = "raw";
+ continue;
+ }
+ } elseif ("```" == $line3) {
+ if (preg_match("/^```\s*(.*)$/", $line, $matches)) {
+ $alt_text = trim(@$matches[1]);
+ if (!(empty($alt_text))) {
+ echo "\n";
+ } else {
+ echo "\n";
+ }
+ }
+ $mode="pre";
+ } elseif (">" == $line1) {
+ $mode = "quote";
+ preg_match("/^>\s*(.*)$/", $line, $quoteParts);
+ $quote = $quoteParts[1];
+ 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";
+ $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";
+ 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 "
\n";
+ } else {
+ htmlPrepare($li);
+ if ($mode_textAttributes xor $mode_textAttributes_temp) addTextAttributes($li);
+ echo "".$li."\n";
+ }
+ } else {
+ echo "\n";
+ $mode = null;
+ continue;
+ }
+ } else {
+ die("Unexpected mode: $mode!");
+ }
+ }
+ break; // exits the while(true) as no continue occured
+ }
+ }
+ $html = ob_get_contents();
+ ob_clean();
+ return $html;
+}
+
+# Gets the page title: the first occurrence with # at the line start
+mb_ereg("#\s*([^\n]+)\n", $fileContents, $matches);
+$page_title = @$matches[1];
+
+#
+echo <<
+
+
+$page_title
+
+
+
+
+EOL;
+
+echo "\n".translateGemToHtml($fileContents);
+echo "\n\n";
+ob_end_flush();
+
+?>