-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
163 lines (149 loc) · 4.6 KB
/
index.ts
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import React_ from "react";
import { Terminal } from "xterm";
import { MenuItemConstructorOptions, clipboard, MenuItem } from "electron";
import { TermProps, Terms, Server } from "./src/hyper-types";
import { rawToHtml, RawToHtmlOptions } from "./src/raw-to-html";
const PLUGIN_NAME = "hyper-copy-as-html";
const PLUGIN_COPY_COMMAND = `${PLUGIN_NAME}:copy`;
/*
Main functionnality
*/
const copyAsHtml = (
termInstance: Terminal | null,
rawToHtmlOptions: RawToHtmlOptions
) => {
// const termInstance = (global as PluginGlobal).hyperCopyAsHtml.termInstance;
if (termInstance !== null) {
const selectionPosition = termInstance.getSelectionPosition();
if (selectionPosition !== undefined) {
const buffer = termInstance.buffer.active;
clipboard.writeText(
rawToHtml(selectionPosition, buffer, rawToHtmlOptions)
);
}
} else {
console.warn(
'No term instance registered in the plugin "hyper-copy-as-html".\nThis might be a bug.'
);
}
};
/*
Plugin exports
*/
// Adds a "Copy as HTML" option in the "Edit" menu
const decorateMenu = (
menu: MenuItemConstructorOptions[]
): MenuItemConstructorOptions[] => {
const editMenuIndex = menu.findIndex(
(menuItem) => menuItem.label && menuItem.label === "Edit"
);
if (editMenuIndex === -1 || menu[editMenuIndex].submenu === undefined) {
return menu;
}
const editSubmenu = menu[editMenuIndex]
.submenu as MenuItemConstructorOptions[];
const copyIndex = editSubmenu.findIndex(
(menuItem) => menuItem.role && menuItem.role === "copy"
);
const editMenu: MenuItemConstructorOptions = {
...menu[editMenuIndex],
// @ts-ignore
submenu: [
...editSubmenu.slice(0, copyIndex + 1),
{
label: "Copy as HTML",
accelerator: "ctrl+shift+h",
click: (_menuItem, browserWindow, _event) => {
if (browserWindow) {
// Send event to the Renderer context
browserWindow.rpc.emit("command", PLUGIN_COPY_COMMAND);
}
},
},
...editSubmenu.slice(copyIndex + 1),
],
};
return [
...menu.slice(0, editMenuIndex),
editMenu,
...menu.slice(editMenuIndex + 1),
];
};
// Add the command to the keymaps
const decorateKeymaps = (keymaps: Record<string, string>) => {
const newKeymaps: Record<string, string> = {};
newKeymaps[PLUGIN_COPY_COMMAND] = "ctrl+shift+h";
return { ...keymaps, ...newKeymaps };
};
// Register copyAsHtml handlers (editMenu button click, shortcut usage)
const decorateTerms = (
Terms: Terms & React_.Component<TermProps>,
{ React }: { React: typeof React_ }
) => {
// Terms alike class
return class extends React.Component<
{ onDecorated?(terms: Terms): void } & TermProps
> {
terms: Terms | null;
constructor(props: any, context: any) {
super(props, context);
this.terms = null;
this.onDecorated = this.onDecorated.bind(this);
}
onDecorated(terms: Terms) {
this.terms = terms;
try {
this.props.backgroundColor;
const commandResgistration: Record<
string,
(e: any, hyperDispatch: any) => void
> = {};
commandResgistration[PLUGIN_COPY_COMMAND] = (
_e: any,
_hyperDispatch: any
) => {
copyAsHtml(this.terms?.getActiveTerm().term || null, {
colorMap: this.props.colors,
defBgColor: this.props.backgroundColor,
defFgColor: this.props.foregroundColor,
});
};
this.terms.registerCommands(commandResgistration);
} catch {
console.error(
"hyper-copy-as-html: failed to add shortcut click listener."
);
}
// Don't forget to propagate it to HOC chain
if (this.props.onDecorated) this.props.onDecorated(terms);
}
componentDidMount() {
const l_window = window as typeof window & { rpc?: Server };
if (l_window.rpc) {
l_window.rpc.on("command", (command: string) => {
if (command === PLUGIN_COPY_COMMAND) {
copyAsHtml(this.terms?.getActiveTerm().term || null, {
colorMap: this.props.colors,
defBgColor: this.props.backgroundColor,
defFgColor: this.props.foregroundColor,
});
}
});
} else {
console.error(
"hyper-copy-as-html: failed to add menu button click listener."
);
}
}
render() {
return React.createElement(
// @ts-ignore
Terms,
Object.assign({}, this.props, {
onDecorated: this.onDecorated,
})
);
}
};
};
export { decorateMenu, decorateTerms, decorateKeymaps };