Merge pull request '[MTM] Replace abandoned spatie/commonmark-highlighter with tempest/highlight' (#103) from develop into main

Reviewed-on: #103
This commit is contained in:
Jonny Barnes 2026-07-14 19:39:25 +02:00
commit a9263cffc4
19 changed files with 167 additions and 233 deletions

View file

@ -14,11 +14,8 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
use League\CommonMark\Extension\CommonMark\Node\Block\IndentedCode;
use League\CommonMark\MarkdownConverter;
use Spatie\CommonMarkHighlighter\FencedCodeRenderer;
use Spatie\CommonMarkHighlighter\IndentedCodeRenderer;
use Tempest\Highlight\CommonMark\HighlightExtension;
#[Table('articles')]
#[Fillable(['url', 'title', 'main', 'published'])]
@ -53,8 +50,7 @@ class Article extends Model
get: function () {
$environment = new Environment;
$environment->addExtension(new CommonMarkCoreExtension);
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer);
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer);
$environment->addExtension(new HighlightExtension);
$markdownConverter = new MarkdownConverter($environment);
return $markdownConverter->convert($this->main)->getContent();

View file

@ -25,14 +25,11 @@ use Laravel\Scout\Searchable;
use League\CommonMark\Environment\Environment;
use League\CommonMark\Extension\Autolink\AutolinkExtension;
use League\CommonMark\Extension\CommonMark\CommonMarkCoreExtension;
use League\CommonMark\Extension\CommonMark\Node\Block\FencedCode;
use League\CommonMark\Extension\CommonMark\Node\Block\IndentedCode;
use League\CommonMark\Extension\Mention\Mention;
use League\CommonMark\Extension\Mention\MentionExtension;
use League\CommonMark\MarkdownConverter;
use Normalizer;
use Spatie\CommonMarkHighlighter\FencedCodeRenderer;
use Spatie\CommonMarkHighlighter\IndentedCodeRenderer;
use Tempest\Highlight\CommonMark\HighlightExtension;
#[Table('notes')]
#[Fillable(['note', 'in_reply_to', 'client_id'])]
@ -354,9 +351,8 @@ class Note extends Model
$environment->addExtension(new CommonMarkCoreExtension);
$environment->addExtension(new AutolinkExtension);
$environment->addExtension(new MentionExtension);
$environment->addExtension(new HighlightExtension);
$environment->addRenderer(Mention::class, new MentionRenderer);
$environment->addRenderer(FencedCode::class, new FencedCodeRenderer);
$environment->addRenderer(IndentedCode::class, new IndentedCodeRenderer);
$markdownConverter = new MarkdownConverter($environment);
return $markdownConverter->convert($note)->getContent();

View file

@ -10,8 +10,8 @@
"ext-dom": "*",
"ext-intl": "*",
"ext-json": "*",
"ext-pgsql": "*",
"ext-pdo": "*",
"ext-pgsql": "*",
"ext-sodium": "*",
"cviebrock/eloquent-sluggable": "^13.0",
"guzzlehttp/guzzle": "^7.2",
@ -27,9 +27,9 @@
"league/commonmark": "^2.0",
"league/flysystem-aws-s3-v3": "^3.0",
"mf2/mf2": "~0.3",
"spatie/commonmark-highlighter": "^3.0",
"spatie/laravel-flare": "^2.2",
"symfony/html-sanitizer": "^8.0",
"tempest/highlight": "^2.27",
"web-auth/webauthn-lib": "^5.0"
},
"require-dev": {

196
composer.lock generated
View file

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "dfc80df4e7e3401d01e7b0f8d6fa3aa9",
"content-hash": "30db4db4dcfdc487f28e738f0d22d68c",
"packages": [
{
"name": "aws/aws-crt-php",
@ -4852,84 +4852,6 @@
},
"time": "2026-06-18T03:57:49+00:00"
},
{
"name": "scrivo/highlight.php",
"version": "v9.18.1.10",
"source": {
"type": "git",
"url": "https://github.com/scrivo/highlight.php.git",
"reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/scrivo/highlight.php/zipball/850f4b44697a2552e892ffe71490ba2733c2fc6e",
"reference": "850f4b44697a2552e892ffe71490ba2733c2fc6e",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": ">=5.4"
},
"require-dev": {
"phpunit/phpunit": "^4.8|^5.7",
"sabberworm/php-css-parser": "^8.3",
"symfony/finder": "^2.8|^3.4|^5.4",
"symfony/var-dumper": "^2.8|^3.4|^5.4"
},
"suggest": {
"ext-mbstring": "Allows highlighting code with unicode characters and supports language with unicode keywords"
},
"type": "library",
"autoload": {
"files": [
"HighlightUtilities/functions.php"
],
"psr-0": {
"Highlight\\": "",
"HighlightUtilities\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Geert Bergman",
"homepage": "http://www.scrivo.org/",
"role": "Project Author"
},
{
"name": "Vladimir Jimenez",
"homepage": "https://allejo.io",
"role": "Maintainer"
},
{
"name": "Martin Folkers",
"homepage": "https://twobrain.io",
"role": "Contributor"
}
],
"description": "Server side syntax highlighter that supports 185 languages. It's a PHP port of highlight.js",
"keywords": [
"code",
"highlight",
"highlight.js",
"highlight.php",
"syntax"
],
"support": {
"issues": "https://github.com/scrivo/highlight.php/issues",
"source": "https://github.com/scrivo/highlight.php"
},
"funding": [
{
"url": "https://github.com/allejo",
"type": "github"
}
],
"time": "2022-12-17T21:53:22+00:00"
},
{
"name": "spatie/backtrace",
"version": "1.8.2",
@ -4994,61 +4916,6 @@
],
"time": "2026-03-11T13:48:28+00:00"
},
{
"name": "spatie/commonmark-highlighter",
"version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/spatie/commonmark-highlighter.git",
"reference": "d707943b3ce47fcd01240bb85b218e280856d017"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/spatie/commonmark-highlighter/zipball/d707943b3ce47fcd01240bb85b218e280856d017",
"reference": "d707943b3ce47fcd01240bb85b218e280856d017",
"shasum": ""
},
"require": {
"league/commonmark": "^2.0",
"php": "^7.4|^8.0",
"scrivo/highlight.php": "^9.18.1.7"
},
"require-dev": {
"larapack/dd": "^1.0",
"phpunit/phpunit": "^8.5|^9.4",
"spatie/phpunit-snapshot-assertions": "^2.0|^4.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Spatie\\CommonMarkHighlighter\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Sebastian De Deyne",
"email": "sebastian@spatie.be",
"homepage": "https://spatie.be",
"role": "Developer"
}
],
"description": "Highlight your markdown code blocks with league/commonmark",
"homepage": "https://github.com/spatie/commonmark-highlighter",
"keywords": [
"commonmark-highlighter",
"spatie"
],
"support": {
"issues": "https://github.com/spatie/commonmark-highlighter/issues",
"source": "https://github.com/spatie/commonmark-highlighter/tree/3.0.0"
},
"abandoned": "tempest/highlight",
"time": "2021-08-04T18:03:57+00:00"
},
{
"name": "spatie/error-solutions",
"version": "2.0.5",
@ -8655,6 +8522,65 @@
],
"time": "2026-06-09T10:54:51+00:00"
},
{
"name": "tempest/highlight",
"version": "2.27.0",
"source": {
"type": "git",
"url": "https://github.com/tempestphp/highlight.git",
"reference": "7eaf2f4030cc218320672902608b6226bb13a39a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tempestphp/highlight/zipball/7eaf2f4030cc218320672902608b6226bb13a39a",
"reference": "7eaf2f4030cc218320672902608b6226bb13a39a",
"shasum": ""
},
"require": {
"php": "^8.4"
},
"require-dev": {
"assertchris/ellison": "^1.0.2",
"friendsofphp/php-cs-fixer": "^3.84",
"league/commonmark": "^2.4",
"phpbench/phpbench": "^1.4",
"phpstan/phpstan": "^2.1",
"phpunit/phpunit": "^12.0",
"symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"suggest": {
"assertchris/ellison": "Allows you to analyse sentence complexity",
"league/commonmark": "Adds markdown support"
},
"type": "library",
"autoload": {
"psr-4": {
"Tempest\\Highlight\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Brent Roose",
"email": "brendt@stitcher.io"
}
],
"description": "Fast, extensible, server-side code highlighting",
"support": {
"issues": "https://github.com/tempestphp/highlight/issues",
"source": "https://github.com/tempestphp/highlight/tree/2.27.0"
},
"funding": [
{
"url": "https://github.com/brendt",
"type": "github"
}
],
"time": "2026-06-29T09:11:42+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
"version": "v2.4.0",
@ -12988,8 +12914,8 @@
"ext-dom": "*",
"ext-intl": "*",
"ext-json": "*",
"ext-pgsql": "*",
"ext-pdo": "*",
"ext-pgsql": "*",
"ext-sodium": "*"
},
"platform-dev": {},

View file

@ -1,2 +1,2 @@
@layer reset{*,:before,:after{box-sizing:border-box}html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none}body,h1,h2,h3,h4,p,figure,blockquote,dl,dd{margin-block-end:0}ul[role=list],ol[role=list]{list-style:none}body{line-height:1.5}h1,h2,h3,h4,button,input,label{line-height:1.1}h1,h2,h3,h4{text-wrap:balance}a:not([class]){text-decoration-skip-ink:auto;color:currentColor}img,picture{max-width:100%;height:auto;display:block}input,button,textarea,select{font-family:inherit;font-size:inherit}textarea:not([rows]){min-height:10em}:target{scroll-margin-block:5ex}@media (prefers-reduced-motion){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}}}@layer base{:root{color-scheme:light dark;--primary-hue:307;--clr-text:light-dark(oklch(5% .1 var(--primary-hue)),oklch(100% .1 var(--primary-hue)));--clr-background:light-dark(oklch(100% .1 var(--primary-hue)),oklch(15% .15 var(--primary-hue)));--clr-border:light-dark(oklch(90% .2 var(--primary-hue)),oklch(25% .1 var(--primary-hue)));--clr-snow-fall:light-dark(oklch(25% .15 var(--primary-hue)),oklch(85% .2 var(--primary-hue)))}body{background-color:var(--clr-background);color:var(--clr-text)}:root{--border-radius:8px}html{font-size:125%}body{grid-template-rows:min-content 1fr min-content;grid-template-columns:1fr min(80ch,80vw) 1fr;padding-inline:4vw;display:grid;&>header{grid-column:1/-1}&>main{grid-column:2/3}&>footer{grid-column:1/-1;margin-block-start:2ex;& search form{flex-direction:row;align-items:center;gap:1ex;display:flex;& input{min-width:0}}}}.h-feed{flex-direction:column;gap:2ex;display:flex}}@layer components{body>header{grid-template-rows:auto auto;grid-template-columns:auto 1fr auto;align-items:baseline;gap:1rem;display:grid;& a{text-decoration:none}& h1{text-wrap:nowrap;margin:0}& nav{flex-direction:row;gap:.5rem;display:flex;@media screen and (width<=1100px){flex-wrap:wrap;grid-area:2/1/auto/span 3}}}.note{border:1px solid var(--clr-border);border-radius:var(--border-radius);flex-direction:column;padding:1ex 2ex;display:flex;& .e-content{&>p:first-child{margin-block-start:0}& .u-photo{width:100%;height:auto}}& .syndication-links{flex-direction:row;gap:1ex;display:flex;& svg{border-radius:4px;width:auto;height:1lh}}}.reply-to{border:1px solid var(--clr-border);border-top-left-radius:var(--border-radius);border-top-right-radius:var(--border-radius);border-bottom:none;margin-inline:2ex;padding-inline:1ex;font-size:85%}.pagination{flex-direction:row;justify-content:center;align-items:center;display:flex;& div{flex-direction:row;gap:1ex;display:flex}}#theme-selector{& button{appearance:none;background:0 0;border:none;&:hover{cursor:pointer}}& #theme-selector-dropdown{position-area:block-end span-inline-start;border:2px solid var(--clr-border);background-color:var(--clr-background);color:var(--clr-text);margin:0;position:absolute;& fieldset{border:0;flex-direction:row;gap:1ch;display:flex;& input{display:none}}}@media (prefers-reduced-motion:no-preference){& #theme-selector-dropdown{&:popover-open{opacity:1;transform:translateY(0)scale(1);@starting-style{opacity:0;transform:translateY(30px)scale(0)}}opacity:0;transition:transform, opacity, display allow-discrete, overlay allow-discrete;transform-origin:100% 0;transition-duration:.5s;transform:translateY(0)scale(0)}}}::view-transition-group(changing-theme){animation-duration:1.25s}::view-transition-new(changing-theme),::view-transition-old(changing-theme){mix-blend-mode:normal}::view-transition-new(changing-theme){animation-name:reveal}::view-transition-old(changing-theme){animation:none}@keyframes reveal{0%{clip-path:polygon(-30% 0,-30% 0,-15% 100%,-10% 115%)}to{clip-path:polygon(-30% 0,130% 0,115% 100%,-10% 115%)}}}
@layer reset{*,:before,:after{box-sizing:border-box}html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none}body,h1,h2,h3,h4,p,figure,blockquote,dl,dd{margin-block-end:0}ul[role=list],ol[role=list]{list-style:none}body{line-height:1.5}h1,h2,h3,h4,button,input,label{line-height:1.1}h1,h2,h3,h4{text-wrap:balance}a:not([class]){text-decoration-skip-ink:auto;color:currentColor}img,picture{max-width:100%;height:auto;display:block}input,button,textarea,select{font-family:inherit;font-size:inherit}textarea:not([rows]){min-height:10em}:target{scroll-margin-block:5ex}@media (prefers-reduced-motion){::view-transition-group(*),::view-transition-old(*),::view-transition-new(*){animation:none!important}}}@layer base{:root{color-scheme:light dark;--primary-hue:307;--clr-text:light-dark(oklch(5% .1 var(--primary-hue)),oklch(100% .1 var(--primary-hue)));--clr-background:light-dark(oklch(100% .1 var(--primary-hue)),oklch(15% .15 var(--primary-hue)));--clr-border:light-dark(oklch(90% .2 var(--primary-hue)),oklch(25% .1 var(--primary-hue)));--clr-snow-fall:light-dark(oklch(25% .15 var(--primary-hue)),oklch(85% .2 var(--primary-hue)))}body{background-color:var(--clr-background);color:var(--clr-text)}:root{--border-radius:8px}html{font-size:125%}body{grid-template-rows:min-content 1fr min-content;grid-template-columns:1fr min(80ch,80vw) 1fr;padding-inline:4vw;display:grid;&>header{grid-column:1/-1}&>main{grid-column:2/3}&>footer{grid-column:1/-1;margin-block-start:2ex;& search form{flex-direction:row;align-items:center;gap:1ex;display:flex;& input{min-width:0}}}}.h-feed{flex-direction:column;gap:2ex;display:flex}}@layer components{.h-entry{& pre{padding:1rem}}body>header{grid-template-rows:auto auto;grid-template-columns:auto 1fr auto;align-items:baseline;gap:1rem;display:grid;& a{text-decoration:none}& h1{text-wrap:nowrap;margin:0}& nav{flex-direction:row;gap:.5rem;display:flex;@media screen and (width<=1100px){flex-wrap:wrap;grid-area:2/1/auto/span 3}}}.note{border:1px solid var(--clr-border);border-radius:var(--border-radius);flex-direction:column;padding:1ex 2ex;display:flex;& .e-content{&>p:first-child{margin-block-start:0}& .u-photo{width:100%;height:auto}}& .syndication-links{flex-direction:row;gap:1ex;display:flex;& svg{border-radius:4px;width:auto;height:1lh}}}.reply-to{border:1px solid var(--clr-border);border-top-left-radius:var(--border-radius);border-top-right-radius:var(--border-radius);border-bottom:none;margin-inline:2ex;padding-inline:1ex;font-size:85%}.pagination{flex-direction:row;justify-content:center;align-items:center;display:flex;& div{flex-direction:row;gap:1ex;display:flex}}#theme-selector{& button{appearance:none;background:0 0;border:none;&:hover{cursor:pointer}}& #theme-selector-dropdown{position-area:block-end span-inline-start;border:2px solid var(--clr-border);background-color:var(--clr-background);color:var(--clr-text);margin:0;position:absolute;& fieldset{border:0;flex-direction:row;gap:1ch;display:flex;& input{display:none}}}@media (prefers-reduced-motion:no-preference){& #theme-selector-dropdown{&:popover-open{opacity:1;transform:translateY(0)scale(1);@starting-style{opacity:0;transform:translateY(30px)scale(0)}}opacity:0;transition:transform, opacity, display allow-discrete, overlay allow-discrete;transform-origin:100% 0;transition-duration:.5s;transform:translateY(0)scale(0)}}}::view-transition-group(changing-theme){animation-duration:1.25s}::view-transition-new(changing-theme),::view-transition-old(changing-theme){mix-blend-mode:normal}::view-transition-new(changing-theme){animation-name:reveal}::view-transition-old(changing-theme){animation:none}@keyframes reveal{0%{clip-path:polygon(-30% 0,-30% 0,-15% 100%,-10% 115%)}to{clip-path:polygon(-30% 0,130% 0,115% 100%,-10% 115%)}}}
/*# sourceMappingURL=/assets/css/app.css.map */

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -0,0 +1,87 @@
pre, code {
color: #d8dee9;
background-color: #2e3440;
}
.hl-keyword {
color: #81A1C1;
}
.hl-property {
color: #88C0D0;
}
.hl-attribute {
font-style: italic;
}
.hl-type {
color: #8FBCBB;
}
.hl-generic {
color: #81A1C1;
}
.hl-value {
color: #A3BE8C;
}
.hl-literal {
color: #A3BE8C;
}
.hl-number {
color: #B48EAD;
}
.hl-variable {
color: #D8DEE9;
}
.hl-comment {
color: #616E88;
}
.hl-blur {
filter: blur(2px);
}
.hl-strong {
font-weight: bold;
}
.hl-em {
font-style: italic;
}
.hl-addition {
display: inline-block;
min-width: 100%;
background-color: #00FF0022;
}
.hl-deletion {
display: inline-block;
min-width: 100%;
background-color: #FF000011;
}
.hl-gutter {
display: inline-block;
font-size: 0.9em;
color: #555;
padding: 0 1ch;
margin-right: 1ch;
user-select: none;
}
.hl-gutter-addition {
background-color: #34A853;
color: #fff;
}
.hl-gutter-deletion {
background-color: #EA4334;
color: #fff;
}

Binary file not shown.

Binary file not shown.

View file

@ -1,80 +0,0 @@
/*
Zenburn style from voldmar.ru (c) Vladimir Epifanov <voldmar@voldmar.ru>
based on dark.css by Ivan Sagalaev
*/
.hljs {
display: block;
overflow-x: auto;
padding: 0.5em;
background: #3f3f3f;
color: #dcdcdc;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-tag {
color: #e3ceab;
}
.hljs-template-tag {
color: #dcdcdc;
}
.hljs-number {
color: #8cd0d3;
}
.hljs-variable,
.hljs-template-variable,
.hljs-attribute {
color: #efdcbc;
}
.hljs-literal {
color: #efefaf;
}
.hljs-subst {
color: #8f8f8f;
}
.hljs-title,
.hljs-name,
.hljs-selector-id,
.hljs-selector-class,
.hljs-section,
.hljs-type {
color: #efef8f;
}
.hljs-symbol,
.hljs-bullet,
.hljs-link {
color: #dca3a3;
}
.hljs-deletion,
.hljs-string,
.hljs-built_in,
.hljs-builtin-name {
color: #cc9393;
}
.hljs-addition,
.hljs-comment,
.hljs-quote,
.hljs-meta {
color: #7f9f7f;
}
.hljs-emphasis {
font-style: italic;
}
.hljs-strong {
font-weight: bold;
}

Binary file not shown.

Binary file not shown.

View file

@ -44,3 +44,12 @@
gap: 2ex;
}
}
@layer components {
.h-entry {
pre {
padding: 1rem;
}
}
}

View file

@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>@yield('title'){{ config('app.name') }}</title>
<link rel="stylesheet" href="/assets/highlight/zenburn.css">
<link rel="stylesheet" href="/assets/highlight/nord.css">
<link rel="stylesheet" href="/assets/css/app.css">
<link rel="alternate" type="application/rss+xml" title="Blog RSS Feed" href="{{ route('feed.blog.rss') }}">
<link rel="alternate" type="application/atom+xml" title="Blog Atom Feed" href="{{ route('feed.blog.atom') }}">

View file

@ -56,5 +56,5 @@
@section('scripts')
@parent
<link rel="stylesheet" href="/assets/highlight/zenburn.css">
<link rel="stylesheet" href="/assets/highlight/nord.css">
@stop