nystudio107/craft-code-editor

提供具有 Twig & Craft API 自动完成的代码编辑器字段

资助包维护!
khalwat

安装次数: 444,464

依赖项: 17

建议者: 0

安全: 0

星星: 4

观察者: 4

分支: 5

开放性问题: 1

类型:yii2-extension

1.0.21 2024-09-13 02:32 UTC

README

Scrutinizer Code Quality Code Coverage Build Status Code Intelligence Status

Craft CMS 3.x, 4.x & 5.0 的代码编辑器

提供具有 Twig & Craft API 自动完成的代码编辑器字段

Demo

要求

Code Editor 需要 Craft CMS 3.x, 4.x 或 5.x。

安装

要安装 Code Editor,请按照以下步骤操作

  1. 打开您的终端并进入您的 Craft 项目

     cd /path/to/project
    
  2. 然后告诉 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 的完整自动完成,包括已安装的插件

Autocomplete

当您将鼠标悬停在表达式上时,它还会添加悬停文档

Hovers

您还可以添加自己的自定义自动完成,并自定义编辑器的行为。

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 是包含编辑器字段中应显示的初始文本的变量。这将创建 labelinstructions,以及 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 是一个变量,包含应出现在编辑器字段中的初始文本。这将创建 labelinstructions,以及仅限于单行的 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
}

附加选项

textareatextareaFieldtexttextFieldincludeJs 宏都接受三个可选参数

{{ 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 来指定代码编辑器使用的 languagetheme,但您也可以覆盖任何您喜欢的 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 - 布尔值 - 是否使编辑器表现得像单行文本字段。对于 texttextField Twig 宏,此选项设置为 true,而对于 textareatextareaField Twig 宏,设置为 false
  • placeholderText - 字符串 - 当代码编辑器字段为空时,应显示的占位符文本。
  • displayLanguageIcon - 布尔值 - 如果可用,是否应在代码编辑器的右上角显示语言图标。
  • fileName - 字符串 - 正在显示的文件名,用于让 Monaco 根据文件名后缀确定要使用的语言
  • fixedHeightEditor - 布尔值 - 通常,编辑器将动态调整大小以适应其内容。如果此选项设置为 true,则编辑器将具有由其父容器确定的固定高度(需要时带有滚动条)
  • maxEditorRows - 数字 - 在固定高度并添加滚动条之前,编辑器可以具有的最大行数。如果您想有无限行数且不带滚动条,请将其设置为 0。默认为 50

使用附加自动完成功能

代码编辑器仅在编辑器语言为 twig 时添加自动完成。原因有两个

  • 提供代码编辑器动力的基于 VScode 的 Monaco 编辑器对 Twig 的支持较差,因此代码编辑器为 Twig 语言提供了自动完成
  • Craft 通过 Craft API、过滤器、函数等形式,以动态方式向 Twig 语言添加了一系列功能,代码编辑器负责将这些功能提供给 Monaco 编辑器

其他语言有更强大的支持,并自带自动完成和语法高亮。

默认情况下,代码编辑器使用 CraftApiAutocompleteTwigLanguageAutocomplete,但它还包括一个可选的 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];
    }
);

请注意,上述所有示例都 添加 自动完成到代码编辑器默认提供的自动完成中(CraftApiAutocompleteTwigLanguageAutocomplete)。如果您想 完全替换 它们,请先清空 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 模板传递下来的任何数据。这允许您具有特定字段的上下文信息。

请参阅以下示例,您可以根据这些示例创建自定义自动完成

Twig 模板验证器

代码编辑器还包含两个 Twig 模板验证器,您可以使用它们来验证作为模型一部分保存的 Twig 模板

您只需将它们作为规则添加到模型中,它就会传播模型,并在渲染模板时遇到任何错误

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 提供