当前位置: 首页 > 网络应用技术

[翻译] CodeMirror系统指南

时间:2023-03-08 00:19:25 网络应用技术

  原来的

  本文是CodeMirror编辑系统的准则。

  因为CodeMirRorrororo中常用的经典JS库是不同的,所以建议首先阅读本章,否则可能会觉得它不符合您的期望和浪费时间

  模块化codemirror是一系列独立的模块组合,可提供提供丰富文本编辑功能和代码编辑功能的编辑器。好的一面是您可以选择所需的特征,甚至可以按需替换核心功能。不良方面是该系列需要集成在一起以配置CodeMirror。

  集成代码并不难,但需要立即进行,然后根据需要导入。下面的核心库是必要的。没有它们,它们不会配置为CodeMirror。

  以下是最基本的codemirror配置

  编辑器中的其他操作(例如线数分隔,历史记录的撤回等)是通过扩展实现的。您需要清楚地将其添加到以配置中打开。为了促进使用,该库配置了可以在编辑器中使用的大多数功能,并且可以使用它来使用它(语言支持除外)

  Codemirror的袋子以ES6模块的形式分发。因此,它目前直接运行而不支持Packager或Module Loader。如果您是新手,我建议尝试或尝试尝试或

  功能核心,指导CodeMirror体系结构的命令的核心点是功能代码(纯函数),它将创建一个没有副作用的新值,这更方便地与命令代码进行交互。浏览器DOM显然也是命令-Type思维,类似于CodeMirror集成的大多数系统。

  为了解决这一矛盾,库的语句层是严格的功能性的,即文档和状态数据结构是不可变的,可以操作它们的人是纯函数,并且视图组件和命令接口将它们封装在一个命令界面的类型。

  这意味着,即使编辑已被转移到新州,旧国家仍然存在。保留旧州和新州对应对国家变化非常有益。这也意味着状态值直接更改状态值,或编写命令扩展名,例如添加附加状态属性,将面临未知的情况,甚至会造成损坏。

  在处理这种情况时,Typescript非常有利,只需将阵列或对象属性标记为ReadOnly。使用纯JS代码时,没有任何保证。除非文档明确指出,在正常情况下,它不受重新分配属性的支持。由图书馆创建,如下:

  状态和更新CODEMIRROR处理状态更新受到或受到启发。除了很少的情况(例如组合和阻力处理)之外,视图状态由EditorSstate中的状态属性确定。

  通过创建文档,选择或其他状态属性的描述的交易,通过此函数调用更新状态。可以通过调度分配此交易,并告诉视图以更新状态,并更新与新的DOM显示状态。

  典型的用户交互数据流如下所示

  查看监视事件发生更改。发生DOM事件(或由快捷键触发的命令,或通过扩展的注册事件处理器触发的命令),CodeMirror会将这些事件转换为新状态转换,然后分发。新状态,并在收到新状态后返回以更新DOM。

  由于需要最小化核心库,并且以系统扩展的形式将扩展名最小化并基于模型,因为核心库可以做任何事情。扩展可以做任何事情,从配置选项到定义状态的新属性,请修改,编辑器样式,并将命令组件注入视图。CODEMIRROR系统可确保组合扩展无冲突。

  激活的扩展名存储在编辑状态(可以通过转移更新)。扩展通常以从包装或数组的形式导入的形式存在。),在配置阶段将自动重。因此,一个扩展可以包含另一个扩展名 - 如果一个扩展名加载多次,则只能生效一次。

  如果相关多个扩展,则必须明确说明其优先级,也就是说,根据它们的扩展布置(pingping)的排列

  上面的代码最终将打印C。由于该代码处于代码的末尾,但其优先级确实是最高的。如果未指定优先级,则输出A最终将输出,因为他的订单是最高级的。

  以下章节将详细介绍扩展的实施和使用

  CodeMirror使用纯数字标记文档中的位置。这些数字代表字符精确的字符数量是UTF16码(因此,恒星角色被视为2码)。银行的变化始终被视为一码(即使您积极设置皇家角色,也是1码))

  这些偏移用于跟踪选择,更新位置,装饰内容等。

  有时,重要的是要找出要更新的文档的内容。可以给出。

  文档的数据结构也可以根据该行传输,因此该行的查询也是非常轻的操作操作

  作为文本编辑器,Codemirror当然被视为平面字符串。它存储在树状的数据结构中,以便可以在文档的任何地方廉价地更新(您可以通过行号有效地找到它)

  文档更新,即准确描述旧文档范围的过程被新文本替换。它允许扩展扩展精确的最终文档,并允许撤回历史记录和协作编辑器等功能在核心库之外实现。

  创建更新集合时,所有更新均相对于最原始的旧文档,从理论上讲它们是同时执行的。(如果您确实需要在更新集合中,则根据最后一个更新相对于最初的文档,最初的文档时间的最后更新,当您进行更新时,您可以使用Compose功能更新收集的集合)

  除了保留文档属性外,选择编辑器状态还保留了当前的选择属性。选定属性可能包含多个范围,每个范围可能是光标或锚固范围或范围由锚和头描述。重叠范围将自动合并,并且范围will Will Will Will被排序。在这一点

  该范围之一将被视为主要范围。这是与浏览器DOM选择相对应的一个范围。其余的精确绘制和处理。

  默认情况下,状态仅接受由范围组成的选择。仅通过扩展(例如DrawSelection)我们才能启用多个选择并访问它们。

  状态对象有一种更改的方式来更改串联,可以操作每个选择(如果手动执行可能难以执行)

  每个编辑器状态的配置都有对其配置的私有属性引用,该属性由当前状态激活确定。如果是常规事务,则配置是相同的。或添加当前配置。

  状态配置直接影响其存储的属性,并与facets关联。

  facet facet是一个扩展。不同的扩展可以为facet提供不同的值。法定可以读取访问后生成的合并值。通过facet,您可以获得所提供的数据集或其计算的值。

  Facet背后的理念是,大多数类型的扩展允许多个输入,然后可以通过输入来计算某些值。这些组合可能有些不同。

  需要清楚地定义方面以生成一个方面的值。可以将此值导出其他代码以进行重新出现,阅读和写作,甚至模块的私有化,也就是说,只有该模块才能访问它。稍后扩展部分将详细介绍它。

  在给定的配置中,大多数方面倾向于作为配置的一部分是静态的。当然,您还可以从其他状态层面计算出图的价值。

  仅需在必要时重新计算Facets值,因此对象或数组可以使用它来测试该方面是否已更改。

  交易交易从该州的更新方法中很常见,结合了以下(所有可选)效果。

  为了完全重置一个像加载新的文档否决以创建新状态而不是使用转移的状态一样。这可以确保没有未知的状态干扰(例如撤回历史事件等)。

  查看视图尽可能尽可能地透明。

  CodeMirror不希望用户代码操作其管理的DOM结构。如果您执行此操作,那么您会看到CodeMirror立即恢复您的更新。查看装饰章节以了解如何正确修改显示的内容。

  视口需要注意的一件事是,当文档很大时,CodeMirror不会呈现整个文档。为了避免其他做工,CodeMirror将检测到当前显示的内容(没有窗口),只有此部分及其边缘。这是视口

  当前视口中未出现的位置坐标是无效的(因为尚未呈现它们)。视图没有跟踪整个文档的高信息(可能在初始化时估计,在渲染内容时准确测量了内容),即使这部分不再是视口。

  长线(无折叠)或折叠代码仍然会使视口庞大。编辑器还提供一系列可见范围,这些范围不包括这些不可见的内容。处理隐形内容。

  更新codemirror视图将最大程度地减少导致其引起的dom重新启动。进行转换通常只会导致编辑器在不阅读布局信息的情况下呈现DOM。阅读布局操作(检查视口是否有效,指针是否需要滑到视图等)将在另一个单独的测量阶段完成,并使用时间表。该周期将在必要时进行另一个写作周期。

  您可以使用自己的测量代码。

  为了避免怪异的重新输入场景,同时执行一个更新并初始化了另一个新更新时,视图将引发错误。当测量周期仍在排队排队时,测量周期仍在更新时,因为测量周期是测量周期Codemirror的of将自动合并。

  观点完成后,您可以调用其设计方法来丢弃它

  DOM结构编辑器的DOM结构看起来像这样

  最外面的元素是垂直弹性箱。它可以像扩展的面板和工具提示一样放置在这里。

  在此期间,滚动器元素。如果编辑器具有自己的滚动条,则该元素的样式应该是。但实际上,没有必要执行此操作,因为编辑器支持根据内容自动适应高度,或者增加滑动时最大高值。

  滚动器是水平弹性箱元素。如果有一个插槽,它将放置在起点。

  滚动器内部是内容元素,他是可编辑的。它注册了DOM .CONTENT上突变观察者的任何更改,这将使编辑者将其分析为文档更新,然后重新绘制受影响的节点。此处。该容器为视口中的每条线生成一个线元素。它是其中的文本,可以通过样式或组件进行装饰。

  为了管理与编辑相关的样式,设计师和主题使用JS注入样式系统实现。该样式可以通过Facet注册,并且可以确保视图肯定会显示它们。

  许多编辑中的元素的分类是CM-。这些可以在您的本地CSS中覆盖。它也可以由主题配置。一个主题是由editorview.theme创建的扩展名。它具有它。当主题扩展被激活时,您可以添加到编辑器)。您可以通过此类名称来定义样式的样式范围。

  主题语句使用样式模式语句来定义任何数字的CSS规则。编辑器使用CM开头的类名来创建一个将默认文本颜色修改为Orage的主题。

  为了确保自动完成类别前缀自动完成,第一个元素指向编辑器包装元素的规则(即添加主题本身的位置),例如以.cm为中心的。从编辑器的封装元素出发。

  扩展可以为他们创建的元素定义基本主题,以提供默认样式。基本样式可以使用&Light(默认)和&Dark(仅在深色主题下激活)。它看起来并不突然

  命令命令是特殊签名的函数。它们主要用于绑定快捷键,但实际上,它们也可以在菜单条目或命令磁盘等场景中使用。命令函数代表用户操作。接收视图,返回布尔值,返回布尔值,返回布尔值,返回布尔值。False表示当前场景不适用。true表示可以执行当前场景。该命令是生成命令公式,通常是分发转换。

  当多个命令绑定到同一快捷键时,只有返回true的命令将被执行。

  该命令只能影响状态,而不能影响整个视图。您可以改用statecommand类型。它是命令的子类型,但其参数必须具有状态和调度属性。它通常可以在没有视图的情况下测试命令。

  有很多方法可以扩展codemirror。哪一个最合适的不容易选择。以下章节将引入这些解决方案,以参考扩展。

  状态领域的扩展通常需要在状态中保存其他信息。覆盖历史记录需要通过撤回,代码折叠扩展来保存,需要跟踪哪种行,依此类推。

  扩展可以通过自定义其他状态属性来满足这些需求。状态属性是状态数据结构中纯函数的形式,并且存储必须不可用。

  状态属性与还原形式的状态状态是一致的。每个属性更新,此属性和事务将函数称为参数,然后返回另一个新的属性值。

  评论或效果通常可用于观察状态属性。

  似乎您可以将状态分配给状态属性,但是当交易触发更新时,会有一些冗余(不要执行此操作)。将您的状态绑定到编辑您的canin是国家更新周期的扩展是有用的,保持同步是非常简单的事情。

  影响视图插头 - 提供了一个想法来扩展视图中运行命令-Type组件的想法。例如,事件处理,添加管理DOM元素或取决于当前视口的操作是有用的。

  下面的插头 - 仅显示编辑器角落的文档大小

  视图插头最好不保存状态(自身生成)。它应用作编辑状态保存的数据的浅视图。

  配置状态后,不属于新配置的视图插头将被破坏(也就是说,如果他们更新编辑器,则这些操作将在其销毁方法中删除)

  当视图插头崩溃时,它会自动禁用以防止整个尝试。

  如果装饰文档不是特别的陈述,则CodeMirror通常使用文档作为普通文本。任务是一种可能影响文档形式的机制。通常有四个类别

  装饰以两种方式存在。一个是国家方面,可以在编辑州级别提供装饰,通常以状态属性的形式运行。不允许装饰视口(因为州不知道视口),所以更好成为折叠区域或棉绒提示。

  第二个是视图插头-in。它用于制作语法或搜索诸如亮点之类的亮点,因为视图插头可以读取当前视口,以避免看不见的内容。

  装饰是无法在集合中存在的可变数据集。在使用情况下,您可以跨越映射(调整内容位置以弥补更新的内容)或在更新过程中进行重建。

  为了创建可用的编辑器,通常需要扩展架构:状态属性保存状态,基本主题提供样式,视图插件 - 管理输入输出,命令/刻痕处理配置等。

  常见的扩展模式正在导出一个可以返回所需功能的扩展值。即使没有参数,此功能也是可能的 - IT使延迟添加配置选项而不会重新兼容。

  因为可以将扩展名引入其他扩展名中,因此您需要在引入扩展时需要考虑它。对于某些扩展,例如Keymap,多个进口是合理的。但是在其他情况下,多余的浪费和问题。

  它通常取决于重复扩展值以处理多个介绍的方法 - 如果您确定仅创建一次的静态扩展值(主题,状态属性,查看插件等),并且始终创建了扩展结构功能返回相同的对象,扩展结构函数始终返回相同的对象,并且扩展构造函数始终返回相同的对象。然后,您只会在编辑器中获取其副本。

  但是,当您的扩展允许配置时,其他逻辑可能需要访问它。当不同的扩展实例具有不同的配置时,您该怎么办?

  有时这只是一个错误,但是通常,可以定义协调它们的策略。FACET对此有效。然后,您需要访问当前的配置代码以读取此方面。

  查看斑马条纹的示例示例以详细介绍此问题。

  原始:https://juejin.cn/post/7099757578393141262