Symfony League CommonMarkdown 自定义ExternalLinksExtension
在 Symfony 4/5/6.1 上的 services.yml 中自定义ExternalLinksExtension的正确方法是怎样的?
根据官方文档 ExternalLinksExtension 假设配置参数必须被传递到环境。但是,环境不是服务,也不会实例化为服务,即使它是这样声明的。它直接从初始化 CommonMarkdown 包的函数实例化,其中将空参数传递给它。
通过制作自定义扩展,也无法修改当前环境的配置。从 ExtensionInterface
继承不会为您提供此类访问权限。
我当前的方法是复制本机扩展 ExternalLinksExtension
的所有内容,并在 configureSchema 方法中将当前环境的配置与自定义参数合并。
class ExternalLinksExtension implements ConfigurableExtensionInterface
{
public function configureSchema(ConfigurationBuilderInterface $builder): void
{
$applyOptions = [
ExternalLinkProcessor::APPLY_NONE,
ExternalLinkProcessor::APPLY_ALL,
ExternalLinkProcessor::APPLY_INTERNAL,
ExternalLinkProcessor::APPLY_EXTERNAL,
];
$builder->addSchema('external_link', Expect::structure([
'internal_hosts' => Expect::type('string|string[]'),
'open_in_new_window' => Expect::bool(false),
'html_class' => Expect::string()->default(''),
'nofollow' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_NONE),
'noopener' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL),
'noreferrer' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL),
]));
//this is where I pass custom arfuments
$builder->merge([
'external_link' => [
'internal_hosts' => ["localhost"],
'open_in_new_window' => true,
'html_class' => 'external-link',
'nofollow' => '',
'noopener' => 'external',
'noreferrer' => 'external',
]
]);
}
public function register(EnvironmentBuilderInterface $environment): void
{
$environment->addEventListener(DocumentParsedEvent::class, new ExternalLinkProcessor($environment->getConfiguration()), -50);
}
}
这种方式对我有用,但我认为必须复制您想要自定义的所有扩展或者必须进行此类黑客攻击并不方便,应该有另一种更直接的配置方法。
在我的 service.yml 文件中
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
League\CommonMark\Environment\Environment:
public: true
arguments:
-
external_link:
-
internal_hosts: [ "localhost" ]
open_in_new_window: true
html_class: "external-link"
nofollow: ""
noopener: "external"
noreferrer: "external"
League\CommonMark\Extension\Table\TableExtension:
tags:
- { name: twig.markdown.league_extension }
League\CommonMark\Extension\Autolink\AutolinkExtension:
tags:
- { name: twig.markdown.league_extension }
League\CommonMark\Extension\Strikethrough\StrikethroughExtension:
tags:
- { name: twig.markdown.league_extension }
App\Service\League\CommonMark\ExternalLinksExtension:
arguments: ... ##arguments here also doesnt work with the native extension
tags:
- { name: twig.markdown.league_extension }
twig docs 提到扩展必须使用标签 twig.markdown.league_extension
How is the correct way to customize the ExternalLinksExtension in the services.yml on Symfony 4/5/6.1?
according to official documentation ExternalLinksExtension it is assumed that the configuration parameters must be passed to the Enviroment. However, the Enviroment is not a service and is not instantiated as a service, even if it is declared as such. It is instantiated directly from the function that initializes the CommonMarkdown bundle, where empty arguments are passed on to it.
By making a custom extension there is also no way to modify the configuration of the current environment. Inheriting from ExtensionInterface
does not give you such access.
The current way I do it is to copy all the content of the native extension ExternalLinksExtension
and in the configureSchema method merge the configuration of the current environment with custom arguments.
class ExternalLinksExtension implements ConfigurableExtensionInterface
{
public function configureSchema(ConfigurationBuilderInterface $builder): void
{
$applyOptions = [
ExternalLinkProcessor::APPLY_NONE,
ExternalLinkProcessor::APPLY_ALL,
ExternalLinkProcessor::APPLY_INTERNAL,
ExternalLinkProcessor::APPLY_EXTERNAL,
];
$builder->addSchema('external_link', Expect::structure([
'internal_hosts' => Expect::type('string|string[]'),
'open_in_new_window' => Expect::bool(false),
'html_class' => Expect::string()->default(''),
'nofollow' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_NONE),
'noopener' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL),
'noreferrer' => Expect::anyOf(...$applyOptions)->default(ExternalLinkProcessor::APPLY_EXTERNAL),
]));
//this is where I pass custom arfuments
$builder->merge([
'external_link' => [
'internal_hosts' => ["localhost"],
'open_in_new_window' => true,
'html_class' => 'external-link',
'nofollow' => '',
'noopener' => 'external',
'noreferrer' => 'external',
]
]);
}
public function register(EnvironmentBuilderInterface $environment): void
{
$environment->addEventListener(DocumentParsedEvent::class, new ExternalLinkProcessor($environment->getConfiguration()), -50);
}
}
This way it works for me, but I believe that it is not convenient to have to be copying all the extensions that you want to customize or that you must make this type of hacks, there should be another more direct method of configuration.
In my service.yml file
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
- '../src/Tests/'
# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\Controller\:
resource: '../src/Controller/'
tags: ['controller.service_arguments']
League\CommonMark\Environment\Environment:
public: true
arguments:
-
external_link:
-
internal_hosts: [ "localhost" ]
open_in_new_window: true
html_class: "external-link"
nofollow: ""
noopener: "external"
noreferrer: "external"
League\CommonMark\Extension\Table\TableExtension:
tags:
- { name: twig.markdown.league_extension }
League\CommonMark\Extension\Autolink\AutolinkExtension:
tags:
- { name: twig.markdown.league_extension }
League\CommonMark\Extension\Strikethrough\StrikethroughExtension:
tags:
- { name: twig.markdown.league_extension }
App\Service\League\CommonMark\ExternalLinksExtension:
arguments: ... ##arguments here also doesnt work with the native extension
tags:
- { name: twig.markdown.league_extension }
the twig docs, mentions that the extensions must go with the tag twig.markdown.league_extension
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
根据 此讨论 和 PR其次,从 Twig 3.3.5 开始,Twig/Extra-Bundle 包含一个工厂,该工厂仅依赖于在 services.yaml 中声明所需的扩展,并使用特定标签
twig.markdown.league_extension
:这对我有用,使用 TableExtension 和我的 twig/extra-bundle v3.3.8。
According to this discussion and the PR that followed, since Twig 3.3.5, the Twig/Extra-Bundle contains a factory that simply relies on declaring the desired extensions in services.yaml, with the specific tag
twig.markdown.league_extension
:This worked for me, with TableExtension and my twig/extra-bundle v3.3.8.
我也找不到在 symfony 中使用配置的方法。 lmeyer 提到了一种解决方法,其中创建了一个自定义工厂类
twig.markdown.league_common_mark_converter_factory
,您可以在其中自定义配置(还包括扩展的设置):https://github.com/twigphp/Twig/issues/3725#issuecomment-1367948462I couldnt find a way to use the configuration in symfony either. lmeyer mentioned a workaround where a custom factory class
twig.markdown.league_common_mark_converter_factory
is created in which you can customize the config (and also inlcude settings of the extensions): https://github.com/twigphp/Twig/issues/3725#issuecomment-1367948462