@wjt blog @wjt blog
首页
  • react
  • react-native
  • webpack
  • 其他
  • docker
  • liunx命令
读书
收藏

@wjt

遇见知识
首页
  • react
  • react-native
  • webpack
  • 其他
  • docker
  • liunx命令
读书
收藏
  • react

  • react-native

  • webpack

  • 其他

    • 从输入url到页面展示我们可以做那些优化?
    • vscode插件code-template实现
      • vscode插件code-template实现
        • 插件功能
        • 实现流程
    • qiankun搭建微前端步骤
  • 前端
  • 其他
@wjt
2023-07-06
目录

vscode插件code-template实现

# vscode插件code-template实现

# 插件功能

  1. 读取已经持久化的代码插入文件或者插入代码块。
  2. 保存代码块或者文件以便之后使用

# 实现流程

  1. 安装依赖
npm install -g yo
// 可能会出现Error: EACCES: permission denied, open '/Users/sherry/Library/Preferences/insight-nodejs/insight-yo.json.1293917385'
// 解决方案 sudo chown -R 用户名 /Users/用户名/Library/Preferences/insight-nodejs

npm install -g generator-code
1
2
3
4
5
  1. 生成初始化代码
yo code
// 第一个问题选择New Extension (JavaScript)
// 后面无特殊需求可以一直下一步
1
2
3
  1. 项目结构 ├── CHANGELOG.md ├── README.md ├── out ├── package.json // 除了基本的依赖信息, 还包含插件配置信息。后续会详细介绍 ├── src ├── extension.ts // 插件入口文件 ├── tsconfig.json ├── vsc-extension-quickstart.md └── yarn.lock

  2. 插件截图 插件截图

  3. 插件package.json配置详解

{
	"activationEvents": [ 
		"onCommand:pluginName.commandName" 
        // 防止与其他插件冲突采取命名空间.指令名称的方式
        // :前面的是指令的类型,不同的功能需要不同的类型。常见的有onCommand(触发式指令)、onView(视图指令)
        /** 所有的指令都需要在这里声明。否则
         *  vscode.commands.registerCommand('pluginName.commandName', (node) => {})
         * 注册的指令不会执行
        **/
	],
	"main": "./out/extension.js",
	"contributes": {
		"commands": [
			{
				"command": "pluginName.commandName",
				"title": "标题"
			},
      /** 针对activationEvents声明的指令添加描述
      * 通常有指令的标题,图标等...
      **/
		],
		"viewsContainers": {
			"activitybar": [
				{
					"id": "viewID",
					"title": "",
					"icon": ""
				}
			]
      // 注册视图入口按钮。通过id: viewID和views.viewID给视图容器绑定多个视图
		},
		"views": {
			"viewID": [
				{
					"id": "pluginName.commandName", // 这里的id需要与activationEvents声明的onView: pluginName.commandName对映
					"name": ""
				},
			]
		},
		"viewsWelcome": [
			{
				"view": "pluginName.commandName",
				"contents": "当视图内容为空的时候显示的内容"
			},
		],
		"menus": {
			"editor/context": [],
			"view/title": [
				{
					"command": "pluginName.commandName",
					"when": ""
				},
                // 给视图声明按钮。command表示点击按钮触发的指令,when控制按钮的显示/隐藏
			],
			"explorer/context": [
				{
					"command": "pluginName.commandName",
					"when": ""
				}
                // 给explorer添加菜单。command表示点击菜单触发的指令,when控制按钮的显示/隐藏
			],
			"view/item/context": [
				{
					"command": "pluginName.commandName",
					"when": ""
				}
                // 给视图树添加右击菜单。。command表示点击菜单触发的指令,when控制按钮的显示/隐藏
			]
		},
		"configuration": [
			{
				"title": "code-template",
				"properties": {
          // 初始化声明插件需要用到的属性。可以通过scode.workspace.getConfiguration('pluginName')获取/设置属性
					"pluginName.port": {
					  "type": "number",
						"default": 22,
						"scope": "application",
						"description": "端口"
					},
				}
			}
		]
	},

}
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  1. 具体实现之本地视图-通过设置本地路径读取目录结构及文件 6.1 设置本地路径
vscode.window.showInputBox({
    placeHolder: '请输入本地绝对地址',
    value: getLocalPath(),
    validateInput: s => validatePath(s)
});
1
2
3
4
5

6.2 在extension.ts中注册视图

vscode.window.registerTreeDataProvider(
  'pluginName.commandName', //  对映pageage.json中"onView:pluginName.commandName"
  xxxTreeDataProvider
);
1
2
3
4

6.3 xxxTreeDataProvider是视图的具体实现

export class LocalCodeTreeDataProvider implements vscode.TreeDataProvider<CodeTree>{
    onDidChangeTreeDataEvent: vscode.EventEmitter<unknown>;
    onDidChangeTreeData: any;
    constructor() {
        this.onDidChangeTreeDataEvent = new vscode.EventEmitter();
        this.onDidChangeTreeData = this.onDidChangeTreeDataEvent.event;
    }
    async refresh() {
        // 刷新树
        this.onDidChangeTreeDataEvent.fire(null);
    }
    getTreeItem(element: CodeTree): vscode.TreeItem {
        // 可以基于element数据为节点添加command
        return {
          ...element,
          command: {
              title: "",
              command: "pluginName.commandName",
              arguments: [element],
          },
        };
    }
    getChildren(element: CodeTree): Thenable<CodeTree[]>  {
        return Promise.reslove(getChildByPath())
    }

    private async getChildByPath(dirPath: string): Promise<CodeTree[]> {
        // 通过node fs模块根据文件夹路径获取子节点
    }
}
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
  1. 具体实现之本地视图-通过设置远程服务器和路径读取目录结构及文件 该实现和第6点实现基本一致。只在设置服务器信息之后利用ssh2 创建了一个sftp的链接。通过sftp读取目录结构及文件 7.1 设置服务器信息
export class ConfigLongRangeProvider extends event.EventEmitter {
    constructor() {
        super();
    }
    async inputLongRangeInfo() {
        const longRangeIP = await vscode.window.showInputBox({
            placeHolder: '请输入服务器IP',
            value: getLongRangeIP(),
            validateInput: s => validateIP(s)
        });
        vscode.window.showInformationMessage('服务器信息配置完成!');
        this.emit("rangePathConfigComplate");
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

7.2 设置完成服务器信息后创建sftp链接

const { Client } = require('ssh2');
import * as vscode from 'vscode';
class ConnectLongRange {
    private conn: any | null;
    constructor() {
        this.conn = null;
    };
    connect(config: any, callback: Function) {
        const {
            longRangeIP,
            longRangePass,
            longRangePort,
            longRangeUser
        } = config;
        const conn = new Client();
        conn.on('ready', async () => {
            conn.sftp((err: any, sftp: any) => {
                if (err) {
                    vscode.window.showErrorMessage(err.toString());
                    return;
                }
                this.conn = conn;
                callback(sftp);
            });
        })
        .connect({
            host: longRangeIP,
            port: longRangePort,
            username: longRangeUser,
            password: longRangePass
        });
    }
    destroy() {
        if (this.conn) {
            this.conn.end();
        }
    }
}
export default ConnectLongRange;


configLongRangeProvider.on("rangePathConfigComplate", (info: any) => {
  connectLongRange.destroy();
  connectLongRange.connect(info, (sftp: any) => {
    longRangeCodeTreeDataProvider.init(sftp); 
  });
});
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

7.3 利用sftp实现getChildByPath方法

private async getChildByPath(dirPath: string): Promise<CodeTree[]> {
    return new Promise((resolve: any, reject: any) => {
        this.sftp.readdir(dirPath, (err: any, list: any) => {
            resolve(fileList);
        });
    });
}
1
2
3
4
5
6
7
  1. 上面介绍的是vscode视图展示的实现,下面给视图添加相应的功能。 视图

8.1 package.json配置

"menus": {
    "editor/context": [],
    "view/title": [ // 视图右上角按钮
        {
            "command": "",
            "when": "",
            "group": ""
        }
    ],
    "view/item/context": [ // 视图右击菜单
        {
            "command": "",
            "group": "",
            "when": ""
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

其他的步骤和视图的实现基本一致(注册指令,编写具体实现逻辑代码)。

  1. 编辑区域菜单实现 子菜单 9.1 package.json配置
"submenus": [
    {
        "id": "相同的子菜单名称",
        "label": "xxx"
    }
]
"menus": {
    "editor/context": [
        {
            "submenu": "相同的子菜单名称",
            "when": "editorFocus"
        }
    ],
    "相同的子菜单名称": [ // 子菜单列表
        {
            "command": "xxx"
        },
        {
            "command": "xxx"
        }
    ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

9.2 读取代码块功能实现 quickPick

export const getCodeBlockProvider = async () => {
    const quickPick = vscode.window.createQuickPick();
    quickPick.placeholder = "placeholder";
    quickPick.items = [] // 包含label detail等字段的数组,按照自己喜欢的持久化方式读取到的数据
    quickPick.onDidChangeSelection(selection => {
        const { detail } = selection[0]; // 选中的item
        let editor = vscode.window.activeTextEditor;
        if (!editor) {
            return;
        }
        // 把代码块插入到光标的位置
        let snippet = new vscode.SnippetString(detail); 
        editor.insertSnippet(snippet);
    });
    quickPick.show();
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

9.3 保存代码块功能

export const saveCodeBlockProvider = async () => {
    let editor = vscode.window.activeTextEditor;
    if (!editor) {
        return;
    }
    const {
        selection
    } = editor;
    const detail = editor.document.getText(selection); // 获取到选中的代码块
    const label: any = await vscode.window.showInputBox({ // 输入代码块名称
        placeHolder: '请输入代码块名称',
    });
    // 最后持久化
    ...
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

插件发布流程 (opens new window) when的用法 (opens new window)

从输入url到页面展示我们可以做那些优化?
qiankun搭建微前端步骤

← 从输入url到页面展示我们可以做那些优化? qiankun搭建微前端步骤→

最近更新
01
find
07-06
02
cp
07-06
03
vim
07-06
更多文章>
Theme by Vdoing | Copyright © 2023-2023 @wjt | 浙ICP备2023018372号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式