gerrit 使用 JS 插件

gerrit JS 插件

Gerrit Code Review 支持用于 JavaScript 插件的 API,以与 Web UI 和服务器进程进行交互。

Plugin loading and initialization

JavaScript 是使用标准的 ``` <script src='??'> ``` HTML 标签加载的。 
插件应该通过 传递给 Gerrit.install() 的匿名函数中定义它们的代码来保护全局命名空间。 
该插件将被传递一个描述其在 Gerrit 注册的对象。

该插件 pluginname.js,可以是独立文件,也可以是jar 中的静态资产作为Web UI 插件。
pluginname.js 包含对 Gerrit.install() 的调用。 每个文件应该只有一个 Gerrit.install() 调用。
Gerrit Web 应用程序导入 pluginname.js。
对于独立插件,入口点文件是位于 gerrit-site/plugins 文件夹中的 pluginname.js 文件,其中 pluginname 是一个字母数字插件名称。 

Here’s a recommended starter myplugin.js:

1
2
3
4
Gerrit.install(plugin => {
// Your code here.
});

您可以在源代码树的 polygerrit-ui/app/samples/ 目录中找到更详细的示例。

Low-level DOM API concepts

基本上,DOM 是 API surface。 低级 API 提供了decorating、replacing和styling 通过一组端点公开的 DOM 元素的方法。
Gerrit 提供了一种通过 DOM  hooks API 访问 DOM 的简单方法。 DOM  hooks 是为插件端点实例化的自定义元素。 
在装饰案例中,使用指向 DOM 元素的内容属性设置了一个钩子。 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Get the DOM hook API instance via plugin.hook(endpointName)
Set up an onAttached callback
Callback is called when the hook element is created and inserted into DOM
Use element.content to get UI element



Gerrit.install(plugin => {
const domHook = plugin.hook('reply-text');
domHook.onAttached(element => {
if (!element.content) { return; }
// element.content is a reply dialog text area.
});
});




  1. Decorating DOM Elements

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    For each endpoint, Gerrit provides a list of DOM properties (such as attributes and events) that are supported in the long-term.


    Gerrit.install(plugin => {
    const domHook = plugin.hook('reply-text');
    domHook.onAttached(element => {
    if (!element.content) { return; }
    element.content.style.border = '1px red dashed';
    });
    });


  2. Replacing DOM Elements

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    An endpoint’s contents can be replaced by passing the replace attribute as an option.

    Gerrit.install(plugin => {
    const domHook = plugin.hook('header-title', {replace: true});
    domHook.onAttached(element => {
    element.appendChild(document.createElement('my-site-header'));
    });
    });


  3. Styling DOM Elements

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Gerrit only offers customized CSS styling by setting custom_properties (aka css variables).
    See app-theme.ts for the list of available variables.
    Just add code like this to your JavaScript plugin:


    const styleEl = document.createElement('style');
    styleEl.innerHTML = `
    html {
    --header-background-color: #c3d9ff;
    }
    html.darkTheme {
    --header-background-color: #c3d9ff90;
    }
    `;
    document.head.appendChild(styleEl);

High-level DOM API concepts

High level API is based on low-level DOM API and is essentially a standardized way for doing common tasks. It’s less flexible, but will be a bit more stable.
The common way to access high-level API is through plugin instance passed into setup callback parameter of Gerrit.install(), also sometimes referred to as self.
高级 API 基于低级 DOM API,本质上是执行常见任务的标准化方式。 它不太灵活,但会更稳定一些。
访问高级 API 的常用方法是通过将插件实例传递给 Gerrit.install() 的 setup 回调参数,有时也称为 self。 

Low-level DOM API

The low-level DOM API methods are the base of all UI customization.
低级 DOM API 方法是所有 UI 定制的基础。 
  1. attributeHelper
    1
    2
    plugin.attributeHelper(element)

    Alternative for Polymer data for plugins that don’t use Polymer. Can be used to bind element attribute changes to callbacks.

See samples/bind-parameters.js for an example.

  1. hook

    1
    2
    3

    plugin.hook(endpointName, opt_options)

    See endpoints. https://gerrit-review.googlesource.com/Documentation/pg-plugin-endpoints.html

  2. registerCustomComponent

    1
    2
    3

    plugin.registerCustomComponent(endpointName, opt_moduleName, opt_options)

    See endpoints. https://gerrit-review.googlesource.com/Documentation/pg-plugin-endpoints.html

  3. registerDynamicCustomComponent

    1
    2
    3

    plugin.registerDynamicCustomComponent(dynamicEndpointName, opt_moduleName, opt_options)

    See endpoints. https://gerrit-review.googlesource.com/Documentation/pg-plugin-endpoints.html

  4. registerStyleModule (deprecated )

    1
    plugin.registerStyleModule(endpointName, moduleName)

    This API is deprecated and will be removed either in version 3.6 or 3.7, see above https://gerrit-review.googlesource.com/Documentation/pg-plugin-dev.html#low-level-style for an alternative

  5. on

Register a JavaScript callback to be invoked when events occur within the web interface. Signature

1
self.on(event, callback);

Parameters

event: A supported event type. See below for description.
callback: JavaScript function to be invoked when event happens. Arguments may be passed to this function, depending on the event.

Supported events:

history: Invoked when the view is changed to a new screen within the Gerrit web application. The token after "#" is passed as the argument to the callback function, for example "/c/42/" while showing change 42.
showchange: Invoked when a change is made visible. A ChangeInfo and RevisionInfo are passed as arguments. Gerrit provides a third parameter which is an object with a mergeable boolean.
submitchange: Invoked when the submit button is clicked on a change. A ChangeInfo and RevisionInfo are passed as arguments. Similar to a form submit validation, the function must return true to allow the operation to continue, or false to prevent it. The function may be called multiple times, for example, if submitting a change shows a confirmation dialog, this event may be called to validate that the check whether dialog can be shown, and called again when the submit is confirmed to check whether the actual submission action can proceed.
comment: Invoked when a DOM element that represents a comment is created. This DOM element is passed as argument. This DOM element contains nested elements that Gerrit uses to format the comment. The DOM structure may differ between comment types such as inline comments, file-level comments and summary comments, and it may change with new Gerrit versions.
highlightjs-loaded: Invoked when the highlight.js library has finished loading. The global hljs object (also now accessible via window.hljs) is passed as an argument to the callback function. This event can be used to register a new language highlighter with the highlight.js library before syntax highlighting begins.

High-level API

Plugin instance provides access to a number of more specific APIs and methods to be used by plugin authors.

例子

主题设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

// gerrit https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/app/samples/theme-plugin.js
// https://gerrit-review.googlesource.com/Documentation/pg-plugin-dev.html
// https://groups.google.com/g/repo-discuss/c/tgvmGhfFcgU
// https://stackoverflow.com/questions/19307964/customize-gerrit-home-pagelogo-and-color



Gerrit.install(plugin => {
const styleElement = document.createElement('dom-module');
styleElement.innerHTML = `
<template>
<style>
html {
--header-background-color: #D4E9A9;
--header-text-color: #000;
--header-title-content: "马哥私房菜 Gerrit";
--header-icon: url("/static/logo.png");
--header-icon-size: 1em;
--primary-text-color: #000;
--dropdown-background-color: #D4E9A9;
}
</style>
</template>`;
styleElement.register('site-theme');
plugin.registerStyleModule('app-theme', 'site-theme');
}); // end Gerrit.install(plugin => {



自定义横幅文字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40


Gerrit.install(plugin => {
const domHook = plugin.hook('banner', {replace: true});
domHook.onAttached(element => {
const banner = document.createElement('div');
banner.innerHTML = `

<div>
<style>
.bs-banner {
background-color: #D4E9A9;
color: #000000;
text-align: left;
padding: 5px;
}
.bs-banner .close {
float: right;
font-size: 12px;
margin: 3px 8px 0px 0px;
cursor: pointer;
}

</style>

<div class="bs-banner" id="bs-banner-message">
<span class="close" title="close" onclick="this.parentElement.style.display = 'none'"> 关闭 </span>
<span class="inner">
这里写上 横幅 展示的 文字!!!!!!!!!!!马哥私房菜 Gerrit
</span>
</div>
</div>
`;

element.appendChild(banner);

}); //end domHook.onAttached(element => {

}); // end Gerrit.install(plugin => {

解释:

  1. 主要这里 plugin.hook(‘banner’, 这里的 banner 是 gerrit 上 定义好的。,通过页面 右键 检查 可以看到 这个标签
  2. 其他的 类似 也是找 gr-endpoint-decorator 这样的标签。例如现例子的 footer。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
// gerrit https://gerrit.googlesource.com/gerrit/+/master/polygerrit-ui/app/samples/theme-plugin.js
// https://gerrit-review.googlesource.com/Documentation/pg-plugin-dev.html
// https://groups.google.com/g/repo-discuss/c/tgvmGhfFcgU
// https://stackoverflow.com/questions/19307964/customize-gerrit-home-pagelogo-and-color


Gerrit.install(plugin => {
const domHook = plugin.hook('footer-up', {replace: true});
domHook.onAttached(element => {
const banner = document.createElement('div');
banner.innerHTML = `


<div>
<style>
a {
color: #0060B6;
text-decoration: none;
}

a:hover {
color:#00A0C6;
text-decoration:none;
cursor:pointer;
}

.bs-footer{
display: flex;
justify-content: space-between;
padding: var(--spacing-m) var(--spacing-l);
}

</style>

<div class="bs-footer" id="bs-banner-message">

<div>
这里写上 footer 展示的 内容。这个 footer up 是我 自己 加的一个,位于 main 现,真正的 footer 上面一点。
</div>

</div>
</div>



`;

element.appendChild(banner);

}); //end domHook.onAttached(element => {

}); // end Gerrit.install(plugin => {





1
2


1
2