nystudio107 / craft-code-editor
提供具有 Twig & Craft API 自动完成的代码编辑器字段
Requires
- craftcms/cms: ^3.0.0 || ^4.0.0 || ^5.0.0
- phpdocumentor/reflection-docblock: ^5.0.0
Requires (Dev)
- craftcms/ecs: dev-main
- craftcms/phpstan: dev-main
- craftcms/rector: dev-main
README
Craft CMS 3.x, 4.x & 5.0 的代码编辑器
提供具有 Twig & Craft API 自动完成的代码编辑器字段
要求
Code Editor 需要 Craft CMS 3.x, 4.x 或 5.x。
安装
要安装 Code Editor,请按照以下步骤操作
-
打开您的终端并进入您的 Craft 项目
cd /path/to/project
-
然后告诉 Composer 需要此包
composer require nystudio107/craft-code-editor
关于 Code Editor
Code Editor 提供了一个功能齐全的代码编辑器,通过强大的 Monaco Editor(这是 VS Code 的基础编辑器)进行语法高亮。
它还可以处理数百种其他代码语言,例如 JavaScript、TypeScript、CSS、Markdown 以及更多。
Code Editor 提供了 Twig 过滤器/函数/标签和完整的 Craft CMS API 的完整自动完成,包括已安装的插件
当您将鼠标悬停在表达式上时,它还会添加悬停文档
您还可以添加自己的自定义自动完成,并自定义编辑器的行为。
Code Editor 还为 Twig 模板和对象模板提供 Yii2 验证器。
如果您需要 Craft CMS 字段,请使用 Code Field 插件,该插件提供包装在字段类型中的 Code Editor。
使用 Code Editor
一旦您将 nystudio107/craft-code-editor
包添加到您的插件、模块或项目中,就无需进一步设置。这是因为它作为自动引导的 Yii2 模块运行。
Code Editor 不是一个 Craft CMS 插件,而是一个供插件、模块或项目使用的包。
将其添加到现有项目中非常容易,正如您可以从 Preparse field pull request 中看到,它添加了 Preparse 插件。
在 Craft CP 中
Code Editor 的工作方式与 Craft CMS forms
宏类似,这对于插件和模块开发者来说应该很熟悉。
导入宏
只需导入宏即可
{% import "codeeditor/codeEditor" as codeEditor %}
多行编辑器
然后,要创建一个 textarea
多行编辑器,请执行以下操作
{{ codeEditor.textarea({ id: "myCodeEditor", name: "myCodeEditor", value: textAreaText, }) }}
...其中 textAreaText
是包含编辑器字段中应显示的初始文本的变量。这将创建 Twig 编辑器。
要创建一个 textareaField
多行编辑器,请执行以下操作
{{ codeEditor.textareaField({ label: "Twig Editor"|t, instructions: "Enter any Twig code below, with full API autocompletion."|t, id: "myCodeEditor", name: "myCodeEditor", value: textAreaText, }) }}
...其中 textAreaText
是包含编辑器字段中应显示的初始文本的变量。这将创建 label
和 instructions
,以及 Twig 编辑器。
单行编辑器
要创建一个单行 text
编辑器,请按照以下步骤操作
{{ codeEditor.text({ id: "myCodeEditor", name: "myCodeEditor", value: text, }) }}
...其中 text
是一个变量,包含应出现在编辑器字段中的初始文本。这将创建一个仅限于单行的 Twig 编辑器,用于简单的 Twig 表达式。
要创建一个 textField
单行编辑器,请按照以下步骤操作
{{ codeEditor.textField({ label: "Twig Editor"|t, instructions: "Enter any Twig code below, with full API autocompletion."|t, id: "myCodeEditor", name: "myCodeEditor", value: text, }) }}
...其中 text
是一个变量,包含应出现在编辑器字段中的初始文本。这将创建 label
和 instructions
,以及仅限于单行的 Twig 编辑器,用于简单的 Twig 表达式。
无论使用哪个宏,都会包含一个包含编辑器所需 CSS 和 JavaScript 的资产包,并初始化编辑器。
在前端模板中
代码编辑器也适用于前端模板,但您可以通过 allowTemplateAccess
配置设置禁用它。默认情况下是启用的。
还有一个默认禁用的 allowFrontendAccess
。这允许访问 codeeditor/autocomplete/index
端点,用于 Twig 和 Craft API 自动完成。默认情况下是禁用的,因此如果您想在前端使用这些自动完成,则需要明确启用它。
通过复制 config.php
文件到 Craft CMS 的 config/
目录,并在过程中将文件重命名为 codeeditor.php
,然后设置 allowFrontendAccess
设置为 true
来实现此操作
return [ // Whether to allow anonymous access be allowed to the codeeditor/autocomplete/index endpoint 'allowFrontendAccess' => true, // Whether to allow frontend templates access to the `codeeditor/codeEditor.twig` Twig template 'allowTemplateAccess' => true, // The default autocompletes to use for the default `CodeEditor` field type 'defaultCodeEditorAutocompletes' => [ CraftApiAutocomplete::class, TwigLanguageAutocomplete::class, SectionShorthandFieldsAutocomplete::class, ] ];
然后导入宏
{% import "codeeditor/codeEditor" as codeEditor %}
创建自己的 <textarea>
元素,并包含必要的 JavaScript,传递您的 textarea
元素的 id
<textarea id="myCodeEditor"> </textarea> {{ codeEditor.includeJs("myCodeEditor") }}
启用 allowFrontendAccess
设置允许访问 codeeditor/autocomplete/index
端点,并将 codeeditor/templates
目录添加到模板根目录。
以下 monacoOptions
允许您使字段为只读(尽管用户仍然可以与代码交互)
{ "domReadOnly": true, "readOnly": true }
附加选项
textarea
、textareaField
、text
、textField
和 includeJs
宏都接受三个可选参数
{{ textarea(config, fieldType, editorOptions, codeEditorOptions) }} {{ textareaField(config, fieldType, editorOptions, codeEditorOptions }} {{ text(config, fieldType, editorOptions, codeEditorOptions) }} {{ textField(config, fieldType, editorOptions, codeEditorOptions }} {{ includeJs(fieldId, fieldType, editorOptions, codeEditorOptions }}
fieldType
fieldType
- 可选的第二个参数。默认设置为 代码编辑器
。您只需在您使用自定义自动完成时将其更改为其他设置(见下文)
例如:
{{ codeEditor.textarea({ id: 'myCodeEditor', name: 'myCodeEditor', value: textAreaText, }), "MyCustomFieldType" }}
editorOptions
editorOptions
- 可选的第四个参数。这是一个传递给 Monaco 编辑器进行配置的 EditorOption。默认情况下,这是一个空对象。
您通常会使用 editorOptions
来指定代码编辑器使用的 language
或 theme
,但您也可以覆盖任何您喜欢的 EditorOption。
例如:
{{ codeEditor.textareaField({ label: "Twig Editor"|t, instructions: "Enter any Twig code below, with full API autocompletion."|t, id: 'myCodeEditor', name: "myCodeEditor", value: textAreaText, }), "Code Editor", { language: "javascript", theme: "vs-dark", } }}
codeEditorOptions
codeEditorOptions
- 可选的第五个参数。这是一个可以包含您想要从 Twig 模板传递到自动完成的任何数据的对象。这可以在自定义自动完成中利用,以便将特定字段的上下文传递给自动完成(见下文)
例如:
{{ codeEditor.textareaField({ label: "Twig Editor"|t, instructions: "Enter any Twig code below, with full API autocompletion."|t, id: "myCodeEditor", name: "myCodeEditor", value: textAreaText, }), "Code Editor", { lineNumbers: "on" }, { wrapperClass: "my-css-class another-css-class", placeholderText: "Type something!", } }}
您可以向 codeEditorOptions
传递任何您喜欢的选项(这可能用于自定义自动完成),但以下预定义选项具有特殊意义
wrapperClass
-string
- 添加到代码编辑器编辑器包装器div
的附加类。默认情况下,这是一个空字符串。已捆绑monaco-editor-background-frame
类,会使字段看起来像 Craft CMS 编辑器字段,但您也可以使用自己的类。还有一个捆绑的monaco-editor-inline-frame
样式,用于表格单元格中的内联编辑器(或不需要边框的其他地方)。singleLineEditor
-布尔值
- 是否使编辑器表现得像单行文本字段。对于text
和textField
Twig 宏,此选项设置为true
,而对于textarea
和textareaField
Twig 宏,设置为false
。placeholderText
-字符串
- 当代码编辑器字段为空时,应显示的占位符文本。displayLanguageIcon
-布尔值
- 如果可用,是否应在代码编辑器的右上角显示语言图标。- fileName -
字符串
- 正在显示的文件名,用于让 Monaco 根据文件名后缀确定要使用的语言 - fixedHeightEditor -
布尔值
- 通常,编辑器将动态调整大小以适应其内容。如果此选项设置为true
,则编辑器将具有由其父容器确定的固定高度(需要时带有滚动条) - maxEditorRows -
数字
- 在固定高度并添加滚动条之前,编辑器可以具有的最大行数。如果您想有无限行数且不带滚动条,请将其设置为0
。默认为50
使用附加自动完成功能
代码编辑器仅在编辑器语言为 twig
时添加自动完成。原因有两个
- 提供代码编辑器动力的基于 VScode 的 Monaco 编辑器对 Twig 的支持较差,因此代码编辑器为 Twig 语言提供了自动完成
- Craft 通过 Craft API、过滤器、函数等形式,以动态方式向 Twig 语言添加了一系列功能,代码编辑器负责将这些功能提供给 Monaco 编辑器
其他语言有更强大的支持,并自带自动完成和语法高亮。
默认情况下,代码编辑器使用 CraftApiAutocomplete
和 TwigLanguageAutocomplete
,但它还包括一个可选的 EnvironmentVariableAutocomplete
,该插件提供任何 Craft CMS 环境变量 和 别名 的自动完成。
如果您想使用 EnvironmentVariableAutocomplete
或您编写的自定义自动完成,您需要在插件、模块或项目中添加一些 PHP 代码
use nystudio107\codeeditor\autocompletes\EnvironmentVariableAutocomplete; use nystudio107\codeeditor\events\RegisterCodeEditorAutocompletesEvent; use nystudio107\codeeditor\services\AutocompleteService; Event::on( AutocompleteService::class, AutocompleteService::EVENT_REGISTER_CODEEDITOR_AUTOCOMPLETES, function (RegisterCodeEditorAutocompletesEvent $event) { $event->types[] = EnvironmentVariableAutocomplete::class; } );
上面的代码将为所有代码编辑器添加环境变量和别名自动完成。
但是,由于您可能在同一页面上有多个代码编辑器实例,并且它们可能提供不同的自动完成,您可能只想在 fieldType
匹配特定值时选择性地添加自定义自动完成。
以下是从 Sprig 插件 中的一个示例
use nystudio107\codeeditor\events\RegisterCodeEditorAutocompletesEvent; use nystudio107\codeeditor\services\AutocompleteService; use putyourlightson\sprig\plugin\autocompletes\SprigApiAutocomplete; public const SPRIG_TWIG_FIELD_TYPE = 'SprigField'; Event::on( AutocompleteService::class, AutocompleteService::EVENT_REGISTER_CODEEDITOR_AUTOCOMPLETES, function (RegisterCodeEditorAutocompletesEvent $event) { if ($event->fieldType === self::SPRIG_TWIG_FIELD_TYPE) { $event->types[] = SprigApiAutocomplete::class; } } );
这确保了只有当传递给代码编辑器宏的 fieldType
设置为 SprigField
时,才会添加 SprigApiAutocomplete
自动完成。
此外,您可能有一个在实例化时要向下传递配置信息的自动完成。您可以通过将其作为数组添加来自行完成此操作
use nystudio107\codeeditor\autocompletes\CraftApiAutocomplete; use nystudio107\codeeditor\events\RegisterCodeEditorAutocompletesEvent; use nystudio107\codeeditor\services\AutocompleteService; Event::on( AutocompleteService::class, AutocompleteService::EVENT_REGISTER_CODEEDITOR_AUTOCOMPLETES, function (RegisterCodeEditorAutocompletesEvent $event) { $config = [ 'additionalGlobals' => $arrayOfVariables, ]; $event->types[] = [CraftApiAutocomplete::class => $config]; } );
请注意,上述所有示例都 添加 自动完成到代码编辑器默认提供的自动完成中(CraftApiAutocomplete
和 TwigLanguageAutocomplete
)。如果您想 完全替换 它们,请先清空 types[]
数组。
$event->types[] = []; $event->types[] = [CraftApiAutocomplete::class => $config];
编写自定义自动完成
一个简单的自动完成看起来像这样
<?php namespace myvendor\myname\autocompletes; use nystudio107\codeeditor\base\Autocomplete; use nystudio107\codeeditor\models\CompleteItem; use nystudio107\codeeditor\types\AutocompleteTypes; use nystudio107\codeeditor\types\CompleteItemKind; class MyCustomAutocomplete extends Autocomplete { public $name = 'EnvironmentVariableAutocomplete'; public $type = AutocompleteTypes::GeneralAutocomplete; public $hasSubProperties = false; public function generateCompleteItems(): void { CompleteItem::create() ->label('MyAutocomplete') ->insertText('MyAutocomplete') ->detail('This is my autocomplete') ->documentation('This detailed documentation of my autocomplete') ->kind(CompleteItemKind::ConstantKind) ->add($this); } }
$name
属性是您的自动完成名称,用于自动完成缓存。
$type
属性可以是 AutocompleteTypes::TwigExpressionAutocomplete
(仅在 Twig 表达式中自动完成)或 AutocompleteTypes::GeneralAutocomplete
(在任何地方自动完成)。
$hasSubProperties
属性表示您的自动完成是否返回嵌套子属性,例如 foo.bar.baz
。这个提示有助于代码编辑器提供更好的自动完成体验。
CompleteItem::create()
是一个工厂方法,用于创建 CompleteItem
对象。您可以使用上面的 Fluent Model 设置器,或者也可以直接在模型上设置属性。CompleteItem::add()
方法将其添加到生成的自动完成列表中。
您的自动完成还有一个 $codeEditorOptions
属性,它将包含通过可选的第五个 codeEditorOptions
参数从您的 Twig 模板传递下来的任何数据。这允许您具有特定字段的上下文信息。
请参阅以下示例,您可以根据这些示例创建自定义自动完成
- TrackingVarsAutocomplete
- SprigApiAutocomplete
- CraftApiAutocomplete
- EnvironmentVariableAutocomplete
- TwigLanguageAutocomplete
Twig 模板验证器
代码编辑器还包含两个 Twig 模板验证器,您可以使用它们来验证作为模型一部分保存的 Twig 模板
- TwigTemplateValidator - 通过
renderString()
验证模板 - TwigObjectTemplateValidator - 通过
renderObjectTemplate()
验证模板
您只需将它们作为规则添加到模型中,它就会传播模型,并在渲染模板时遇到任何错误
use nystudio107\codeeditor\validators\TwigTemplateValidator; public function defineRules() { return [ ['myTwigCode', TwigTemplateValidator::class], ]; }
您还可以添加在 Twig 环境中应存在的任何 variables
use nystudio107\codeeditor\validators\TwigTemplateValidator; public function defineRules() { return [ [ 'myTwigCode', TwigTemplateValidator::class, 'variables' => [ 'foo' => 'bar', ] ], ]; }
对于 TwigObjectTemplateValidator
,您还可以传入在渲染对象模板时应使用的 object
use nystudio107\codeeditor\validators\TwigObjectTemplateValidator; public function defineRules() { return [ [ 'myTwigCode', TwigObjectTemplateValidator::class, 'object' => $object, 'variables' => [ 'foo' => 'bar', ] ], ]; }
JSON Schema 自动完成
代码编辑器所基于的 Monaco 编辑器支持 JSON Schema,用于 JSON 自动完成,这允许您为 JSON 编辑器实例定义模式。
您可以在 Monaco playground 中尝试这个示例
代码编辑器添加了一些支持,使其更易于实现,以下是从 Craft Code Field 插件 中获取的一个示例,展示了如何通过 Twig 模板 来实现
{% js %} // Add schema definitions for this JSON editor field var jsonSchemaUri = 'https://craft-code-editor.com/{{ "monacoEditorOptions"|namespaceInputId }}'; var jsonSchema = { uri: jsonSchemaUri, fileMatch: [jsonSchemaUri], schema: {{ optionsSchema | raw }} } // configure the JSON language support with schemas and schema associations monaco.languages.json.jsonDefaults.setDiagnosticsOptions({ validate: true, schemas: [jsonSchema] }); {% endjs %}
...其中 optionsSchema
变量是 注入到模板中的,并包含 IEditorOptionsSchema.json
文件的内容。
您可以选择通过 Asset Bundle 使用 XHR 获取此文件,或者直接内联模式定义。
代码编辑器路线图
一些要做的事情以及潜在功能的想法
- 添加解析方法返回参数的处理程序,这样我们就可以在
craft.app.getSecurity().
等事物上获得自动完成 - 找出为什么建议详情子窗口看起来没有正确调整大小以适应
文档
。它在那里,但你必须调整窗口大小才能看到它,并且似乎某些地方计算错误 - 更智能的Twig表达式检测
- 只有当它们在Twig表达式中时,才应该添加
TwigExpressionAutocomplete
的悬停效果 - 如果
SectionShorthandFieldsAutocomplete
的完成项也能提供子项完成项,那就更好了
由 nystudio107 提供