CC BY-SA, Martin Helmich
Hallo! Dieser Artikel steht auch auf Deutsch zur Verfügung!

Source code content elements for TYPO3 Neos

Of all the features of TYPO3 Neos, one that astonishes me most is the system’s extensibility. For this site, I needed the possibility to present source code examples with syntax highlighting. Luckily, that isn’t any problem at all in Neos. In this article, I describe how you can extend TYPO3 Neos with a custom NodeType that renders a content element with source code and syntax highlighting into your Neos site.

At this point I’m assuming that you know about the TYPO3 Neos basics, and especially know

  • how the Neos package structures looks like and which files are stored where
  • how content is structured in Neos and that there’s something like a Content Repository
  • how to create your own Node Types

Define Node Types

Start by defining the corresponding node type. This is done in the configuration file Configuration/NodeTypes.yaml in your own site package. For my example, I’m using the package key Helmich.Homepage. When taking over code examples, remember to adjust the package key according to your own needs:

 1 'Helmich.Homepage:SourceCode':
 2   superTypes:
 3     - 'TYPO3.Neos:Content'
 4   ui:
 5     group: general
 6     label: Source code
 7     icon: icon-code
 8     inspector:
 9       groups:
10         code:
11           label: Code
12   properties:
13     content:
14       type: string
15       ui:
16         label: Code
17         reloadIfChanged: true
18         inspector:
19           group: code
20           position: 80
21           editor: 'TYPO3.Neos/Inspector/Editors/CodeEditor'
22           editorOptions:
23             buttonLabel: 'Edit source code'

Unfortunately, we cannot use the inline editing that we already know from Neos. This is because the Aloha editor does not get along with the <pre> tags that the content will be rendered into later. That’s not a big thing, though, because Neos offers a special code editor just for this case. This editor is activated in the snippet above in line 21. Using this editor, Neos will offer you a fully functional source code editor with syntax highlighting in the backend for editing the source code content.

The Fluid Template

Next, define the Fluid template for the Node Type. This isn’t overly complex, because after all, we simply want to output the source code exactly the same way that it was entered. By default, Neos will look for the template in Resources/Private/Templates/NodeTypes/SourceCode.html. You could override this convention using TypoScript, but why should you?

{namespace neos=TYPO3\Neos\ViewHelpers}
{namespace media=TYPO3\Media\ViewHelpers}

<pre class="prettyprint"><code>{node.properties.content}</code></pre>

That’s not too hard, is it? At this point, you can already create source code content elements in the Neos backend. You don’t have syntax highlighting or any other fancy stuff yet, though. That’s what’s next.

Configure syntax highlighting

For syntax highlighting, I’m using Google’s Prettify library. It’s working entirely in JavaScript, which saves you the trouble of processing the source code in your PHP backend. The library consists of some JavaScript and CSS files, which you best put into the Resources/Public directory of your package (I’m using Resources/Public/Libraries/Prettify for that).

Now all that’s left is to include the library. The easiest way to do that is using the page template:

 1 <!DOCTYPE html>
 2 {namespace neos=TYPO3\Neos\ViewHelpers}
 3 {namespace ts=TYPO3\TypoScript\ViewHelpers}
 4 {namespace tbs=TYPO3\Twitter\Bootstrap\ViewHelpers}
 5 <html>
 6 <head>
 7     <f:section name="stylesheets">
 8         <!-- Put your stylesheet inclusions here, they will be included in your website by TypoScript -->
 9     </f:section>
10     <f:section name="headScripts">
11         <script type="text/javascript"
12                 src="{f:uri.resource(path:'Libraries/Prettify/run_prettify.js', package: 'Helmich.Homepage')}?skin=desert">
13         </script>
14     </f:section>
15 </head>
16 <body>
17     <!-- ... -->

More configuration!

In the last step I’d like to make the content element a bit more configurable. For example, Prettify’s automatical language recognition does not work that well at times, and it would be nice to specify the used programming language in the Neos backend. Another nice feature would be to enable or disable the line numbering in the source code examples.

For both configuration options, you can extend the original node type definition:

 1 'Helmich.Homepage:SourceCode':
 2   superTypes:
 3     - 'TYPO3.Neos:Content'
 4   ui:
 5     group: general
 6     label: Source code
 7     icon: icon-code
 8     inspector:
 9       groups:
10         code:
11           label: Code
12   properties:
13     content:
14       type: string
15       ui:
16         label: Code
17         reloadIfChanged: true
18         inspector:
19           group: code
20           position: 80
21           editor: 'TYPO3.Neos/Inspector/Editors/CodeEditor'
22           editorOptions:
23             buttonLabel: 'Edit source code'
24     lineNumbers:
25       type: boolean
26       defaultValue: false
27       ui:
28         label: 'Enable line numbering'
29         reloadIfChanged: TRUE
30         inspector:
31           group: 'code'
32           position: 60
33     language:
34       type: string
35       defaultValue: 'auto'
36       ui:
37         reloadIfChanged: TRUE
38         inspector:
39           group: code
40           position: 50
41           editor: 'TYPO3.Neos/Inspector/Editors/SelectBoxEditor'
42           editorOptions:
43             values:
44               'auto':
45                 label: 'Determine automatically'
46               'html':
47                 label: 'HTML'
48               'php':
49                 label: 'PHP'
50               'xml':
51                 label: 'XML'
52               'yaml':
53                 label: 'YAML'

Evaluating these options is best done in TypoScript. The standard point of entry is the file Root.ts2, which Neos will look for in Resources/Private/TypoScript:

 1 prototype(Helmich.Homepage:SourceCode) {
 2   attributes.class = 'prettyprint'
 3   [email protected] {
 4     language {
 5       expression = ${value + (q(node).property('language') != 'auto' ? ' lang-' + q(node).property('language') : '')}
 6     }
 7 
 8     lineNumbering {
 9       expression = ${value + (q(node).property('lineNumbers') ? ' linenums' : '')}
10     }
11   }
12 }

In order to use the attributes configured in TypoScript in your template, you’ll need to adjust the Fluid template:

1 {namespace neos=TYPO3\Neos\ViewHelpers}
2 {namespace media=TYPO3\Media\ViewHelpers}
3 
4 <pre {attributes -> f:format.raw()}><code>{node.properties.content}</code></pre>

Comments