8 use League\CommonMark\GithubFlavoredMarkdownConverter
;
9 use League\CommonMark\MarkdownConverter
;
10 use League\CommonMark\Normalizer
;
11 use League\CommonMark\Extension
;
12 use mdref\Formatter\Wrapper
;
15 public function __construct(
16 protected ?MarkdownConverter
$md = null,
17 protected ?Wrapper
$wrapper = null,
20 $this->md
= new GithubFlavoredMarkdownConverter([
21 "slug_normalizer" => [
22 "instance" => new class($this) implements Normalizer\TextNormalizerInterface
{
24 function __construct(Formatter
$fmt) {
25 $this->formatter
= $fmt;
27 function normalize(string $text, $context = null) : string {
28 return $this->formatter
->formatSlug($text);
33 $this->md
->getEnvironment()->addExtension(
34 new Extension\DescriptionList\DescriptionListExtension
36 $this->md
->getEnvironment()->addExtension(
37 new Extension\Attributes\AttributesExtension
40 if (!$this->wrapper
) {
41 $this->wrapper
= new Wrapper($this);
45 public function formatString(string $string) : string {
46 return $this->md
->convertToHtml($string);
49 public function formatFile(string $file) : string {
50 $string = file_get_contents($file);
51 if ($string === false) {
52 throw Exception
::fromLastError();
54 return $this->md
->convertToHtml($string);
58 * Format a simplified url slug
59 * @param string $string input text, like a heading
60 * @return string the simplified slug
62 public function formatSlug(string $string) : string {
63 return preg_replace("/[^\$[:alnum:]:._-]+/", ".", trim($string, "/ \r\n\t"));
67 * @param string $page HTML content
68 * @param object $pld Action payload
69 * @return string marked up HTML content
71 public function markup(string $page, $pld) : string {
72 $dom = new DOMDocument("1.0", "utf-8");
73 $dom->formatOutput
= true;
74 $dom->loadHTML("<!doctype html>\n <meta charset=utf-8>\n" . $page, LIBXML_HTML_NOIMPLIED
);
75 foreach ($dom->childNodes
as $node) {
76 $this->walk($node, $pld);
79 foreach ($dom->childNodes
as $child) {
80 $html .= $dom->saveHTML($child);
85 public function createPermaLink(DOMElement
$node, string $slug, $pld) {
87 $node->setAttribute("id", $slug);
89 $perm = $node->ownerDocument
->createElement("a");
90 $perm->setAttribute("class", "permalink");
91 $perm->setAttribute("href", "$pld->ref#$slug");
92 $perm->textContent
= "#";
96 protected function walk(DOMNode
$node, $pld) {
97 switch ($node->nodeType
) {
98 case XML_ELEMENT_NODE
:
99 $this->walkElement($node, $pld);
102 $this->wrapper
->wrap($node, $pld);
109 protected function highlightCode(DOMElement
$node) {
110 foreach (["default", "comment", "html", "keyword", "string"] as $type) {
111 ini_set("highlight.$type", "inherit\" class=\"$type");
113 $code = highlight_string($node->textContent
, true);
114 $temp = new DOMDocument("1.0", "utf-8");
115 $temp->loadHTML($code, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD
);
116 return $node->ownerDocument
->importNode($temp->firstChild
, true);
119 protected function walkElement(DOMElement
$node, $pld) {
120 switch ($node->tagName
) {
122 $perm = $this->createPermaLink($node, "", $pld);
123 $node->insertBefore($perm, $node->firstChild
);
124 $pld->currentSection
= null;
127 $pld->currentSection
= $this->formatSlug($node->textContent
);
132 $slug = $this->formatSlug($node->textContent
);
133 $perm = $this->createPermaLink($node, $slug, $pld);
134 $node->appendChild($perm);
137 if (!empty($pld->currentSection
) && $node->hasAttribute("class")) {
138 switch ($pld->currentSection
) {
141 switch ($node->getAttribute("class")) {
144 $slug = $this->formatSlug($node->textContent
);
145 $perm = $this->createPermaLink($node, $slug, $pld);
146 $node->insertBefore($perm);
158 if ($node->parentNode
&& $node->parentNode
->nodeName
=== "pre") {
159 $code = $this->highlightCode($node);
160 $this->walk($code, $pld);
161 $node->parentNode
->replaceChild($code, $node);
166 // suck it out, because we're modifying the DOM
167 foreach (iterator_to_array($node->childNodes
) as $child) {
168 $this->walk($child, $pld);