posts/plugins/markdown-typography/markdown-typography.php

390 lines
15 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace Grav\Plugin;
use Grav\Common\Plugin;
use RocketTheme\Toolbox\Event\Event;
class MarkdownTypographyPlugin extends Plugin
{
private array $thin_arrows;
private array $thick_arrows;
/**
* @return array
*/
public static function getSubscribedEvents()
{
return [
"onMarkdownInitialized" => ["onMarkdownInitialized", 0],
];
}
public function onMarkdownInitialized(Event $event)
{
$markdown = $event["markdown"];
$config = $this->grav["config"]->get("plugins.".$this->name);
// TODO: Once Grav requires Parsedown 1.8:
// - $Element["name"] is no longer required, so remove redundant spans
// - $Element["handler"] changes for extents with Markdown inside
// - Do arrows starting with "<" work in that version?
$arrows = $config["arrows"];
// Enable arrows (before dashes to avoid conflict)
if ($arrows["enabled"]) {
$this->thin_arrows = explode(",", $arrows["thin_arrows"]) ?: ["","","",""];
$this->thick_arrows = explode(",", $arrows["thick_arrows"]) ?: ["","","",""];
// Add inline types
$markdown->addInlineType("-", "TypographyArrowSingleRight");
$markdown->addInlineType("=", "TypographyArrowDoubleRight");
//$markdown->addInlineType(">", "TypographyArrowBothLeft");
// Add function to handle inline type
$markdown->inlineTypographyArrowSingleRight = function($excerpt) {
if (preg_match("/^(--?>)/", $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[1]),
"element" => array(
"name" => "span",
"text" => strlen($matches[1]) == 2 ? $this->thin_arrows[0] : $this->thin_arrows[2 % count($this->thin_arrows)], // single right arrow (long arrow: ⟶)
"attributes" => [
"class" => "typography-arrow"
]
),
);
}
elseif (preg_match("/^(--?<)/", $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[1]),
"element" => array(
"name" => "span",
"text" => strlen($matches[1]) == 2 ? $this->thin_arrows[1] : $this->thin_arrows[3 % count($this->thin_arrows)], // single left arrow (long arrow: ⟵)
"attributes" => [
"class" => "typography-arrow"
]
),
);
}
};
$markdown->inlineTypographyArrowDoubleRight = function($excerpt) {
if (preg_match("/^(==?>)/", $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[1]),
"element" => array(
"name" => "span",
"text" => strlen($matches[1]) == 2 ? $this->thick_arrows[0] : $this->thick_arrows[2 % count($this->thick_arrows)], // fat right arrow
"attributes" => [
"class" => "typography-arrow"
]
),
);
}
elseif (preg_match("/^(==?<)/", $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[1]),
"element" => array(
"name" => "span",
"text" => strlen($matches[1]) == 2 ? $this->thick_arrows[1] : $this->thick_arrows[3 % count($this->thick_arrows)], // fat left arrow
"attributes" => [
"class" => "typography-arrow"
]
),
);
}
};
// TODO: Doesn't seem to work at the moment!?
/*$markdown->inlineTypographyArrowBothLeft = function($excerpt) {
$this->grav["debugger"]->addMessage($excerpt);
if (preg_match("/^(.--?)/", $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[1]),
"element" => array(
"name" => "span",
"text" => "←", // thin left arrow
"attributes" => [
"class" => "typography-arrow"
]
),
);
}
elseif (preg_match("/^(.==?)/", $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[1]),
"element" => array(
"name" => "span",
"text" => "⇦", // fat left arrow
"attributes" => [
"class" => "typography-arrow"
]
),
);
}
};*/
}
// Enable dashes
if ($config["dashes"]) {
// Add inline type
$markdown->addInlineType("-", "TypographyDash");
// Add function to handle inline type
$markdown->inlineTypographyDash = function($excerpt) {
if (preg_match("/-/", $excerpt["text"], $matches) && preg_match("/ (-) /", $excerpt["context"], $matches))
{
return array(
"extent" => 1,
"element" => array(
"name" => "span",
"text" => "", // en dash
),
);
} elseif (preg_match("/^(---)/", $excerpt["text"], $matches))
{
return array(
"extent" => 3,
"element" => array(
"name" => "span",
"text" => "", // em dash
),
);
} elseif (preg_match("/^(--)/", $excerpt["text"], $matches))
{
return array(
"extent" => 2,
"element" => array(
"name" => "span",
"text" => "", // en dash
),
);
}
};
}
// Enable smart-quotes
if ($config["smart_quotes"]) {
// Add inline types
$markdown->addInlineType('"', "TypographyDoubleQuote");
$markdown->addInlineType("'", "TypographySingleQuote");
// Add function to handle double quotes
$markdown->inlineTypographyDoubleQuote = function($excerpt) {
if (preg_match_all('/^"([\s\S]*?)"/', $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[0][0]),
"element" => array(
"name" => "span",
"text" => "".$matches[1][0]."", // double-quotes
"handler" => "line",
),
);
}
elseif (preg_match('/^\s?"/', $excerpt["context"], $matches))
{
return array(
"extent" => strlen($excerpt["text"]),
"element" => array(
"name" => "span",
"text" => "" . substr($excerpt["text"], 1), // Lonely opening double-quotes
"handler" => "line",
),
);
}
};
// Add function to handle single quotes (+ apostrophes)
$markdown->inlineTypographySingleQuote = function($excerpt) {
if (preg_match("/\w".preg_quote($excerpt["text"], "/")."/", $excerpt["context"], $matches))
{
return array(
"extent" => 1,
"element" => array(
"name" => "span",
"text" => "", // apostrophe
),
);
}
elseif (preg_match_all("/^'([\s\S]*?)'(?=\W?)/", $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[0][0]),
"element" => array(
"name" => "span",
"text" => "".$matches[1][0]."", // single-quotes
"handler" => "line",
),
);
}
elseif (preg_match("/^(')|(\s')/", $excerpt["context"], $matches))
{
return array(
"extent" => strlen($excerpt["text"]),
"element" => array(
"name" => "span",
"text" => "" . substr($excerpt["text"], 1), // Lonely opening single-quote
"handler" => "line",
),
);
}
};
// Don't process inside of inline shortcode tags
// This is a fix to stop quoted attributes getting broken when inline
// Temporary tags are stripped by $this->stripTemporaryTags()
// Once Parsedown 1.8 is used in Grav, the temp tags will be unnecessary
$markdown->addInlineType("[", "TypographyShortcode");
$markdown->inlineTypographyShortcode = function($excerpt) {
if (preg_match("/\[[\s\S]+?((\".+?\")|(\'.+?\')|(\[.+?\])|([\s\S]+?))*?\]/", $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[0]),
"element" => array(
"name" => "temporary-tag",
"text" => $matches[0],
),
);
}
};
$this->enable(["onOutputGenerated" => ["stripTemporaryTags", 0]]);
}
// Enable ellipsis
if ($config["ellipsis"]) {
// Add inline type
$markdown->addInlineType(".", "TypographyEllipsis");
// Add function to handle inline type
$markdown->inlineTypographyEllipsis = function($excerpt) {
if (preg_match("/^(\.\.\.)/", $excerpt["text"], $matches))
{
return array(
"extent" => 3,
"element" => array(
"name" => "span",
"text" => "", // ellipsis
),
);
}
};
}
// Enable line breaks
if ($config["line_breaks"]) {
// Add inline type
$markdown->addInlineType("\\", "TypographyLineBreaks");
// Add function to handle inline type
$markdown->inlineTypographyLineBreaks = function($excerpt) {
if (preg_match("/\\\n/", $excerpt["text"], $matches))
{
return array(
"extent" => 1,
"element" => array(
"name" => "br", // line break
),
);
}
};
}
// Enable interrobang
if ($config["interrobang"]) {
// Add inline type
$markdown->addInlineType("!", "TypographyInterrobang");
// Add function to handle inline type
$markdown->inlineTypographyInterrobang = function($excerpt) {
if (preg_match("/^(!\?)/", $excerpt["text"], $matches))
{
return array(
"extent" => 2,
"element" => array(
"name" => "span",
"text" => "", // interrobang
),
);
}
};
}
// Enable plus-minus
if ($config["plus_minus"]) {
// Add inline type
$markdown->addInlineType("+", "TypographyPlusMinus");
// Add function to handle inline type
$markdown->inlineTypographyPlusMinus = function($excerpt) {
if (preg_match("/^(\+\/?-)/", $excerpt["text"], $matches))
{
return array(
"extent" => strlen($matches[1]),
"element" => array(
"name" => "span",
"text" => "±", // plus-minus
),
);
}
};
}
// Enable X Times
if ($config["x_times"]) {
// Add inline type
$markdown->addInlineType("x", "TypographyXTimes");
// Add function to handle inline type
$markdown->inlineTypographyXTimes = function($excerpt) {
if (
(substr($excerpt["text"], 0, 2) == "x ") and
(preg_match("/( ".preg_quote($excerpt["text"], "/").")/", $excerpt["context"], $matches))
)
{
return array(
"extent" => 1,
"element" => array(
"name" => "span",
"text" => "×", // times symbol
),
);
}
};
}
}
public function stripTemporaryTags()
{
// Check that it's an HTML page, abort if not
if ($this->grav["page"]->templateFormat() !== 'html') {
return;
}
// Get the rendered content (HTML)
$content = $this->grav->output;
// Remove the temporary tags
$content = str_replace("<temporary-tag>", "", $content);
$content = str_replace("</temporary-tag>", "", $content);
// Remove encoded temporary tags (eg. those generatred by [safe-email])
$content = str_replace("&#60;&#116;&#101;&#109;&#112;&#111;&#114;&#97;&#114;&#121;&#45;&#116;&#97;&#103;&#62;", "", $content);
$content = str_replace("&#60;&#47;&#116;&#101;&#109;&#112;&#111;&#114;&#97;&#114;&#121;&#45;&#116;&#97;&#103;&#62;", "", $content);
// Rewrite the output
$this->grav->output = $content;
}
}