Plone的协作编辑
项目描述
介绍
jarn.xmpp.collaboration 定义了一种通过XMPP进行实时协作编辑的协议,并提供
了一个可覆盖的服务器组件的通用实现。
一个针对Plone的特定实现(服务器组件和javascript客户端)。
基本Plone内容类型(页面和新闻条目)的适配器。
它是旨在为Plone提供XMPP服务的软件包套件的一部分。其他两个包是
jarn.xmpp.twisted,为twisted提供XMPP特定的协议实现。
jarn.xmpp.core 提供了存在、消息传递、聊天和微博的功能。
需求
有关设置您的Plone站点和XMPP服务器的详细信息,请参阅 jarn.xmpp.core。如果您不使用包含在 jarn.xmpp.buildout 中的配方,则需要配置ejabberd以允许协作组件的连接。对于 ejabberd,这通过在您的配置文件中包含以下内容来完成
{{5347, {0,0,0,0} }, ejabberd_service, [ {access, all}, {shaper_rule, fast}, {ip, {127, 0, 0, 1}}, {hosts, ["collaboration.localhost"], [{password, "secret"}] } ]},
将运行xmpp组件的实例应包含 component.zcml。您可以在您的buildout中这样做
zcml-additional = <configure xmlns="http://namespaces.zope.org/zope"> <include package="jarn.xmpp.twisted" file="reactor.zcml" /> <include package="jarn.xmpp.collaboration" file="component.zcml" /> </configure>
最后,您需要在Plone控制面板中“激活”该产品。完成后,请编辑注册设置,特别是
jarn.xmpp.collaborationJID 是协作编辑服务组件的Jabber ID。本质上,如果 myserver 是您的XMPP域名,则 collaboration.myserver 是一个不错的名称。这应该与上面提到的ejabberd的名称相匹配。默认值为 collaboration.localhost。
jarn.xmpp.collaborationPassword 是组件将用于连接到您的XMPP服务器的密码,见上面。默认值为 secret。
jarn.xmpp.collaborationPort 是允许组件连接到您的 XMPP 服务器的端口,请参见上文。默认值为 5347。
用法
一旦您完成了设置,使用 jarn.xmpp.collaboration 就很简单了。在协同编辑内容时,无需使用特殊视图。如果您的内容存在对 ICollaborativelyEditable 的适配器,则访问其编辑表单将允许多个用户同时编辑。
默认情况下,存在针对架构以及基于 dexterity 的内容类型的适配器。对于 AT 内容类型,实现 IStringField 或 ITextField 的字段将自动获得协同编辑支持。对于 Dexterity,将自动包含提供 ITextLine、IText 或 IRichText 的字段,无论它们是通过哪种 行为 定义的。请注意,JavaScript 客户端假定使用了 TinyMCE。在富文本字段上的协作将无法与 Kupu 一起工作。
协议规范。
初始化
为了开始一个协同编辑会话,一方向服务器组件发送一个表示在哪个节点上工作的 presence 消息。该方必须在 query 元素中指定 node 属性。
<presence from='foo@example.com/work' to='collaboration.example.com'> <query xmlns='http://jarn.com/ns/collaborative-editing' node='collab-node'/> </presence>
收到消息后,会向可能正在编辑同一节点的任何人发送一个 message 消息,通知他们新参与者的情况。
<message from='collaboration.example.com' to='bar@example.com/home'> <x xmlns='http://jarn.com/ns/collaborative-editing'> <item action='user-joined' node='collab-node' user='foo@example.com/work'/> </x> </message>
新加入的用户也会收到有关现有用户的类似通知。
<message from='collaboration.example.com' to='foo@example.com/home'> <x xmlns='http://jarn.com/ns/collaborative-editing'> <item action='user-joined' node='collab-node' user='bar@example.com/work'/> </x> </message>
为了完成初始化,新方必须从服务器请求节点的当前版本。
<iq id='123' from='foo@example.com/work' to='collaboration.example.com' type='get'> <shadowcopy xmlns='http://jarn.com/ns/collaborative-editing' node='collab-node'/> </iq>
服务器将回复,提供其当前文本副本。
<iq id='123' from='collaboration.example.com' to='foo@example.com/work' type='result'> <shadowcopy xmlns='http://jarn.com/ns/collaborative-editing' node='collab-node'>Hello world</shadowcopy> </iq>
如果节点不存在,或者用户没有访问权限的权限,服务器必须以错误回复,例如。
<iq id='123' from='collaboration.example.com' to='foo@example.com/work' type='error'> <error xmlns='http://jarn.com/ns/collaborative-editing'>Unauthorized</error> </iq>
编辑周期
当一方编辑文本时,它通过发送一个类型为 set 的 iq 消息通知服务器。消息包含一个 patch 元素,该元素必须指定要应用到的 node,并在其正文中包含由 Diff-Match-Patch 算法创建的补丁文本格式。例如,如果文本从“Hello world”更改为“Hello world, have a nice day!”,则消息将是:
<iq id='234' from='foo@example.com/work' to='collaboration.example.com' type='set'> <patch xmlns='http://jarn.com/ns/collaborative-editing' node='collab-node' digest='b9e8241b3cc82c43af870641078ee03f'> @@ -4,8 +4,26 @@\n lo world\n+, have a nice day!\n </patch> </iq>
如果服务器成功将补丁应用到其影子副本,则回复一个 成功 结果。
<iq id='234' from='collaboration.example.com' to='foo@example.com/work' type='result'> <success xmlns='http://jarn.com/ns/collaborative-editing'/> </iq>
此外,服务器必须将补丁广播到所有在节点上存在的一方。
<iq id='345' from='collaboration.example.com' to='bar@example.com/home' type='set'> <patch xmlns='http://jarn.com/ns/collaborative-editing' node='collab-node'> @@ -4,8 +4,26 @@\n lo world\n+, have a nice day!\n </patch> </iq>
各方必须将其应用到他们的文本上。如果应用补丁失败,服务器(或客户端)必须回复一个类型为 错误 的 iq 消息。例如,如果发送到服务器的补丁由于某种原因无法应用到影子副本,则服务器会回复:
<iq id='234' from='collaboration.example.com' to='foo@example.com/work' type='error'> <error xmlns='http://jarn.com/ns/collaborative-editing'> Patch @@ -4,8 +4,26 @@\n lo world\n+, have a nice day!\n could not be applied. </error> </iq>
在这种情况下,客户端应该通过发送一个类型为 get 的 iq 消息重新同步当前副本,请求影子副本,请参阅上面的“初始化”部分。
最后,patch 元素可以有 digest 属性。在这种情况下,服务器应该检查校验和,如果存在不匹配,则根据情况以错误消息回复。请注意,当前校验和算法没有协商,并且假定是 MD5 十六进制摘要。
聚焦
在同时编辑多个节点(例如,在内容有多个协同可编辑字段的环境中)的环境中,客户端可以发送一个通知,指定当前正在编辑的特定节点。
<message from='foo@example.com/work' to='collaboration.example.com'> <x xmlns='http://jarn.com/ns/collaborative-editing'> <item node='collab-node' action='focus' user='foo@example.com/work'/> </x> </message>
服务器必须将消息传播到所有当前正在节点上协作的其他用户。
<message from='collaboration.example.com' to='bar@example.com/home'> <x xmlns='http://jarn.com/ns/collaborative-editing'> <item node='collab-node' action='focus' user='foo@example.com/work'/> </x> </message>
保存
在任何时候,任何一方都可以请求保存。这通过发送一个消息来完成,该消息的 item 必须指示节点,并且其动作必须设置为 save
<message from='foo@example.com/work' to='collaboration.example.com'> <x xmlns='http://jarn.com/ns/collaborative-editing'> <item node='collab-node' action='save'></item> </x> </message>
服务器组件负责执行保存时的任何安全考虑。
终止
当一方发送一个 unavailable 存在时,会话终止。
<presence from='foo@example.com/work' type='unavailable' />
收到后,服务器会通知任何可能仍在编辑该节点的任何一方。
<message from='collaboration.example.com' to='bar@example.com/home'> <x xmlns='http://jarn.com/ns/collaborative-editing'> <item action='user-left' node='collab-node' user='foo@example.com/work'/> </x> </message>
致谢
大部分工作都是利用 Jarn AS 员工可用的10%时间用于开源项目开发完成的。
David Glick (davisagli) 为 dexterity 支持和总体上的出色表现。
jarn.xmpp.collaboration 依赖于 Google 的 Neil Fraser 提供的奇妙工具 Diff-Match-Patch。它根据 Apache License 2.0 分发。
变更日志
0.1b3 - 2011-11-26
修复了检查和错误,防止在发生错误时应用阴影文本。[ggozad]
0.1b2 - 2011-10-01
在每次补丁上执行校验和检查。处理由于网络延迟引起的潜在错误。[ggozad]
使用 TinyMCE 的原始文本而不是处理后的文本。提高了可靠性。[ggozad]
0.1b1 - 2011-09-18
主要协议更新。不再发送消息片段,现在使用 iq 片段。这使得在特定边缘情况下检查错误和同步成为可能。这也使协议更符合 XMPP 惯例。[ggozad]
重新组织和清理了 js 代码。客户端协议实现现在与 plone 特定部分分离,允许代码重用并提高可读性。[ggozad]
当其他用户加入/离开节点时通知用户。[ggozad]
0.1a4 - 2011-09-07
更新文档。[ggozad]
修复用户离开协作编辑时出现的 js 错误。[ggozad]
0.1a3 - 2011-09-01
简化配置并修复了注册表中的混淆性错别字[ggozad]
0.1a2 - 2011-06-06
在 p.a.registry 中配置组件/服务器密码和连接端口。[ggozad]
支持 Dexterity 内容类型。[davisagli, ggozad]
泛化 ATContentTypes 支持。[ggozad]
当用户更新节点时提供视觉反馈。[ggozad]
JS 清理。[ggozad]
测试覆盖率。[ggozad]
0.1a1 2011-05-09
初始发布 [ggozad]