style: add assist_tools_vs_plugin and adapt to modify other revant plugins
Signed-off-by: zhaojunxia <zhaojunxia@kaihong.com>
@ -24,6 +24,10 @@ const path = require('path');
|
||||
var exeFilePath = null;
|
||||
const dirCache={};
|
||||
var globalPanel = null;
|
||||
|
||||
var importToolChain = false;
|
||||
var extensionIds = [];
|
||||
var nextPluginId = null;
|
||||
// this method is called when your extension is activated
|
||||
// your extension is activated the very first time the command is executed
|
||||
|
||||
@ -33,7 +37,7 @@ var globalPanel = null;
|
||||
function activate(context) {
|
||||
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
||||
// This line of code will only be executed once when your extension is activated
|
||||
console.log('Congratulations, your extension "gnapi" is now active!');
|
||||
console.log('Congratulations, your extension "ApiScan" is now active!');
|
||||
let disposable = register(context, 'api_scan');
|
||||
let disposableMenu = register(context, 'api_scan_menu');
|
||||
context.subscriptions.push(disposable);
|
||||
@ -72,7 +76,7 @@ function exeFileExit() {
|
||||
}
|
||||
|
||||
function register(context, command) {
|
||||
let disposable = vscode.commands.registerCommand(command, function (uri) {
|
||||
let disposable = vscode.commands.registerCommand(command, function (uri, boolValue, items) {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
// Display a message box to the user
|
||||
globalPanel = vscode.window.createWebviewPanel(
|
||||
@ -84,7 +88,24 @@ function register(context, command) {
|
||||
retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset
|
||||
}
|
||||
);
|
||||
globalPanel.webview.html = getWebviewContent(context);
|
||||
|
||||
if (typeof(boolValue) == 'boolean' && Array.isArray(items)) {
|
||||
if (boolValue == true) {
|
||||
//遍历数组item,查看当前插件id是数组的第几个元素,并拿出下一个元素,并判断当前id是否是最后一个元素并做相应处理
|
||||
let myExtensionId = 'kaihong.ApiScan';
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (myExtensionId == items[i] && (i == items.length - 1)) {
|
||||
importToolChain = false;
|
||||
} else if (myExtensionId == items[i] && (i != items.length - 1)) {
|
||||
importToolChain = boolValue;
|
||||
nextPluginId = items[i + 1];
|
||||
}
|
||||
extensionIds.push(items[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
globalPanel.webview.html = getWebviewContent(context, importToolChain);
|
||||
let msg;
|
||||
globalPanel.webview.onDidReceiveMessage(message => {
|
||||
msg = message.msg;
|
||||
@ -92,19 +113,8 @@ function register(context, command) {
|
||||
globalPanel.dispose();
|
||||
}
|
||||
else if (msg == "api_scan") {
|
||||
let name = message.fileNames;
|
||||
let genDir = message.genDir;
|
||||
name = re.replaceAll(name, " ", "");
|
||||
if ("" == name) {
|
||||
vscode.window.showErrorMessage("Please enter the path!");
|
||||
return;
|
||||
}
|
||||
if (exeFileExit()) {
|
||||
executorApiscan(name, genDir);
|
||||
} else {
|
||||
vscode.window.showInformationMessage("Copy executable program to " + __dirname);
|
||||
}
|
||||
}else {
|
||||
checkReceiveMsg(message);
|
||||
} else {
|
||||
selectPath(globalPanel, message);
|
||||
}
|
||||
}, undefined, context.subscriptions);
|
||||
@ -119,6 +129,59 @@ function register(context, command) {
|
||||
return disposable;
|
||||
}
|
||||
|
||||
function checkReceiveMsg(message) {
|
||||
let name = message.fileNames;
|
||||
let genDir = message.genDir;
|
||||
let buttonName = message.buttonName;
|
||||
name = re.replaceAll(name, " ", "");
|
||||
if ("" == name) {
|
||||
vscode.window.showErrorMessage("Please enter the path!");
|
||||
return;
|
||||
}
|
||||
if (exeFileExit()) {
|
||||
executorApiscan(name, genDir);
|
||||
if (buttonName == 'Next') {
|
||||
startNextPlugin();
|
||||
}
|
||||
} else {
|
||||
vscode.window.showInformationMessage("Copy executable program to " + __dirname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件执行命令
|
||||
*/
|
||||
function nextPluginExeCommand(nextPluginId) {
|
||||
if (nextPluginId == "kaihong.ApiScan") {
|
||||
return 'api_scan';
|
||||
} else if (nextPluginId == "kaihong.gn-gen") {
|
||||
return 'generate_gn';
|
||||
} else if (nextPluginId == "kaihong.service-gen") {
|
||||
return 'generate_service';
|
||||
} else if (nextPluginId == "kaihong.ts-gen") {
|
||||
return 'generate_ts';
|
||||
} else if (nextPluginId == "kaihong.napi-gen") {
|
||||
return 'generate_napi';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行完毕后开启工具链中下一个插件
|
||||
*/
|
||||
function startNextPlugin() {
|
||||
const extension = vscode.extensions.getExtension(nextPluginId);
|
||||
if (extension) {
|
||||
let startNextPlugin = nextPluginExeCommand(nextPluginId);
|
||||
try {
|
||||
vscode.commands.executeCommand(startNextPlugin, '', importToolChain, extensionIds);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择本地目录/文件夹
|
||||
*/
|
||||
@ -149,10 +212,14 @@ function selectPath(panel, message) {
|
||||
// this method is called when your extension is deactivated
|
||||
function deactivate() { }
|
||||
|
||||
function getWebviewContent(context) {
|
||||
function getWebviewContent(context, importToolChain) {
|
||||
let data = readFile(__dirname + '/vs_plugin_view.html');
|
||||
data = getWebViewContent(context, '/vs_plugin_view.html');
|
||||
return data.toString();
|
||||
let content = data.toString();
|
||||
if (importToolChain) {
|
||||
content = content.replace('Ok', 'Next');
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
function getWebViewContent(context, templatePath) {
|
||||
|
@ -69,7 +69,7 @@
|
||||
"vsce": "^2.11.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "gitee",
|
||||
"url": "https://gitee.com/openharmony/napi_generator/tree/master/hdc/api"
|
||||
}
|
||||
"type": "gitee",
|
||||
"url": "https://gitee.com/openharmony/napi_generator/tree/master/hdc/api"
|
||||
}
|
||||
}
|
||||
|
@ -113,10 +113,12 @@
|
||||
function sendApiscanParamMsg() {
|
||||
var fileNames = document.getElementById("asFilePath").value;
|
||||
var genDir = document.getElementById("genASResultDir").value;
|
||||
var buttonName = document.getElementById("okButton").textContent;
|
||||
var result = {
|
||||
msg: "api_scan",
|
||||
fileNames: fileNames,
|
||||
genDir: genDir,
|
||||
buttonName: buttonName,
|
||||
}
|
||||
vscode.postMessage(result);
|
||||
}
|
||||
@ -186,7 +188,7 @@
|
||||
<div style="margin-top: 20px; text-align: left;">
|
||||
<button type="button" class="button" onclick="cancel()"
|
||||
style="background-color: #333333; border: 1px solid #333333; color: #fff;">Cancel</button>
|
||||
<button type="button" class="button" onclick="sendApiscanParamMsg()"
|
||||
<button id="okButton" type="button" class="button" onclick="sendApiscanParamMsg()"
|
||||
style="background-color: #4B97D9; border: 1px solid #4B97D9; color: #fff;">Ok</button>
|
||||
<a href="https://gitee.com/openharmony/napi_generator" target="_blank">
|
||||
<button type="button"
|
||||
|
26
hdc/assist/assist_tools_vs_plugin/package.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "assist_tools",
|
||||
"version": "1.0.0",
|
||||
"description": "This is the Kaihong assistance tools unified entrance for OpenHarmony OS developer.",
|
||||
"main": "./src/extension.js",
|
||||
"directories": {
|
||||
"doc": "docs"
|
||||
},
|
||||
"dependencies": {
|
||||
"mocha": "^9.2.1",
|
||||
"node-gyp": "^8.4.1",
|
||||
"stdio": "^2.1.1",
|
||||
"typescript": "^4.5.5"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"pkg": {
|
||||
"assets": [
|
||||
]
|
||||
}
|
||||
}
|
201
hdc/assist/assist_tools_vs_plugin/src/LICENSE
Normal file
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
244
hdc/assist/assist_tools_vs_plugin/src/extension.js
Normal file
@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// The module 'vscode' contains the VS Code extensibility API
|
||||
// Import the module and reference it with the alias vscode in your code below
|
||||
const vscode = require('vscode');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { readFile } = require('./util/VsPluginTool');
|
||||
|
||||
var extensionIds = [];
|
||||
var importCheck = false;
|
||||
|
||||
// This method is called when your extension is activated
|
||||
// Your extension is activated the very first time the command is executed
|
||||
|
||||
/**
|
||||
* @param {vscode.ExtensionContext} context
|
||||
*/
|
||||
function activate(context) {
|
||||
|
||||
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
||||
// This line of code will only be executed once when your extension is activated
|
||||
console.log('Congratulations, your extension "Kaihong Assist Tools" is now active!');
|
||||
|
||||
// The command has been defined in the package.json file
|
||||
// Now provide the implementation of the command with registerCommand
|
||||
// The commandId parameter must match the command field in package.json
|
||||
let disposable = vscode.commands.registerCommand('assist_tools', function () {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
|
||||
globalPanel = vscode.window.createWebviewPanel(
|
||||
'assist tools', // Identifies the type of WebView
|
||||
'Kaihong Assist Tools', // Title of the panel displayed to the user
|
||||
vscode.ViewColumn.Two, // Display the WebView panel in the form of new columns in the editor
|
||||
{
|
||||
enableScripts: true, // Enable or disable JS, default is Enable
|
||||
retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset
|
||||
}
|
||||
);
|
||||
globalPanel.webview.html = getWebviewContent(context);
|
||||
let msg;
|
||||
globalPanel.webview.onDidReceiveMessage(message => {
|
||||
msg = message.msg;
|
||||
if (msg == "cancel") {
|
||||
globalPanel.dispose();
|
||||
} else if (msg == "startApi") {
|
||||
const extensionId = 'kaihong.ApiScan';
|
||||
installStartExtension(extensionId);
|
||||
} else if (msg == "startGn") {
|
||||
const extensionId = 'kaihong.gn-gen';
|
||||
installStartExtension(extensionId);
|
||||
} else if (msg == "startService") {
|
||||
const extensionId = 'kaihong.service-gen';
|
||||
installStartExtension(extensionId);
|
||||
} else if (msg == "startTs") {
|
||||
const extensionId = 'kaihong.ts-gen';
|
||||
installStartExtension(extensionId);
|
||||
} else if (msg == "startNapi") {
|
||||
const extensionId = 'kaihong.napi-gen';
|
||||
installStartExtension(extensionId);
|
||||
} else if (msg == "param") {
|
||||
let isSelectToolChain = installExtensions(message);
|
||||
startExtensions(isSelectToolChain);
|
||||
}
|
||||
}, undefined, context.subscriptions);
|
||||
// Display a message box to the user
|
||||
vscode.window.showInformationMessage('Welcome to use Kaihong Assist Tools!');
|
||||
});
|
||||
|
||||
context.subscriptions.push(disposable);
|
||||
}
|
||||
|
||||
function installExtensions(message) {
|
||||
importCheck = message.importIsCheck;
|
||||
let checkApi = message.checkApi;
|
||||
let checkGn = message.checkGn;
|
||||
let checkService = message.checkService;
|
||||
let checkTs = message.checkTs;
|
||||
let checkNapi = message.checkNapi;
|
||||
if (importCheck) {
|
||||
if (extensionIds.length != 0) {
|
||||
extensionIds.length = 0;
|
||||
}
|
||||
if (checkApi == 'true') {
|
||||
extensionIds.push('kaihong.ApiScan')
|
||||
}
|
||||
if (checkGn == 'true') {
|
||||
extensionIds.push('kaihong.gn-gen')
|
||||
}
|
||||
if (checkService == 'true') {
|
||||
extensionIds.push('kaihong.service-gen')
|
||||
}
|
||||
if (checkTs == 'true') {
|
||||
extensionIds.push('kaihong.ts-gen')
|
||||
}
|
||||
if (checkNapi == 'true') {
|
||||
extensionIds.push('kaihong.napi-gen')
|
||||
}
|
||||
}
|
||||
startInstallExtensions(extensionIds).catch((error) => {
|
||||
console.error(error);
|
||||
});
|
||||
return importCheck;
|
||||
}
|
||||
|
||||
async function startInstallExtensions(extensionIds) {
|
||||
const promises = extensionIds.map(async (extensionId) => {
|
||||
const extension = vscode.extensions.getExtension(extensionId);
|
||||
if (!extension) {
|
||||
await vscode.commands.executeCommand('workbench.extensions.installExtension', extensionId);
|
||||
console.log(`扩展插件 ${extensionId} 下载完成`);
|
||||
} else {
|
||||
console.log(`扩展插件 ${extensionId} 已经下载`);
|
||||
}
|
||||
});
|
||||
await Promise.all(promises);
|
||||
console.log('所有扩展插件下载完成');
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行完毕后启动工具链中下一个插件
|
||||
*/
|
||||
function nextPluginExeCommand(nextPluginId) {
|
||||
if (nextPluginId == "kaihong.ApiScan") {
|
||||
return 'api_scan';
|
||||
} else if (nextPluginId == "kaihong.gn-gen") {
|
||||
return 'generate_gn';
|
||||
} else if (nextPluginId == "kaihong.service-gen") {
|
||||
return 'generate_service';
|
||||
} else if (nextPluginId == "kaihong.ts-gen") {
|
||||
return 'generate_ts';
|
||||
} else if (nextPluginId == "kaihong.napi-gen") {
|
||||
return 'generate_napi';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function startExtensions(isSelectToolChain) {
|
||||
//启动工具链,根据需求启用插件
|
||||
let extensionId0 = extensionIds[0];
|
||||
//将isSelectToolChain和extensionIds数组传入其他插件
|
||||
//启动第一个插件
|
||||
let nextStartPlugin = nextPluginExeCommand(extensionId0);
|
||||
try {
|
||||
vscode.commands.executeCommand(nextStartPlugin, '', isSelectToolChain, extensionIds);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
// 参数单位 毫秒
|
||||
function wait(ms) {
|
||||
return new Promise(resolve => setTimeout(() => resolve(), ms));
|
||||
};
|
||||
|
||||
async function installStartExtension(extensionId) {
|
||||
const extension = vscode.extensions.getExtension(extensionId);
|
||||
if (!extension) {
|
||||
try {
|
||||
// 下载插件
|
||||
vscode.window.showInformationMessage(`Extension ${extensionId} installing...`);
|
||||
setTimeout(() => {
|
||||
const active = vscode.window.activeInformationMessage;
|
||||
if (active && active.message === `Extension ${extensionId} installing...`) {
|
||||
active.dispose();
|
||||
}
|
||||
}, 8000);
|
||||
await vscode.commands.executeCommand('workbench.extensions.installExtension', extensionId);
|
||||
vscode.window.showInformationMessage(`Extension ${extensionId} installed successfully.`);
|
||||
vscode.window.showInformationMessage(`Extension ${extensionId} activating...`);
|
||||
console.log(`Extension ${extensionId} activating...`);
|
||||
await wait(1000); // 等待下载插件初始化
|
||||
const extensionDone = vscode.extensions.getExtension(extensionId);
|
||||
if (extensionDone && extensionDone.isActive) {
|
||||
vscode.window.showInformationMessage(`Extension ${extensionId} activated successfully.`);
|
||||
console.log(`Extension ${extensionId} activated successfully.`);
|
||||
} else {
|
||||
console.log('请等待插件初始化完成')
|
||||
await wait(1000);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`Failed to install extension ${extensionId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 启动扩展
|
||||
if (extensionId == "kaihong.ApiScan") {
|
||||
vscode.commands.executeCommand('api_scan', '', false, '');
|
||||
} else if (extensionId == "kaihong.gn-gen") {
|
||||
vscode.commands.executeCommand('generate_gn', '', false, '');
|
||||
} else if (extensionId == "kaihong.service-gen") {
|
||||
vscode.commands.executeCommand('generate_service', '', false, '');
|
||||
} else if (extensionId == "kaihong.ts-gen") {
|
||||
vscode.commands.executeCommand('generate_ts', '', false, '');
|
||||
} else if (extensionId == "kaihong.napi-gen") {
|
||||
vscode.commands.executeCommand('generate_napi', '', false, '');
|
||||
}
|
||||
else {
|
||||
console.error('the toolChain does not include this extension!')
|
||||
}
|
||||
}
|
||||
|
||||
function getWebviewContent(context) {
|
||||
let data = readFile(__dirname + '/vs_plugin_view.html');
|
||||
data = getWebViewContent(context, '/vs_plugin_view.html');
|
||||
return data.toString();
|
||||
}
|
||||
|
||||
function getWebViewContent(context, templatePath) {
|
||||
const resourcePath = path.join(context.extensionPath, templatePath);
|
||||
const dirPath = path.dirname(resourcePath);
|
||||
let html = fs.readFileSync(resourcePath, 'utf-8');
|
||||
html = html.replace(/(<link.+?href="|<script.+?src="|<iframe.+?src="|<img.+?src=")(.+?)"/g, (m, $1, $2) => {
|
||||
if ($2.indexOf("https://") < 0) {
|
||||
return $1 + globalPanel.webview.asWebviewUri(vscode.Uri.file(path.resolve(dirPath, $2))) + '"';
|
||||
} else {
|
||||
return $1 + $2+'"';
|
||||
}
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
// This method is called when your extension is deactivated
|
||||
function deactivate() {}
|
||||
|
||||
module.exports = {
|
||||
activate,
|
||||
deactivate
|
||||
}
|
BIN
hdc/assist/assist_tools_vs_plugin/src/images/api.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
hdc/assist/assist_tools_vs_plugin/src/images/clear.png
Normal file
After Width: | Height: | Size: 327 B |
BIN
hdc/assist/assist_tools_vs_plugin/src/images/gn.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
hdc/assist/assist_tools_vs_plugin/src/images/h2ts.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
hdc/assist/assist_tools_vs_plugin/src/images/napi.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
hdc/assist/assist_tools_vs_plugin/src/images/search.png
Normal file
After Width: | Height: | Size: 408 B |
BIN
hdc/assist/assist_tools_vs_plugin/src/images/service.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
13
hdc/assist/assist_tools_vs_plugin/src/jsconfig.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "ES2020",
|
||||
"checkJs": false, /* Typecheck .js files. */
|
||||
"lib": [
|
||||
"ES2020"
|
||||
]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
61
hdc/assist/assist_tools_vs_plugin/src/package.json
Normal file
@ -0,0 +1,61 @@
|
||||
{
|
||||
"name": "AssistTools",
|
||||
"displayName": "Kaihong Assist Tools",
|
||||
"description": "This is the Kaihong assistance tools unified entrance for OpenHarmony OS developer.",
|
||||
"version": "0.0.1",
|
||||
"engines": {
|
||||
"vscode": "^1.70.3"
|
||||
},
|
||||
"publisher": "kaihong",
|
||||
"categories": [
|
||||
"Other"
|
||||
],
|
||||
"activationEvents": [
|
||||
"onStartupFinished"
|
||||
],
|
||||
"main": "./extension.js",
|
||||
"contributes": {
|
||||
"commands": [
|
||||
{
|
||||
"command": "assist_tools",
|
||||
"title": "Kaihong Assist Tools"
|
||||
}
|
||||
],
|
||||
"menus": {
|
||||
"explorer/context": [
|
||||
{
|
||||
"when": "resourceScheme == file",
|
||||
"command": "assist_tools"
|
||||
}
|
||||
],
|
||||
"editor/context": [
|
||||
{
|
||||
"command": "assist_tools"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint .",
|
||||
"pretest": "npm run lint",
|
||||
"test": "node ./test/runTest.js"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/glob": "^8.1.0",
|
||||
"@types/mocha": "^10.0.1",
|
||||
"@types/node": "16.x",
|
||||
"@types/vscode": "^1.70.3",
|
||||
"@vscode/test-electron": "^2.2.3",
|
||||
"eslint": "^8.34.0",
|
||||
"glob": "^8.1.0",
|
||||
"mocha": "^10.2.0",
|
||||
"typescript": "^4.9.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"vsce": "^2.15.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "gitee",
|
||||
"url": "https://gitee.com/openharmony/napi_generator/tree/master/hdc/assist"
|
||||
}
|
||||
}
|
68
hdc/assist/assist_tools_vs_plugin/src/util/VsPluginTool.js
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
const fs = require('fs');
|
||||
let vscode = null;
|
||||
try {
|
||||
vscode = require('vscode');
|
||||
}
|
||||
catch (err) {
|
||||
vscode = null;
|
||||
}
|
||||
|
||||
function utf8ArrayToStr(array) {
|
||||
var out, i, len, c;
|
||||
var char2, char3;
|
||||
|
||||
out = "";
|
||||
len = array.length;
|
||||
i = 0;
|
||||
while (i < len) {
|
||||
c = array[i++];
|
||||
switch (c >> 4) {
|
||||
case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
|
||||
// 0xxxxxxx
|
||||
out += String.fromCharCode(c);
|
||||
break;
|
||||
case 12: case 13:
|
||||
// 110x xxxx 10xx xxxx
|
||||
char2 = array[i++];
|
||||
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||
break;
|
||||
case 14:
|
||||
// 1110 xxxx 10xx xxxx 10xx xxxx
|
||||
char2 = array[i++];
|
||||
char3 = array[i++];
|
||||
out += String.fromCharCode(((c & 0x0F) << 12) |
|
||||
((char2 & 0x3F) << 6) |
|
||||
((char3 & 0x3F) << 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
function readFile(fn) {
|
||||
if (!fs.existsSync(fn)) {
|
||||
return "";
|
||||
}
|
||||
let data = fs.readFileSync(fn);
|
||||
data = utf8ArrayToStr(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
readFile
|
||||
}
|
430
hdc/assist/assist_tools_vs_plugin/src/vs_plugin_view.html
Normal file
@ -0,0 +1,430 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" style="width: 100%; height: 100%;">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Kaihong Assist Tools</title>
|
||||
</head>
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #333333;
|
||||
margin:0 auto;
|
||||
font-family: Consolas, sans-serif;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
button.button {
|
||||
background-color: #ffffff;
|
||||
font-family: Consolas, sans-serif;
|
||||
font-size: 16px;
|
||||
border-radius: 3px;
|
||||
border-color: #C4C4C4;
|
||||
align-self: center;
|
||||
border: 1px solid #C4C4C4;
|
||||
outline: none;
|
||||
width: 100px;
|
||||
height:24px
|
||||
}
|
||||
|
||||
button.button:hover {
|
||||
background: #4B97D9;
|
||||
color: #fff;
|
||||
border: 0px;
|
||||
font-family: Consolas, sans-serif;
|
||||
font-size: 16px;
|
||||
width: 100px;
|
||||
height: 24px
|
||||
}
|
||||
|
||||
input.text:focus {
|
||||
outline: 2px solid #4B97D9;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
input.text {
|
||||
outline: 2px solid #C4C4C4;
|
||||
border: 0px;
|
||||
}
|
||||
.tabs{
|
||||
position: relative;
|
||||
height: 800px;
|
||||
min-height: 800px;
|
||||
max-height: 800px;
|
||||
clear: both;
|
||||
margin: 25px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.tab{
|
||||
float: left;
|
||||
margin: 25px 0;
|
||||
}
|
||||
.tab label{
|
||||
background: #333333;
|
||||
padding: 10px 20px;
|
||||
position: relative;
|
||||
left: 1px;
|
||||
border: 0px solid;
|
||||
margin-left: -1px;
|
||||
z-index: 2;
|
||||
color: #eee;
|
||||
}
|
||||
input.text {
|
||||
width: 250px;
|
||||
height: 18px;
|
||||
vertical-align:middle;
|
||||
}
|
||||
.content{
|
||||
position: absolute;
|
||||
top: 61px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: #333333;
|
||||
padding: 20px 20px;
|
||||
border: 0px solid #ccc;
|
||||
max-height: 800px;
|
||||
overflow: hidden;
|
||||
}
|
||||
[type=radio]:checked ~ label{
|
||||
color: white;
|
||||
background: #3288e9;
|
||||
border: 0px solid #ccc;
|
||||
z-index: 3;
|
||||
}
|
||||
[type=radio]:checked ~ label ~ .content{
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
<script type="text/javascript">
|
||||
var mode = 0;
|
||||
let vscode = acquireVsCodeApi();
|
||||
var importCheck = false;
|
||||
var chooseApi = false;
|
||||
var chooseGn = false;
|
||||
var chooseService = false;
|
||||
var chooseTs = false;
|
||||
var chooseNapi = false;
|
||||
|
||||
function onInput(event) {
|
||||
var value = event.target.value;
|
||||
value.replace(/\s*/g,"").toLowerCase();
|
||||
checkInput(value);
|
||||
}
|
||||
|
||||
// 匹配子串
|
||||
function matchSubString(str, input) {
|
||||
for (let j = 1; j <= str.length; j++) {
|
||||
const sub = str.substring(0, j);
|
||||
if (input.indexOf(sub) !== -1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkInput(value) {
|
||||
if (matchSubString("apiscan", value)) {
|
||||
document.getElementById("api").style.display="flex";
|
||||
document.getElementById("gn").style.display="none";
|
||||
document.getElementById("service").style.display="none";
|
||||
document.getElementById("ts").style.display="none";
|
||||
document.getElementById("napi").style.display="none";
|
||||
} else if (matchSubString("gngen", value)) {
|
||||
document.getElementById("api").style.display="none";
|
||||
document.getElementById("gn").style.display="flex";
|
||||
document.getElementById("service").style.display="none";
|
||||
document.getElementById("ts").style.display="none";
|
||||
document.getElementById("napi").style.display="none";
|
||||
} else if (matchSubString("servicegen", value)) {
|
||||
document.getElementById("api").style.display="none";
|
||||
document.getElementById("gn").style.display="none";
|
||||
document.getElementById("service").style.display="flex";
|
||||
document.getElementById("ts").style.display="none";
|
||||
document.getElementById("napi").style.display="none";
|
||||
} else if (matchSubString("tsgen", value)) {
|
||||
document.getElementById("api").style.display="none";
|
||||
document.getElementById("gn").style.display="none";
|
||||
document.getElementById("service").style.display="none";
|
||||
document.getElementById("ts").style.display="flex";
|
||||
document.getElementById("napi").style.display="none";
|
||||
} else if (matchSubString("napigen", value)) {
|
||||
document.getElementById("api").style.display="none";
|
||||
document.getElementById("gn").style.display="none";
|
||||
document.getElementById("service").style.display="none";
|
||||
document.getElementById("ts").style.display="none";
|
||||
document.getElementById("napi").style.display="flex";
|
||||
} else if (value.trim() == '') {
|
||||
clearSelect();
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelect() {
|
||||
document.getElementById("api").style.display="flex";
|
||||
document.getElementById("gn").style.display="flex";
|
||||
document.getElementById("service").style.display="flex";
|
||||
document.getElementById("ts").style.display="flex";
|
||||
document.getElementById("napi").style.display="flex";
|
||||
}
|
||||
|
||||
function cancel() {
|
||||
var result = {
|
||||
msg: "cancel"
|
||||
}
|
||||
vscode.postMessage(result);
|
||||
}
|
||||
|
||||
function sendParamMsg() {
|
||||
if (importCheck) {
|
||||
let checkApi = document.getElementById("isCheckApi").value;
|
||||
let checkGn = document.getElementById("isCheckGn").value;
|
||||
let checkService = document.getElementById("isCheckService").value;
|
||||
let checkTs = document.getElementById("isCheckTs").value;
|
||||
let checkNapi = document.getElementById("isCheckNapi").value;
|
||||
var result = {
|
||||
msg: "param",
|
||||
importIsCheck: importCheck,
|
||||
checkApi: checkApi,
|
||||
checkGn: checkGn,
|
||||
checkService: checkService,
|
||||
checkTs: checkTs,
|
||||
checkNapi: checkNapi,
|
||||
}
|
||||
vscode.postMessage(result);
|
||||
} else {
|
||||
sendParamMsg2();
|
||||
}
|
||||
}
|
||||
|
||||
function sendParamMsg2() {
|
||||
if (chooseApi) {
|
||||
var result = {
|
||||
msg: "startApi"
|
||||
}
|
||||
} else if (chooseGn) {
|
||||
var result = {
|
||||
msg: "startGn"
|
||||
}
|
||||
} else if (chooseService) {
|
||||
var result = {
|
||||
msg: "startService"
|
||||
}
|
||||
} else if (chooseTs) {
|
||||
var result = {
|
||||
msg: "startTs"
|
||||
}
|
||||
} else if (chooseNapi) {
|
||||
var result = {
|
||||
msg: "startNapi"
|
||||
}
|
||||
} else {
|
||||
console.error("ERROR!")
|
||||
}
|
||||
vscode.postMessage(result);
|
||||
}
|
||||
|
||||
function checkBox(obj) {
|
||||
importCheck = obj.checked;
|
||||
if (importCheck) {
|
||||
document.getElementById("isCheckApi").style.display="";
|
||||
document.getElementById("isCheckGn").style.display="";
|
||||
document.getElementById("isCheckService").style.display="";
|
||||
document.getElementById("isCheckTs").style.display="";
|
||||
document.getElementById("isCheckNapi").style.display="";
|
||||
} else {
|
||||
document.getElementById("isCheckApi").style.display="none";
|
||||
document.getElementById("isCheckGn").style.display="none";
|
||||
document.getElementById("isCheckService").style.display="none";
|
||||
document.getElementById("isCheckTs").style.display="none";
|
||||
document.getElementById("isCheckNapi").style.display="none";
|
||||
}
|
||||
}
|
||||
|
||||
function chooseApiTool() {
|
||||
document.getElementById("apiDescriptions").style.display="flex";
|
||||
document.getElementById("gnDescriptions").style.display="none";
|
||||
document.getElementById("serviceDescriptions").style.display="none";
|
||||
document.getElementById("tsDescriptions").style.display="none";
|
||||
document.getElementById("napiDescriptions").style.display="none";
|
||||
chooseApi = true;
|
||||
chooseGn = false;
|
||||
chooseService = false;
|
||||
chooseTs = false;
|
||||
chooseNapi = false;
|
||||
}
|
||||
|
||||
function chooseGnTool() {
|
||||
document.getElementById("apiDescriptions").style.display="none";
|
||||
document.getElementById("gnDescriptions").style.display="flex";
|
||||
document.getElementById("serviceDescriptions").style.display="none";
|
||||
document.getElementById("tsDescriptions").style.display="none";
|
||||
document.getElementById("napiDescriptions").style.display="none";
|
||||
chooseApi = false;
|
||||
chooseGn = true;
|
||||
chooseService = false;
|
||||
chooseTs = false;
|
||||
chooseNapi = false;
|
||||
}
|
||||
|
||||
function chooseServiceTool() {
|
||||
document.getElementById("apiDescriptions").style.display="none";
|
||||
document.getElementById("gnDescriptions").style.display="none";
|
||||
document.getElementById("serviceDescriptions").style.display="flex";
|
||||
document.getElementById("tsDescriptions").style.display="none";
|
||||
document.getElementById("napiDescriptions").style.display="none";
|
||||
chooseApi = false;
|
||||
chooseGn = false;
|
||||
chooseService = true;
|
||||
chooseTs = false;
|
||||
chooseNapi = false;
|
||||
}
|
||||
|
||||
function chooseTsTool() {
|
||||
document.getElementById("apiDescriptions").style.display="none";
|
||||
document.getElementById("gnDescriptions").style.display="none";
|
||||
document.getElementById("serviceDescriptions").style.display="none";
|
||||
document.getElementById("tsDescriptions").style.display="flex";
|
||||
document.getElementById("napiDescriptions").style.display="none";
|
||||
chooseApi = false;
|
||||
chooseGn = false;
|
||||
chooseService = false;
|
||||
chooseTs = true;
|
||||
chooseNapi = false;
|
||||
}
|
||||
|
||||
function chooseNapiTool() {
|
||||
document.getElementById("apiDescriptions").style.display="none";
|
||||
document.getElementById("gnDescriptions").style.display="none";
|
||||
document.getElementById("serviceDescriptions").style.display="none";
|
||||
document.getElementById("tsDescriptions").style.display="none";
|
||||
document.getElementById("napiDescriptions").style.display="flex";
|
||||
chooseApi = false;
|
||||
chooseGn = false;
|
||||
chooseService = false;
|
||||
chooseTs = false;
|
||||
chooseNapi = true;
|
||||
}
|
||||
|
||||
function chooseTool(obj) {
|
||||
if (obj == "isChooseApi") {
|
||||
chooseApiTool();
|
||||
} else if (obj == "isChooseGn") {
|
||||
chooseGnTool();
|
||||
} else if (obj == "isChooseService") {
|
||||
chooseServiceTool();
|
||||
} else if (obj == "isChooseTs") {
|
||||
chooseTsTool();
|
||||
} else if (obj == "isChooseNapi") {
|
||||
chooseNapiTool();
|
||||
} else {
|
||||
console.error("ERROR!")
|
||||
}
|
||||
}
|
||||
|
||||
function checkTool(obj, name) {
|
||||
if (name == "isCheckApi") {
|
||||
document.getElementById("isCheckApi").value = obj.checked;
|
||||
} else if (name == "isCheckGn") {
|
||||
document.getElementById("isCheckGn").value = obj.checked;
|
||||
} else if (name == "isCheckService") {
|
||||
document.getElementById("isCheckService").value = obj.checked;
|
||||
} else if (name == "isCheckTs") {
|
||||
document.getElementById("isCheckTs").value = obj.checked;
|
||||
} else if (name == "isCheckNapi") {
|
||||
document.getElementById("isCheckNapi").value = obj.checked;
|
||||
}
|
||||
else {
|
||||
console.error("ERROR!")
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<body>
|
||||
<div class="tabs">
|
||||
<div class="tab">
|
||||
<label for="tab2" style="font-size: x-large;">Choose Your Tool</label>
|
||||
<div class="content">
|
||||
<div style="float: right;" class="search">
|
||||
<img src="./images/search.png" width="20px" height="20px" style="vertical-align:middle;">
|
||||
<input class="text" accept="text" id="searchInput" placeholder="Search" oninput="onInput(event)" onpropertychange="onInput(event)">
|
||||
<img src="./images/clear.png" id="clearInput" width="20px" height="20px" style="vertical-align:middle;" onclick="clearSelect()">
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row; margin-top: 50px;">
|
||||
<div id="api" style="display: flex; flex-direction: column;">
|
||||
<img id="isChooseApi" src="./images/api.png" width="120px" height="150px" style="vertical-align:middle;"
|
||||
onclick="chooseTool('isChooseApi')">
|
||||
<label id="checkApiLabel" style="text-align: center;"><input id="isCheckApi" type="checkbox" style="vertical-align:middle; width: 20px; height: 20px; margin-left: -1px; display: none;"
|
||||
onclick="checkTool(this, 'isCheckApi')">API Scan</label>
|
||||
</div>
|
||||
<div id="gn" style="display: flex; flex-direction: column; margin-left: 25px;">
|
||||
<img id="isChooseGn" src="./images/gn.png" width="120px" height="150px" style="vertical-align:middle;"
|
||||
onclick="chooseTool('isChooseGn')">
|
||||
<label id="checkGnLabel" style="text-align: center;"><input id="isCheckGn" type="checkbox" style="vertical-align:middle; width: 20px; height: 20px; margin-left: -1px; display: none;"
|
||||
onclick="checkTool(this, 'isCheckGn')">GN</label>
|
||||
</div>
|
||||
<div id="service" style="display: flex; flex-direction: column; margin-left: 25px;">
|
||||
<img id="isChooseService" src="./images/service.png" width="120px" height="150px" style="vertical-align:middle;"
|
||||
onclick="chooseTool('isChooseService')">
|
||||
<label id="checkServiceLabel" style="text-align: center;"><input id="isCheckService" type="checkbox" style="vertical-align:middle; width: 20px; height: 20px; margin-left: -1px; display: none;"
|
||||
onclick="checkTool(this, 'isCheckService')">SERVICE</label>
|
||||
</div>
|
||||
<div id="ts" style="display: flex; flex-direction: column; margin-left: 25px;">
|
||||
<img id="isChooseTs" src="./images/h2ts.png" width="120px" height="150px" style="vertical-align:middle;"
|
||||
onclick="chooseTool('isChooseTs')">
|
||||
<label id="checkTsLabel" style="text-align: center;"><input id="isCheckTs" type="checkbox" style="vertical-align:middle; width: 20px; height: 20px; margin-left: -1px; display: none;"
|
||||
onclick="checkTool(this, 'isCheckTs')">TS</label>
|
||||
</div>
|
||||
<div id="napi" style="display: flex; flex-direction: column; margin-left: 25px;">
|
||||
<img id="isChooseNapi" src="./images/napi.png" width="120px" height="150px" style="vertical-align:middle;"
|
||||
onclick="chooseTool('isChooseNapi')">
|
||||
<label id="checkNapiLabel" style="text-align: center;"><input id="isCheckNapi" type="checkbox" style="vertical-align:middle; width: 20px; height: 20px; margin-left: -1px; display: none;"
|
||||
onclick="checkTool(this, 'isCheckNapi')">NAPI</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<label style="color: #BBBBBB;">是否启用工具链:</label>
|
||||
<input id= "importCheck" type="checkbox" name="import" style="vertical-align:middle; width: 20px; height: 20px; margin-left: -1px;"
|
||||
onclick="checkBox(this)">
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 50px;">
|
||||
<div id="apiDescriptions" style="display: flex; flex-direction: column;">
|
||||
<label style="font-size: large;">API Scan</label>
|
||||
<label style="color: #BBBBBB;">This tool can scan the Android APIs in OpenHarmony Projects</label>
|
||||
</div>
|
||||
<div id="gnDescriptions" style="display: none; flex-direction: column;">
|
||||
<label style="font-size: large;">GN Gen</label>
|
||||
<label style="color: #BBBBBB;">gn generate tool</label>
|
||||
</div>
|
||||
<div id="serviceDescriptions" style="display: none; flex-direction: column;">
|
||||
<label style="font-size: large;">SERVICE Gen</label>
|
||||
<label style="color: #BBBBBB;">Generate IPC service framework code for OpenHarmony</label>
|
||||
</div>
|
||||
<div id="tsDescriptions" style="display: none; flex-direction: column;">
|
||||
<label style="font-size: large;">TS Gen</label>
|
||||
<label style="color: #BBBBBB;">Generate TS interface file for OpenHarmony</label>
|
||||
</div>
|
||||
<div id="napiDescriptions" style="display: none; flex-direction: column;">
|
||||
<label style="font-size: large;">NAPI Gen</label>
|
||||
<label style="color: #BBBBBB;">Generate NAPI definition code and framework code for OpenHarmony</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<div style="text-align: left;">
|
||||
<a href="https://gitee.com/openharmony/napi_generator" target="_blank">
|
||||
<button type="button" style="background-color: #333333; width: 20px; height: 20px; border-radius: 50%;border: none; color: #BBBBBB;">?</button>
|
||||
</a>
|
||||
</div>
|
||||
<div style="text-align: right;">
|
||||
<button type="button" class="button" onclick="cancel()" style="background-color: #333333; border: 1px solid #333333; color: #fff;">Cancel</button>
|
||||
<button type="button" class="button" onclick="sendParamMsg()" style="background-color: #4B97D9; border: 1px solid #4B97D9; color: #fff;">Ok</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -26,6 +26,10 @@ var exeFilePath = null;
|
||||
var flag = "";
|
||||
var isTrue = false;
|
||||
var globalPanel = null;
|
||||
|
||||
var importToolChain = false;
|
||||
var extensionIds = [];
|
||||
var nextPluginId = null;
|
||||
// this method is called when your extension is activated
|
||||
// your extension is activated the very first time the command is executed
|
||||
|
||||
@ -35,7 +39,7 @@ var globalPanel = null;
|
||||
function activate(context) {
|
||||
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
||||
// This line of code will only be executed once when your extension is activated
|
||||
console.log('Congratulations, your extension "gnapi" is now active!');
|
||||
console.log('Congratulations, your extension "gn-gen" is now active!');
|
||||
let disposable = register(context, 'generate_gn');
|
||||
let disposableMenu = register(context, 'generate_gn_menu');
|
||||
context.subscriptions.push(disposable);
|
||||
@ -112,7 +116,7 @@ function exeFileExit() {
|
||||
}
|
||||
|
||||
function register(context, command) {
|
||||
let disposable = vscode.commands.registerCommand(command, function (uri) {
|
||||
let disposable = vscode.commands.registerCommand(command, function (uri, boolValue, items) {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
// Display a message box to the user
|
||||
globalPanel = vscode.window.createWebviewPanel(
|
||||
@ -124,24 +128,29 @@ function register(context, command) {
|
||||
retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset
|
||||
}
|
||||
);
|
||||
globalPanel.webview.html = getWebviewContent(context);
|
||||
if (typeof(boolValue) == 'boolean' && Array.isArray(items)) {
|
||||
if (boolValue == true) {
|
||||
//遍历数组item,查看当前插件id是数组的第几个元素,并拿出下一个元素,并判断当前id是否是最后一个元素并做相应处理
|
||||
let myExtensionId = 'kaihong.gn-gen';
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (myExtensionId == items[i] && (i == items.length - 1)) {
|
||||
importToolChain = false;
|
||||
} else if (myExtensionId == items[i] && (i != items.length - 1)) {
|
||||
importToolChain = boolValue;
|
||||
nextPluginId = items[i + 1];
|
||||
}
|
||||
extensionIds.push(items[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
globalPanel.webview.html = getWebviewContent(context, importToolChain);
|
||||
let msg;
|
||||
globalPanel.webview.onDidReceiveMessage(message => {
|
||||
msg = message.msg;
|
||||
if (msg == "cancel") {
|
||||
globalPanel.dispose();
|
||||
} else if(msg == "gn") {
|
||||
let outputCodeDir = message.outputCodeDir;
|
||||
let originCodeDir = message.originCodeDir;
|
||||
let inputScriptDir = message.inputScriptDir;
|
||||
let scriptType = message.scriptType;
|
||||
let transplantDir = message.transplantDir;
|
||||
let subsystemName = message.subsystemName;
|
||||
let componentName = message.componentName;
|
||||
let compileOptions = message.compileOptions;
|
||||
refreshJsonCfg(message.extFile, message.extFlag);
|
||||
checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType,
|
||||
transplantDir, subsystemName, componentName, compileOptions);
|
||||
checkReceiveMsg(message);
|
||||
} else {
|
||||
selectPath(globalPanel, message);
|
||||
}
|
||||
@ -157,6 +166,60 @@ function register(context, command) {
|
||||
return disposable;
|
||||
}
|
||||
|
||||
function checkReceiveMsg(message) {
|
||||
let outputCodeDir = message.outputCodeDir;
|
||||
let originCodeDir = message.originCodeDir;
|
||||
let inputScriptDir = message.inputScriptDir;
|
||||
let scriptType = message.scriptType;
|
||||
let transplantDir = message.transplantDir;
|
||||
let subsystemName = message.subsystemName;
|
||||
let componentName = message.componentName;
|
||||
let compileOptions = message.compileOptions;
|
||||
let buttonName = message.buttonName;
|
||||
|
||||
refreshJsonCfg(message.extFile, message.extFlag);
|
||||
checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType,
|
||||
transplantDir, subsystemName, componentName, compileOptions);
|
||||
|
||||
if (buttonName == 'Next') {
|
||||
startNextPlugin();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件执行命令
|
||||
*/
|
||||
function nextPluginExeCommand(nextPluginId) {
|
||||
if (nextPluginId == "kaihong.ApiScan") {
|
||||
return 'api_scan';
|
||||
} else if (nextPluginId == "kaihong.gn-gen") {
|
||||
return 'generate_gn';
|
||||
} else if (nextPluginId == "kaihong.service-gen") {
|
||||
return 'generate_service';
|
||||
} else if (nextPluginId == "kaihong.ts-gen") {
|
||||
return 'generate_ts';
|
||||
} else if (nextPluginId == "kaihong.napi-gen") {
|
||||
return 'generate_napi';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行完毕后开启工具链中下一个插件
|
||||
*/
|
||||
function startNextPlugin() {
|
||||
const extension = vscode.extensions.getExtension(nextPluginId);
|
||||
if (extension) {
|
||||
let startNextPlugin = nextPluginExeCommand(nextPluginId);
|
||||
try {
|
||||
vscode.commands.executeCommand(startNextPlugin, '', importToolChain, extensionIds);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择本地目录/文件夹
|
||||
*/
|
||||
@ -251,10 +314,14 @@ function checkMode(outputCodeDir, originCodeDir, inputScriptDir, scriptType,
|
||||
// this method is called when your extension is deactivated
|
||||
function deactivate() { }
|
||||
|
||||
function getWebviewContent(context) {
|
||||
function getWebviewContent(context, importToolChain) {
|
||||
let data = readFile(__dirname + '/vs_plugin_view.html');
|
||||
data = getWebViewContent(context, '/vs_plugin_view.html');
|
||||
return data.toString();
|
||||
let content = data.toString();
|
||||
if (importToolChain) {
|
||||
content = content.replace('Ok', 'Next');
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
function getWebViewContent(context, templatePath) {
|
||||
|
@ -68,8 +68,8 @@
|
||||
"typescript": "^4.8.4",
|
||||
"vsce": "^2.11.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "gitee",
|
||||
"url": "https://gitee.com/openharmony/napi_generator/tree/master/hdc/gn"
|
||||
}
|
||||
"repository": {
|
||||
"type": "gitee",
|
||||
"url": "https://gitee.com/openharmony/napi_generator/tree/master/hdc/gn"
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +163,7 @@
|
||||
var extFlagRadio = document.getElementById("extFlagRadio");
|
||||
var extFileInput = document.getElementById("extFileInput");
|
||||
var extFlagInput = document.getElementById("extFlagInput");
|
||||
var buttonName = document.getElementById("okButton").textContent;
|
||||
|
||||
var result = {
|
||||
msg: "gn",
|
||||
@ -175,7 +176,8 @@
|
||||
componentName: componentName,
|
||||
compileOptions: compileOptions,
|
||||
extFile: extFileRadio.checked ? extFileInput.value : "",
|
||||
extFlag: extFlagRadio.checked ? extFlagInput.value : ""
|
||||
extFlag: extFlagRadio.checked ? extFlagInput.value : "",
|
||||
buttonName: buttonName,
|
||||
}
|
||||
vscode.postMessage(result);
|
||||
}
|
||||
@ -430,7 +432,7 @@
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<button type="button" class="button" onclick="cancel()" style="background-color: #333333; border: 1px solid #333333; color: #fff;">Cancel</button>
|
||||
<button type="button" class="button" onclick="sendGnParamMsg()" style="background-color: #4B97D9; border: 1px solid #4B97D9; color: #fff;">Ok</button>
|
||||
<button id="okButton" type="button" class="button" onclick="sendGnParamMsg()" style="background-color: #4B97D9; border: 1px solid #4B97D9; color: #fff;">Ok</button>
|
||||
<a href="https://gitee.com/openharmony/napi_generator" target="_blank">
|
||||
<button type="button" style="background-color: #333333; width: 20px; height: 20px; border-radius: 50%;border: none; color: #fff;">?</button>
|
||||
</a>
|
||||
|
@ -23,6 +23,10 @@ const { detectPlatform, readFile } = require('./gen/tools/VsPluginTool');
|
||||
const path = require('path');
|
||||
var exeFilePath = null;
|
||||
var globalPanel = null;
|
||||
|
||||
var importToolChain = false;
|
||||
var extensionIds = [];
|
||||
var nextPluginId = null;
|
||||
// this method is called when your extension is activated
|
||||
// your extension is activated the very first time the command is executed
|
||||
|
||||
@ -32,7 +36,7 @@ var globalPanel = null;
|
||||
function activate(context) {
|
||||
// Use the console to output diagnostic information (console.log) and errors (console.error)
|
||||
// This line of code will only be executed once when your extension is activated
|
||||
console.log('Congratulations, your extension "gnapi" is now active!');
|
||||
console.log('Congratulations, your extension "service-gen" is now active!');
|
||||
let disposable = register(context, 'generate_service');
|
||||
let disposableMenu = register(context, 'generate_service_menu');
|
||||
context.subscriptions.push(disposable);
|
||||
@ -74,7 +78,7 @@ function exeFileExit() {
|
||||
}
|
||||
|
||||
function register(context, command) {
|
||||
let disposable = vscode.commands.registerCommand(command, function (uri) {
|
||||
let disposable = vscode.commands.registerCommand(command, function (uri, boolValue, items) {
|
||||
// The code you place here will be executed every time your command is executed
|
||||
// Display a message box to the user
|
||||
globalPanel = vscode.window.createWebviewPanel(
|
||||
@ -86,27 +90,30 @@ function register(context, command) {
|
||||
retainContextWhenHidden: true, // Keep the WebView state when it is hidden to avoid being reset
|
||||
}
|
||||
);
|
||||
globalPanel.webview.html = getWebviewContent(context);
|
||||
if (typeof(boolValue) == 'boolean' && Array.isArray(items)) {
|
||||
if (boolValue == true) {
|
||||
//遍历数组item,查看当前插件id是数组的第几个元素,并拿出下一个元素,并判断当前id是否是最后一个元素并做相应处理
|
||||
let myExtensionId = 'kaihong.service-gen';
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
if (myExtensionId == items[i] && (i == items.length - 1)) {
|
||||
importToolChain = false;
|
||||
} else if (myExtensionId == items[i] && (i != items.length - 1)) {
|
||||
importToolChain = boolValue;
|
||||
nextPluginId = items[i + 1];
|
||||
}
|
||||
extensionIds.push(items[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
globalPanel.webview.html = getWebviewContent(context, importToolChain);
|
||||
let msg;
|
||||
globalPanel.webview.onDidReceiveMessage(message => {
|
||||
msg = message.msg;
|
||||
if (msg == "cancel") {
|
||||
globalPanel.dispose();
|
||||
} else if(msg == "param") {
|
||||
let name = message.fileNames;
|
||||
let genDir = message.genDir;
|
||||
let serviceId = message.serviceId;
|
||||
name = re.replaceAll(name, " ", "");
|
||||
if ("" == name) {
|
||||
vscode.window.showErrorMessage("Please enter the path!");
|
||||
return;
|
||||
}
|
||||
if (exeFileExit()) {
|
||||
executorService(name, genDir, serviceId);
|
||||
} else {
|
||||
vscode.window.showInformationMessage("Copy executable program to " + __dirname);
|
||||
}
|
||||
}else {
|
||||
checkReceiveMsg(message);
|
||||
} else {
|
||||
selectPath(globalPanel, message);
|
||||
}
|
||||
}, undefined, context.subscriptions);
|
||||
@ -121,6 +128,61 @@ function register(context, command) {
|
||||
return disposable;
|
||||
}
|
||||
|
||||
function checkReceiveMsg(message) {
|
||||
let name = message.fileNames;
|
||||
let genDir = message.genDir;
|
||||
let serviceId = message.serviceId;
|
||||
let buttonName = message.buttonName;
|
||||
name = re.replaceAll(name, " ", "");
|
||||
if ("" == name) {
|
||||
vscode.window.showErrorMessage("Please enter the path!");
|
||||
return;
|
||||
}
|
||||
if (exeFileExit()) {
|
||||
executorService(name, genDir, serviceId);
|
||||
if (buttonName == 'Next') {
|
||||
startNextPlugin();
|
||||
}
|
||||
} else {
|
||||
vscode.window.showInformationMessage("Copy executable program to " + __dirname);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件执行命令
|
||||
*/
|
||||
function nextPluginExeCommand(nextPluginId) {
|
||||
if (nextPluginId == "kaihong.ApiScan") {
|
||||
return 'api_scan';
|
||||
} else if (nextPluginId == "kaihong.gn-gen") {
|
||||
return 'generate_gn';
|
||||
} else if (nextPluginId == "kaihong.service-gen") {
|
||||
return 'generate_service';
|
||||
} else if (nextPluginId == "kaihong.ts-gen") {
|
||||
return 'generate_ts';
|
||||
} else if (nextPluginId == "kaihong.napi-gen") {
|
||||
return 'generate_napi';
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行完毕后开启工具链中下一个插件
|
||||
*/
|
||||
function startNextPlugin() {
|
||||
const extension = vscode.extensions.getExtension(nextPluginId);
|
||||
if (extension) {
|
||||
let startNextPlugin = nextPluginExeCommand(nextPluginId);
|
||||
try {
|
||||
vscode.commands.executeCommand(startNextPlugin, '', importToolChain, extensionIds);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 选择本地目录/文件夹
|
||||
*/
|
||||
@ -158,10 +220,14 @@ function register(context, command) {
|
||||
// this method is called when your extension is deactivated
|
||||
function deactivate() { }
|
||||
|
||||
function getWebviewContent(context) {
|
||||
function getWebviewContent(context, importToolChain) {
|
||||
let data = readFile(__dirname + '/vs_plugin_view.html');
|
||||
data = getWebViewContent(context, '/vs_plugin_view.html');
|
||||
return data.toString();
|
||||
let content = data.toString();
|
||||
if (importToolChain) {
|
||||
content = content.replace('Ok', 'Next');
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
function getWebViewContent(context, templatePath) {
|
||||
|
@ -69,7 +69,7 @@
|
||||
"vsce": "^2.11.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "gitee",
|
||||
"url": "https://gitee.com/openharmony/napi_generator/tree/master/hdc/service"
|
||||
}
|
||||
"type": "gitee",
|
||||
"url": "https://gitee.com/openharmony/napi_generator/tree/master/hdc/service"
|
||||
}
|
||||
}
|
||||
|
@ -88,11 +88,13 @@
|
||||
var fileNames = document.getElementById("hFilePath").value;
|
||||
var genDir = document.getElementById("genHResultDir").value;
|
||||
var serviceId = document.getElementById("serviceID").value;
|
||||
var buttonName = document.getElementById("okButton").textContent;
|
||||
var result = {
|
||||
msg: "param",
|
||||
fileNames: fileNames,
|
||||
genDir: genDir,
|
||||
serviceId: serviceId,
|
||||
buttonName: buttonName,
|
||||
}
|
||||
vscode.postMessage(result);
|
||||
}
|
||||
@ -178,6 +180,7 @@
|
||||
document.getElementById("error").innerHTML="";
|
||||
}
|
||||
}
|
||||
|
||||
function isDarkColor(colorArr) {
|
||||
let grayLevel = colorArr[0] * 0.299 + colorArr[1] * 0.587 + colorArr[2] * 0.114;
|
||||
return grayLevel < 192;
|
||||
@ -248,7 +251,7 @@
|
||||
<td colspan="2">
|
||||
<button type="button" class="button" onclick="cancel()"
|
||||
style="background-color: #333333; border: 1px solid #333333; color: #fff;">Cancel</button>
|
||||
<button type="button" class="button" onclick="sendParamMsg()"
|
||||
<button id="okButton" type="button" class="button" onclick="sendParamMsg()"
|
||||
style="background-color: #4B97D9; border: 1px solid #4B97D9; color: #fff;">Ok</button>
|
||||
<a href="https://gitee.com/openharmony/napi_generator" target="_blank">
|
||||
<button type="button"
|
||||
|