Embedded languages
Some host languages delegate parts of their source to another registered parser. The outer highlighter still returns one escaped HTML block and uses one theme.
Built-in behavior
| Host identifier | Embedded content | Target identifier |
|---|---|---|
html |
Content of <style> tags |
css |
html |
Content of <script> tags |
javascript |
svg |
Content of <style> tags |
css |
svg |
Content of <script> tags |
javascript |
markdown |
Content of a fenced block whose info string is an identifier | Dynamic |
twig |
Template text outside Twig delimiters | html |
HTML and SVG use declarative tag triggers from the default
EmbeddedLanguageRegistry. Markdown resolves the fenced identifier
dynamically. Twig parses its expressions and tags itself, while delegating
ordinary template text to HTML.
The default Twig plan has no named block mappings. Add them explicitly when a Twig block contains CSS, JavaScript, or another language.
HTML and SVG tags
No extra configuration is required:
<?php
$source = <<<'HTML'
<style>
.notice { color: rebeccapurple; }
</style>
<script>
const notice = document.querySelector('.notice');
</script>
HTML;
$html = $highlighter->highlight($source, 'html');The tag and attributes use the host parser. Text up to the matching closing tag
uses the css or javascript parser.
Markdown fences
Use an exact registered identifier in the fence:
```php
echo "Embedded PHP";Embedded PHP may omit its opening tag. The highlighter adds one for parsing and removes the synthetic tag from the rendered result.
If the fence has no identifier, its content is rendered as code text. If the identifier is unknown or an embedded parser fails, the host highlight still succeeds and keeps that content visible with the generic string scope.
Named Twig blocks
Create a registry that replaces the empty default Twig plan while preserving the other defaults:
<?php
use Alto\Code\Highlight\Embedded\EmbeddedLanguagePlan;
use Alto\Code\Highlight\Embedded\EmbeddedLanguageRegistry;
use Alto\Code\Highlight\Embedded\EmbeddedTrigger;
use Alto\Code\Highlight\Highlighter;
use Alto\Code\Highlight\Theme\AltoTheme;
$plans = EmbeddedLanguageRegistry::getDefaultPlans();
$plans[] = EmbeddedLanguagePlan::forHost('twig', [
EmbeddedTrigger::block('css', 'css'),
EmbeddedTrigger::block('javascript', 'javascript'),
]);
$registry = new EmbeddedLanguageRegistry($plans);
$highlighter = new Highlighter(new AltoTheme(), $registry);
$html = $highlighter->highlight(
'{% block javascript %}const ready = true;{% endblock %}',
'twig',
);Block names and target identifiers are normalized to lowercase.
Passing a custom registry to Highlighter does not merge plans automatically.
The example starts with getDefaultPlans() so HTML, SVG, and Markdown keep
their built-in behavior. A later plan for the same host replaces the earlier
one.
Customize tag triggers
Attribute constraints can route a tag to a different parser. Put a constrained trigger before a generic trigger for the same tag:
<?php
$registry = new EmbeddedLanguageRegistry([
EmbeddedLanguagePlan::forHost('html', [
EmbeddedTrigger::tag('style', 'css'),
EmbeddedTrigger::tag('script', 'typescript', [
'type' => ['text/typescript', 'application/typescript'],
]),
EmbeddedTrigger::tag('script', 'javascript'),
]),
]);Constraint names and values are compared case-insensitively. A null
constraint requires only that the attribute be present.
Toggle a host/target pair
Configured tag or block triggers are enabled by default:
<?php
$highlighter->setEmbeddingEnabled('html', 'javascript', false);
$plainScript = $highlighter->highlight($source, 'html');
$highlighter->setEmbeddingEnabled('html', 'javascript', true);
$parsedScript = $highlighter->highlight($source, 'html');The toggle is stored per highlighter instance and per normalized
host:target pair. Disabling a pair keeps the embedded source visible, but the
host parser treats it as markup text instead of delegating it.
Dynamic Markdown fences are not declarative triggers, so
setEmbeddingEnabled() does not toggle them.