33namespace Torchlight \Commonmark ;
44
55use Illuminate \Support \Str ;
6- use League \CommonMark \Environment \EnvironmentBuilderInterface ;
6+ use League \CommonMark \Block \Element \AbstractBlock ;
7+ use League \CommonMark \Block \Element \FencedCode ;
8+ use League \CommonMark \Block \Element \IndentedCode ;
9+ use League \CommonMark \Block \Renderer \BlockRendererInterface ;
10+ use League \CommonMark \ConfigurableEnvironmentInterface ;
11+ use League \CommonMark \ElementRendererInterface ;
712use League \CommonMark \Event \DocumentParsedEvent ;
8- use League \CommonMark \Extension \CommonMark \Node \Block \FencedCode ;
9- use League \CommonMark \Extension \CommonMark \Node \Block \IndentedCode ;
10- use League \CommonMark \Extension \ExtensionInterface ;
11- use League \CommonMark \Node \Node ;
12- use League \CommonMark \Renderer \ChildNodeRendererInterface ;
13- use League \CommonMark \Renderer \NodeRendererInterface ;
1413use League \CommonMark \Util \Xml ;
1514use Torchlight \Block ;
1615use Torchlight \Torchlight ;
1716
18- class TorchlightExtensionV2 implements ExtensionInterface, NodeRendererInterface
17+ abstract class BaseExtension
1918{
19+ /**
20+ * @var array
21+ */
2022 public static $ torchlightBlocks = [];
2123
22- public function register (EnvironmentBuilderInterface $ environment ): void
23- {
24- // We start by walking the document immediately after it's parsed
25- // to gather up all the code blocks and send off our requests.
26- $ environment ->addEventListener (DocumentParsedEvent::class, [$ this , 'onDocumentParsed ' ]);
27-
28- // After the document is parsed, it's rendered. We register our
29- // renderers with a higher priority than the default ones,
30- // and we'll fetch the blocks straight from the cache.
31- $ environment ->addRenderer (FencedCode::class, $ this , 10 );
32- $ environment ->addRenderer (IndentedCode::class, $ this , 10 );
33- }
24+ /**
25+ * @var callable
26+ */
27+ protected $ customBlockRenderer ;
3428
29+ /**
30+ * @param DocumentParsedEvent $event
31+ */
3532 public function onDocumentParsed (DocumentParsedEvent $ event )
3633 {
3734 $ walker = $ event ->getDocument ()->walker ();
3835
3936 while ($ event = $ walker ->next ()) {
40- /** @var FencedCode|IndentedCode $node */
4137 $ node = $ event ->getNode ();
4238
4339 // Only look for code nodes, and only process them upon entering.
@@ -59,31 +55,71 @@ public function onDocumentParsed(DocumentParsedEvent $event)
5955 Torchlight::highlight (static ::$ torchlightBlocks );
6056 }
6157
62- public function render (Node $ node , ChildNodeRendererInterface $ childRenderer )
63- {
64- $ hash = $ this ->makeTorchlightBlock ($ node )->hash ();
65-
66- if (array_key_exists ($ hash , static ::$ torchlightBlocks )) {
67- $ renderer = $ this ->customBlockRenderer ?? $ this ->defaultBlockRenderer ();
68-
69- return call_user_func ($ renderer , static ::$ torchlightBlocks [$ hash ]);
70- }
71- }
72-
58+ /**
59+ * @param callable $callback
60+ * @return $this
61+ */
7362 public function useCustomBlockRenderer ($ callback )
7463 {
7564 $ this ->customBlockRenderer = $ callback ;
7665
7766 return $ this ;
7867 }
7968
69+ /**
70+ * @return \Closure
71+ */
8072 public function defaultBlockRenderer ()
8173 {
8274 return function (Block $ block ) {
8375 return "<pre><code class=' {$ block ->classes }' style=' {$ block ->styles }'> {$ block ->highlighted }</code></pre> " ;
8476 };
8577 }
8678
79+ /**
80+ * @return array
81+ */
82+ abstract protected function codeNodes ();
83+
84+ /**
85+ * @param $node
86+ * @return string
87+ */
88+ abstract protected function getLiteralContent ($ node );
89+
90+ /**
91+ * Bind into a Commonmark V1 or V2 environment.
92+ *
93+ * @param $environment
94+ * @param string $renderMethod
95+ */
96+ protected function bind ($ environment , $ renderMethod )
97+ {
98+ // We start by walking the document immediately after it's parsed
99+ // to gather up all the code blocks and send off our requests.
100+ $ environment ->addEventListener (DocumentParsedEvent::class, [$ this , 'onDocumentParsed ' ]);
101+
102+ foreach ($ this ->codeNodes () as $ blockType ) {
103+ // After the document is parsed, it's rendered. We register our
104+ // renderers with a higher priority than the default ones,
105+ // and we'll fetch the blocks straight from the cache.
106+ $ environment ->{$ renderMethod }($ blockType , $ this , 10 );
107+ }
108+ }
109+
110+ /**
111+ * @param $node
112+ * @return bool
113+ */
114+ protected function isCodeNode ($ node )
115+ {
116+ return in_array (get_class ($ node ), $ this ->codeNodes ());
117+ }
118+
119+ /**
120+ * @param $node
121+ * @return Block
122+ */
87123 protected function makeTorchlightBlock ($ node )
88124 {
89125 return Block::make ()
@@ -92,15 +128,30 @@ protected function makeTorchlightBlock($node)
92128 ->code ($ this ->getContent ($ node ));
93129 }
94130
95- protected function isCodeNode ($ node )
131+ /**
132+ * @param $node
133+ * @return string
134+ */
135+ protected function renderNode ($ node )
96136 {
97- return $ node instanceof FencedCode || $ node instanceof IndentedCode;
137+ $ hash = $ this ->makeTorchlightBlock ($ node )->hash ();
138+
139+ if (array_key_exists ($ hash , static ::$ torchlightBlocks )) {
140+ $ renderer = $ this ->customBlockRenderer ?? $ this ->defaultBlockRenderer ();
141+
142+ return call_user_func ($ renderer , static ::$ torchlightBlocks [$ hash ]);
143+ }
98144 }
99145
146+ /**
147+ * @param $node
148+ * @return string
149+ */
100150 protected function getContent ($ node )
101151 {
102- $ content = $ node -> getLiteral ( );
152+ $ content = $ this -> getLiteralContent ( $ node );
103153
154+ // Check for our file loading convention.
104155 if (!Str::startsWith ($ content , '<<< ' )) {
105156 return $ content ;
106157 }
@@ -115,6 +166,10 @@ protected function getContent($node)
115166 return Torchlight::processFileContents ($ file ) ?: $ content ;
116167 }
117168
169+ /**
170+ * @param $node
171+ * @return array|mixed|null
172+ */
118173 protected function getInfo ($ node )
119174 {
120175 if (!$ this ->isCodeNode ($ node ) || $ node instanceof IndentedCode) {
@@ -126,13 +181,21 @@ protected function getInfo($node)
126181 return empty ($ infoWords ) ? [] : $ infoWords ;
127182 }
128183
184+ /**
185+ * @param $node
186+ * @return string|null
187+ */
129188 protected function getLanguage ($ node )
130189 {
131190 $ language = $ this ->getInfo ($ node )[0 ];
132191
133192 return $ language ? Xml::escape ($ language , true ) : null ;
134193 }
135194
195+ /**
196+ * @param $node
197+ * @return string
198+ */
136199 protected function getTheme ($ node )
137200 {
138201 foreach ($ this ->getInfo ($ node ) as $ item ) {
0 commit comments