# Cloud Studio 云部署插件

## 开发流程

1、 安装依赖

```
yarn
```

2、 安装 Malagu CLI Runtimes 供插件内置使用

```
yarn install-runtimes
```

3、 React 项目构建生成 WebView 所需文件

```
yarn build-webview
```

**注：如需更新 Malagu CLI 需在`package.json`内配置版本后重新执行`步骤1`和`步骤2`，然后更新`/src/common/utils.ts`中引用的版本号**

4、 本地 VSCode 在 DEBUG 菜单内使用 `Run Extension` 或者将插件打包到 Cloud Studio 调试

```
vsce package
```

## 国际化

### 插件国际化

由于官方目前还未提供 Webpack 版国际化的解决方案，且较为复杂，故使用与其他项目一致的工具库 [vscode-nls-i18n](https://github.com/axetroy/vscode-nls-i18n)

**使用方法**

1. 新增语言： 新增对应语言的 json 配置，如中文简体：package.nls.zh-cn.json
2. 新增词条： 在所有的 nls 配置中新增条目
3. 代码引用：

```
import { localize } from 'vscode-nls-i18n';
// 对应nls配置中的key
localize('module.key')
```

### WebView 国际化

本项目中的 WebView 分为两种形式展示，一种直接按字符串方式引用，一种是通过构建 React 项目生成的文件引用。其中字符串方式使用同上 `插件国际化` ，React 构建的项目则通过 [react-intl](https://formatjs.io/docs/react-intl/) 进行国际化。

**使用方法**

1. 新增语言： 在 i18n 目录下新增对应语言的 ts 文件，如：en.ts
2. 新增词条： 在 i18n 目录下所有的 ts 文件中新增条目
3. 代码引用：

```
import { IntlProvider, FormattedMessage } from 'react-intl';

// 引入所有使用的语言配置
import zh from '../../i18n/zh';
import en from '../../i18n/en';

// 根据获取到的vscode.env.language来选定使用的配置
const handleI18nMessages = (lang: string) => {
	let res = {};
	switch (lang) {
		case 'zh-CN':
			res = zh;
			break;
		case 'zh-cn':
			res = zh;
			break;
		default:
			res = en
			break;
	}
	return res;
}

// language: 当前对应的react-intl可识别的语言， messages: 所应用的具体语言包
<IntlProvider locale={language} messages={handleI18nMessages(language)}>
...
</IntlProvider>

```

## 使用 React 构建 WebView

由于本项目中使用的 WebView 较复杂，故使用 React 进行项目构建再进行引用。React 项目涉及所有内容均位于`/web`目录。

> 由于 CRA 官方还没有正式发版支持 Webpack5，暂时未升级，待支持后再根据当前项目需求进行改造升级。

**插件引用不同入口的 js 和 css 文件**

按插件创建 WebView 的正常流程生成 html 内容，在对应标签内引入 js 和 css。

1、读取 `asset-manifest.json` 找到需引用的对应 js 和 css，如：

```
const manifest = __non_webpack_require__(path.join(this._context.extensionPath, 'web', 'build', 'asset-manifest.json'));
const mainScript = manifest.files['main.js'];
const mainStyle = manifest.files['main.css'];
```

2、 将 js 和 css 文件解析成 vscode 可识别的路径， 如：

```
const scriptPathOnDisk = vscode.Uri.file(path.join(this._context.extensionPath, 'web', 'build', mainScript));
		const scriptUri = scriptPathOnDisk.with({ scheme: 'vscode-resource' });
```

3、 在 head 中引入 css，在 body 中引入 js， 如：

```
<link rel="stylesheet" type="text/css" href="${styleUri}">
```

```
<script nonce="${nonce}" src="${scriptUri}"></script>
```

## 插件与 WebView 通信

本项目对插件与 WebView 通信使用了 sap-devx/webview-rpc，可较为方便地进行交互。
[@sap-devx/webview-rpc Github 文档](https://github.com/SAP/vscode-webview-rpc-lib)

1、 在 WebView 中

```
// 页面入口引入依赖库，并进行初始化
import { RpcBrowser } from '@sap-devx/webview-rpc/out.browser/rpc-browser';
import '@sap-devx/webview-rpc/out.browser/rpc-common';

const rpc = new RpcBrowser(window, vscode);

// 发消息给 vscode 插件（如需等待vscode回调值，则可使用 async/await 获取）
rpc.invoke('test',['a','b']);

// 注册指定方法来处理vscode发来的消息
rpc.registerMethod({ func: (value: string) => setLanguage(value), name: 'getLanguage' });

```

2、 在 vscode 中

```
// webview 组件入口引如依赖库，并进行初始化
import { RpcExtension } from '@sap-devx/webview-rpc/out.ext/rpc-extension';

const rpc = new RpcExtension(webviewView.webview);

// 发消息给 webview （如需等待webview回调值，则可使用 async/await 获取）
rpc.invoke('refresh', ['data']);
```
