View the Laravel client on GitHub at github.com/torchlight-api/torchlight-laravel.
To install, require the package from composer:
1composer require torchlight/torchlight-laravel
Include the RenderTorchlight
middleware in your Http/Kernel.php
. You should include this as the very first middleware in your global middleware stack, to ensure that it will be the last middleware to run as the response comes out.
1protected $middleware = [+ \Torchlight\Middleware\RenderTorchlight::class, 3 \App\Http\Middleware\TrustProxies::class,4 \Fruitcake\Cors\HandleCors::class,5 \App\Http\Middleware\PreventRequestsDuringMaintenance::class,6 \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,7 \App\Http\Middleware\TrimStrings::class,8 \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,9];
The Torchlight client is designed in such a way that regardless of how many blocks you have on a page, only one request to the Torchlight API will ever be made. If all the blocks are cached, zero requests are made.
When the middleware runs, it will fire a request to the Torchlight API if there are any blocks that aren't already cached. Once the client has gathered all the blocks from the API or the cache, it will replace the plain code blocks with properly highlighted blocks.
You can run the following command to publish your configuration file:
1php artisan torchlight:install
Once run, you should see a new torchlight.php
file in your config
folder, with contents that look like this:
1<?php 2 3return [ 4 // The Torchlight client caches highlighted code blocks. Here 5 // you can define which cache driver you'd like to use. 6 'cache' => env('TORCHLIGHT_CACHE_DRIVER'), 7 8 // Which theme you want to use. You can find all of the themes at10 'theme' => env('TORCHLIGHT_THEME', 'material-theme-palenight'),11 12 // Your API token from torchlight.dev.13 'token' => env('TORCHLIGHT_TOKEN'),14 15 // If you want to register the blade directives, set this to true.16 'blade_components' => true,17 18 // The Host of the API.19 'host' => env('TORCHLIGHT_HOST', 'https://api.torchlight.dev'),20 21 // Global options to control blocks-level settings.23 'options' => [24 // Turn line numbers on or off globally25 'lineNumbers' => true,26 27 // Control the `style` attribute applied to line numbers.28 // 'lineNumbersStyle' => '',29 30 // Turn on +/- diff indicators.31 'diffIndicators' => true,32 33 // If there are any diff indicators for a line, put them34 // in place of the line number to save horizontal space.35 'diffIndicatorsInPlaceOfLineNumbers' => true,36 37 // When lines are collapsed, this is the text that will38 // be shown to indicate that they can be expanded.39 // 'summaryCollapsedIndicator' => '...',40 ]41];
Torchlight caches code blocks based on their contents and configuration, so that blocks that have already been rendered won't be rendered again. Using the cache
key you can set which driver you would like to use.
If you don't specify a cache, your application's default cache will be used.
You can change the theme of all your code blocks by adjusting the theme
key in your configuration. To view all of the themes provided by Torchlight, head over to torchlight.dev/themes.
This is your API token from torchlight.dev. (Torchlight is completely free for personal and open source projects.)
Torchlight works by using a custom Laravel Blade component. If you'd like to disable the registration of the component for whatever reason, you can set this to false
.
These are options that you can set to control every code block on your site. Read more in the options section.
The Laravel client provides you with a custom custom Laravel Blade component registered as <x-torchlight-code>
. To highlight code, you would use this component in place of the standard HTML <code>
tag.
1<x-torchlight-code language='php'>2 echo "Hello World!";3</x-torchlight-code>
The contents inside of the custom component will be sent to Torchlight, parsed as PHP (based on the language
attribute), and returned as fully rendered HTML:
1<code class="torchlight" style="background-color: #fff;">2 <div class="line">3 <span style="color: #1b1f234d; text-align: right; -webkit-user-select: none; user-select: none;" class="line-number">1</span>4 <span style="color: #005CC5;">echo</span>5 <span style="color: #24292E;"> </span>6 <span style="color: #032F62;">"Hello World!"</span>7 <span style="color: #24292E;">;</span>8 </div>9</code>
Line breaks added for readability. In reality, it's all compressed onto a single.
You will likely want to wrap blocks of code in <pre>
tags just like you would normally do:
1<pre><x-torchlight-code language='php'>2 echo "Hello World!";3</x-torchlight-code></pre>
You must declare a language
attribute, so that Torchlight knows how to parse the contents.
1<x-torchlight-code language='php'>2 echo "Hello World!";3</x-torchlight-code>
To see all of the available languages, check the languages page.
You may also override the theme for a specific block by passing in a theme
attribute
1<x-torchlight-code language='php' theme='github-dark'>2 echo "Hello World!";3</x-torchlight-code>
Regardless of what is specified in your torchlight.php
file, this block will be using the github-dark
theme.
Sometimes it's easier to write your code in a dedicated file instead of inline in your blade view. The code component accepts a contents
attribute for just such use cases.
Using the contents
attribute, you can pass in the path of a file to be rendered:
1<x-torchlight-code language='js' contents="{{ base_path('webpack.mix.js') }}" />2{{-- Or... --}}3<x-torchlight-code language='js' :contents="base_path('webpack.mix.js')" />
Torchlight will read the contents of that file and send it off to be highlighted. This lets you write your docs or examples in your editor with proper indentation and highlighting.
If you use the contents
attribute, Torchlight will first check to see if the attribute you have provided is a file. If you pass in an absolute path, Torchlight will render that file.
If the path is not a valid file, Torchlight will wrap check the resource_path
to see if your file lives there.
If you have a folder of examples
in your resources
folder, then you can pass a string as a shorthand:
1<x-torchlight-code language='php' contents='examples/very-impressive-example.php' />
Since examples/very-impressive-example.php
is not a file, but resource_path('examples/very-impressive-example.php')
is, the component will read the content from that file and send it to Torchlight.
All other attributes will be passed through to the code
tag.
If you add classes to your component, they will be merged with the classes that come back from the Torchlight API.
So if you add e.g. my-6
:
1<x-torchlight-code language='php' class='my-6'>2 echo "Hello World!";3</x-torchlight-code>
It will still be there when the contents are swapped in:
1<code class="torchlight my-6" style="background-color: #fff;">2 <!-- ... -->3</code>
All other attributes will be passed through unmodified:
1<x-torchlight-code id="block-1" language='php'>2 echo "Hello World!";3</x-torchlight-code>
It will still be there when the contents are swapped in:
1<code id="block-1" class="torchlight my-6" style="background-color: #fff;">2 <!-- ... -->3</code>
The Laravel client allows you to register "post processors" that can change the contents of a code block after it comes back from the API and before it's sent to your frontend.
This can be particularly useful if you want to inject some user information (API keys, URL endpoints, etc), or if you want to further mark up a specific string for easier JavaScript access.
Let's take a look at an example that will add a user's authentication token to a block of code.
The first thing you'll need to do is create a post-processor class. It must implement the PostProcessor
interface:
1use Torchlight\Block;2 3class InjectAuthToken implements PostProcessor4{5 public function process(Block $block)6 {7 // @TODO8 }9}
The only required method is process
, which will receive a Torchlight Block. You can modify the contents of the block in this method. For this example, we will look for user_auth_token
and replace it with the user's actual token.
1use Torchlight\Block; 2 3class InjectAuthToken implements PostProcessor 4{ 5 public function process(Block $block) 6 { 7 $token = Auth::check() ? Auth::user()->token : 'token'; 8 9 // Replace the placeholder with the user's token.10 $block->highlighted = str_replace(11 'user_auth_token', $token, $block->highlighted12 );13 } 14}
Every single block will run through this process
method, so make sure the placeholder you choose is pretty unique. You may make it a little bit longer and more random:
1use Torchlight\Block; 2 3class InjectAuthToken implements PostProcessor 4{ 5 public function process(Block $block) 6 { 7 $token = Auth::check() ? Auth::user()->token : 'token'; 8 9 // Replace the placeholder with the user's token.10 $block->highlighted = str_replace(11 'processor_replace_user_token_here', $token, $block->highlighted 12 );13 } 14}
You can also use post-processors to add HTML markup, that will not be escaped. This is helpful if you want to add some sort of JavaScript enhancement and need a way to target a specific element.
1use Torchlight\Block; 2 3class InjectAuthToken implements PostProcessor 4{ 5 public function process(Block $block) 6 { 7 $token = Auth::check() ? Auth::user()->token : 'token'; 8 9 // Wrap the token in a `mark` tag and give it a class10 // so JavaScript can target it and enhance it.11 $token = "<mark class='user-auth-token'>{$token}</mark>";12 13 // Replace the placeholder with the user's token.14 $block->highlighted = str_replace(15 'user_auth_token', $token, $block->highlighted16 );17 } 18}
Once you have your class created, you'll need to register it, typically in a service provider:
1Torchlight::addPostProcessors([2 InjectAuthToken::class3]);
If you are using the Laravel Markdown package by Graham Campbell and you're using post-processors, there is one thing you'll need to look out for.
The Laravel Markdown package allows you to return .md
views from your controller and Laravel Markdown will render them to proper HTML. It also writes the rendered file to the view cache, and pulls it from the cache the next time it's needed.
By default, post-processors are disabled when the views are being compiled by the Laravel Markdown package. The reason we do this is because if you inject a user's auth token into a block, the Markdown package will save it to disk and serve it to every user from there on out, showing the user's auth token to everyone. Obviously this is a huge security issue.
If you understand this risk, you can add a property to your post-processor called $processEvenWhenCompiling
and set it to true
.
1use Torchlight\Block; 2 3class InjectAuthToken implements PostProcessor 4{ 5 public $processEvenWhenCompiling = true; 6 7 public function process(Block $block) 8 { 9 // Do NOT use Auth::user() here!10 }11}
This processor will now run when views are being compiled, so be sure to not inject any user data.
There are a few common things that can go wrong. Read below for solutions.
If your component is not rendering, make sure that you are not using the same kind of quote (single/double) on the outside and inside of the contents
attribute. This is a Laravel limitation, not a Torchlight one.
1{{-- This will work, double quotes on the outside, single on the inside. --}}2<x-torchlight-code contents="{{ base_path('webpack.mix.js') }}" language='js' />3 4{{-- This will NOT work, single quotes for both out and inside. --}}5<x-torchlight-code contents='{{ base_path('webpack.mix.js') }}' language='js' />
If you are changing your code or Torchlight config and not seeing changes reflected in the browser, it is likely because Laravel has cached your views and is serving old versions instead of the most recent versions.
You can clear that by calling php artisan view:clear
. If you are still seeing cached results, you may try clearing your application cache as well:
1php artisan view:clear && php artisan cache:clear
Are you seeing weird stuff like this?
##PRE_TL_COMPONENT##__torchlight-block-[6179eb34-30dd-406d-b870-1b03988fa248]__##POST_TL_COMPONENT##
That means that the blade component has captured your code contents and left its placeholder on the page, but it was never replaced by the rendered code. Typically this means that you haven't registered the middleware (see above).
If you aren't using the middleware at all (e.g. Jigsaw doesn't use the middleware), then you'll need to make sure you are manually calling BladeManager::renderContent($content)
somewhere. This is the function that replaces all the placeholders with fully rendered blocks.
Our first-party clients (e.g. the Jigsaw one) handle this for you, but if you're off the beaten path you'll want to make sure you're completing "Step 2" of the Torchlight process.