Skip to content

Commit 6717cba

Browse files
authored
Merge pull request #6 from demyanovs/release-v3.0.0
### Added - Support for `<pre><code>` pattern (in addition to `<pre>`) for better Markdown compatibility - Support for `class="language-*"` attribute on `<code>` tag for language detection - Fluent interface for `showLineNumbers()` and `showActionPanel()` methods - `HighlighterFactory` class for creating highlighter instances based on language - `CodeBlockWrapper` class for separating presentation logic from highlighting - `LanguageNormalizer` class for normalizing language identifiers with aliases support - Custom exceptions: `InvalidLanguageException`, `InvalidThemeException`, `ThemeNotSetException` - PHP as default language for code blocks without specified language - Comprehensive test suite ### Changed - **BREAKING**: Removed Singleton pattern from all highlighter classes (`HighlighterPHP`, `HighlighterXML`, `HighlighterBash`) - **BREAKING**: Made `HighlighterBase` an abstract class (cannot be instantiated directly) - **BREAKING**: Added `ext-dom` PHP extension requirement (previously optional with regex fallback) - Improved HTML attribute parsing using `DOMDocument` with regex fallback - Enhanced syntax highlighting logic in `HighlighterBase` - Improved XML/HTML highlighting: fixed line-by-line processing, proper attribute highlighting - Updated PHPDoc comments throughout the codebase ### Fixed - Fixed issue with extra empty lines at the beginning and end of code blocks - Fixed line numbering
2 parents 98b5f20 + 769ccf4 commit 6717cba

26 files changed

+1824
-281
lines changed

CHANGELOG.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2828
## [2.1.0] - 2023-06-13
2929
- Set PHP minimum version in composer
3030
- Throws UnknownThemeException
31-
- Added tests
31+
- Added tests
32+
33+
## [3.0.0] - 2025-11-21
34+
35+
### Added
36+
- Support for `<pre><code>` pattern (in addition to `<pre>`) for better Markdown compatibility
37+
- Support for `class="language-*"` attribute on `<code>` tag for language detection
38+
- Fluent interface for `showLineNumbers()` and `showActionPanel()` methods
39+
- `HighlighterFactory` class for creating highlighter instances based on language
40+
- `CodeBlockWrapper` class for separating presentation logic from highlighting
41+
- `LanguageNormalizer` class for normalizing language identifiers with aliases support
42+
- Custom exceptions: `InvalidLanguageException`, `InvalidThemeException`, `ThemeNotSetException`
43+
- PHP as default language for code blocks without specified language
44+
- Comprehensive test suite
45+
46+
### Changed
47+
- **BREAKING**: Removed Singleton pattern from all highlighter classes (`HighlighterPHP`, `HighlighterXML`, `HighlighterBash`)
48+
- **BREAKING**: Made `HighlighterBase` an abstract class (cannot be instantiated directly)
49+
- **BREAKING**: Added `ext-dom` PHP extension requirement (previously optional with regex fallback)
50+
- Improved HTML attribute parsing using `DOMDocument` with regex fallback
51+
- Enhanced syntax highlighting logic in `HighlighterBase`
52+
- Improved XML/HTML highlighting: fixed line-by-line processing, proper attribute highlighting
53+
- Updated PHPDoc comments throughout the codebase
54+
55+
### Fixed
56+
- Fixed issue with extra empty lines at the beginning and end of code blocks
57+
- Fixed line numbering

README.md

Lines changed: 56 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
PHPHighlight is a PHP syntax highlighting library that can be easily customized and extended.
44

55
## How it works
6-
The library parses the text, finds the \<pre> tag, reads the attributes (data-lang, data-file, data-theme) and highlights the syntax of the code block.
6+
The library parses the text, finds the `<pre>` and `<pre><code>` tags, reads the attributes (data-lang, data-file, data-theme) and highlights the syntax of the code block.
7+
8+
**Recommended:** Use `<pre><code>` pattern for better semantics and compatibility with Markdown output.
79

810
Supports style customization. Here are examples of styling:
911

10-
<img width="757" height="309" src="https://demyanov.dev/sites/default/files/images/phphighlight2.png" alt="styling example">
12+
<img width="757" height="309" src="examples/img/scr_01.png" alt="styling example">
1113

1214
## Requirements
1315
PHP 8.1+
@@ -19,7 +21,7 @@ $ composer require demyanovs/php-highlight
1921
```
2022

2123
## Usage
22-
See full example here [index.php](../master/examples/index.php)
24+
See full example in [examples/index.php](examples/index.php)
2325
```php
2426
<?php
2527

@@ -29,7 +31,7 @@ use Demyanovs\PHPHighlight\Highlighter;
2931
use Demyanovs\PHPHighlight\Themes\ObsidianTheme;
3032

3133
$text = '
32-
<pre data-file="php-highlight/examples/index.php" data-lang="php">
34+
<pre><code class="language-php" data-file="php-highlight/examples/index.php">
3335
&lt;?php
3436
abstract class AbstractClass
3537
{
@@ -62,13 +64,12 @@ class ConcreteClass extends AbstractClass
6264
$class = new ConcreteClass;
6365
echo $class->prefixName("Pacman"), "\n";
6466
echo $class->prefixName("Pacwoman"), "\n";
65-
</pre>
67+
</code></pre>
6668
';
6769

68-
$highlighter = new Highlighter($text, ObsidianTheme::TITLE);
69-
// Configuration
70-
$highlighter->showLineNumbers(true);
71-
$highlighter->showActionPanel(true);
70+
$highlighter = (new Highlighter($text, ObsidianTheme::TITLE))
71+
->showLineNumbers(true)
72+
->showActionPanel(true);
7273
echo $highlighter->parse();
7374
```
7475

@@ -78,19 +79,53 @@ $highlighter->showLineNumbers(true);
7879
$highlighter->showActionPanel(true);
7980
```
8081

81-
You can set following attributes in \<pre> tag
82-
\<pre data-lang="php" data-file="example.php" data-theme="drakuala">
83-
* lang - a language of the text. This affects how the parser will highlight the syntax.
84-
* file - show file name in action panel.
85-
* theme - allows to overwrite the global theme.
82+
You can set following attributes in `<pre>` or `<code>` tags:
83+
```html
84+
<pre><code class="language-php" data-file="example.php" data-theme="darkula">
85+
// or
86+
<pre data-lang="php" data-file="example.php" data-theme="darkula"><code>
87+
```
88+
89+
* `data-lang` or `class="language-*"` - a language of the text. This affects how the parser will highlight the syntax.
90+
* `data-file` - show file name in action panel.
91+
* `data-theme` - allows to overwrite the global theme.
92+
93+
**Note:** `class="language-*"` on `<code>` tag is automatically recognized (common in Markdown output).
8694

8795
### How to create a custom theme
88-
To create a custom theme you need to create an instance of Demyanovs\PHPHighlight\Themes\Theme class
96+
To create a custom theme you need to create an instance of `Demyanovs\PHPHighlight\Themes\Theme` class
8997
and pass it to Highlighter as a third argument:
9098
```php
91-
$defaultColorSchemaDto = new DefaultColorSchemaDto(...);
92-
$PHPColorSchemaDto = new PHPColorSchemaDto(...);
93-
$XMLColorSchemaDto = new XMLColorSchemaDto(...);
99+
use Demyanovs\PHPHighlight\Highlighter;
100+
use Demyanovs\PHPHighlight\Themes\Theme;
101+
use Demyanovs\PHPHighlight\Themes\Dto\DefaultColorSchemaDto;
102+
use Demyanovs\PHPHighlight\Themes\Dto\PHPColorSchemaDto;
103+
use Demyanovs\PHPHighlight\Themes\Dto\XMLColorSchemaDto;
104+
105+
$defaultColorSchemaDto = new DefaultColorSchemaDto(
106+
'#000000', // background
107+
'#ffffff', // default text
108+
'#888888', // comment
109+
'#ff0000', // keyword
110+
'#00ff00', // string
111+
'#0000ff', // number
112+
'#ffff00' // variable
113+
);
114+
115+
$PHPColorSchemaDto = new PHPColorSchemaDto(
116+
'#0000BB', // keyword
117+
'#FF8000', // variable
118+
'#fbc201', // function
119+
'#007700', // string
120+
'#DD0000' // comment
121+
);
122+
123+
$XMLColorSchemaDto = new XMLColorSchemaDto(
124+
'#008000', // tag
125+
'#7D9029', // attribute
126+
'#BA2121', // string
127+
'#BC7A00' // comment
128+
);
94129

95130
$myTheme = new Theme(
96131
'myThemeTitle',
@@ -124,5 +159,8 @@ Pull requests are welcome. For major changes, please open an issue first to disc
124159

125160
Please make sure to update tests as appropriate.
126161

162+
## Changelog
163+
See [CHANGELOG.md](./CHANGELOG.md) for a list of changes and version history.
164+
127165
## License
128166
[MIT](./LICENSE.md)

composer.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717
}
1818
],
1919
"require": {
20-
"php": ">=8.1"
20+
"php": ">=8.1",
21+
"ext-dom": "*"
2122
},
2223
"autoload": {
2324
"psr-4": {
@@ -31,13 +32,15 @@
3132
},
3233
"require-dev": {
3334
"phpunit/phpunit": "^10.2",
34-
"squizlabs/php_codesniffer": "*",
35+
"squizlabs/php_codesniffer": "^3.13",
3536
"doctrine/coding-standard": "^12.0"
3637
},
3738
"config": {
3839
"allow-plugins": {
3940
"dealerdirect/phpcodesniffer-composer-installer": true
40-
}
41+
},
42+
"sort-packages": true,
43+
"prefer-stable": true
4144
},
4245
"scripts": {
4346
"test": "./vendor/bin/phpunit",

examples/css/highlighter.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,7 @@
5454
.code-highlighter .line-number {
5555
display: block;
5656
}
57+
58+
.code-block-wrapper .code-block {
59+
display: block;
60+
}

examples/img/scr_01.png

186 KB
Loading

examples/index.php

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
$text = '
1717
<h2>PHP</h2>
18-
<pre data-file="php-highlight/examples/index.php" data-lang="php">
18+
<pre><code class="language-php" data-file="php-highlight/examples/index.php">
1919
&lt;?php
2020
abstract class AbstractClass
2121
{
@@ -48,10 +48,10 @@ public function prefixName(string $name): string
4848
$class = new ConcreteClass;
4949
echo $class->prefixName("Pacman"), "\n";
5050
echo $class->prefixName("Pacwoman"), "\n";
51-
</pre>
51+
</code></pre>
5252
5353
<h2>JavaScript</h2>
54-
<pre data-file="example.js" data-lang="js">
54+
<pre><code class="language-javascript" data-file="example.js">
5555
// Arrow functions let us omit the `function` keyword. Here `long_example`
5656
// points to an anonymous function value.
5757
const long_example = (input1, input2) => {
@@ -65,10 +65,10 @@ public function prefixName(string $name): string
6565
6666
long_example(2, 3); // Prints "Hello, World!" and returns 5.
6767
short_example(2); // Returns 7.
68-
</pre>
68+
</code></pre>
6969
7070
<h2>Bash</h2>
71-
<pre data-file="example.sh" data-lang="bash">
71+
<pre><code class="language-bash" data-file="example.sh">
7272
#!/bin/bash
7373
read -p "Enter number : " n
7474
if test $n -ge 0
@@ -77,10 +77,10 @@ public function prefixName(string $name): string
7777
else
7878
echo "$n number is negative number."
7979
fi
80-
</pre>
80+
</code></pre>
8181
8282
<h2>Go</h2>
83-
<pre data-lang="go" data-file="main.go">
83+
<pre><code class="language-go" data-file="main.go">
8484
package main
8585
8686
import "fmt"
@@ -104,9 +104,9 @@ public function prefixName(string $name): string
104104
fmt.Scanln()
105105
fmt.Println("done")
106106
}
107-
</pre>
107+
</code></pre>
108108
<h2>Xml</h2>
109-
<pre data-lang="xml" data-file="recipe.xml">
109+
<pre><code class="language-xml" data-file="recipe.xml">
110110
<?xml version="1.0" encoding="utf-8"?>
111111
<!DOCTYPE recipe>
112112
<recipe name="bread" preptime="5min" cooktime="180min">
@@ -130,10 +130,10 @@ public function prefixName(string $name): string
130130
</step>
131131
</instructions>
132132
</recipe>
133-
</pre>
133+
</code></pre>
134134
135135
<h2>HTML</h2>
136-
<pre data-lang="html" data-file="index.html">
136+
<pre><code class="language-html" data-file="index.html">
137137
<!DOCTYPE html>
138138
<title>Title</title>
139139
@@ -150,18 +150,17 @@ function $init() {return true;}
150150
Mix all ingredients and knead thoroughly.
151151
</div>
152152
</body>
153-
</pre>
153+
</code></pre>
154154
';
155155

156156
require_once '../vendor/autoload.php';
157157

158158
use Demyanovs\PHPHighlight\Highlighter;
159159
use Demyanovs\PHPHighlight\Themes\ObsidianTheme;
160160

161-
$highlighter = new Highlighter($text, ObsidianTheme::TITLE);
162-
// Configuration
163-
$highlighter->showLineNumbers(true);
164-
$highlighter->showActionPanel(true);
161+
$highlighter = (new Highlighter($text, ObsidianTheme::TITLE))
162+
->showLineNumbers(true)
163+
->showActionPanel(true);
165164
echo $highlighter->parse();
166165

167166
?>

phpcs.xml.dist

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,13 @@
2828
<exclude name="SlevomatCodingStandard.Commenting.RequireOneLineDocComment.MultiLineDocComment"/>
2929
<exclude name="SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed"/>
3030
<exclude name="SlevomatCodingStandard.PHP.RequireExplicitAssertion.RequiredExplicitAssertion"/>
31+
<exclude name="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousSuffix"/>
3132
<exclude name="Generic.Formatting.SpaceAfterNot.Incorrect"/>
3233
<exclude name="Generic.Formatting.MultipleStatementAlignment.NotSame"/>
3334
<exclude name="Squiz.Functions.FunctionDeclarationArgumentSpacing.SpacingAfterHint"/>
3435
<exclude name="Squiz.Functions.MultiLineFunctionDeclaration.NewlineBeforeOpenBrace"/>
3536
</rule>
3637

3738
<exclude-pattern>examples/</exclude-pattern>
39+
<exclude-pattern>tests/</exclude-pattern>
3840
</ruleset>

0 commit comments

Comments
 (0)