UNPKG

8.58 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.LinuxTargetHelper = exports.installPrefix = void 0;
4const builder_util_1 = require("builder-util");
5const fs_extra_1 = require("fs-extra");
6const lazy_val_1 = require("lazy-val");
7const path_1 = require("path");
8exports.installPrefix = "/opt";
9class LinuxTargetHelper {
10 constructor(packager) {
11 this.packager = packager;
12 this.iconPromise = new lazy_val_1.Lazy(() => this.computeDesktopIcons());
13 this.mimeTypeFilesPromise = new lazy_val_1.Lazy(() => this.computeMimeTypeFiles());
14 this.maxIconPath = null;
15 }
16 get icons() {
17 return this.iconPromise.value;
18 }
19 get mimeTypeFiles() {
20 return this.mimeTypeFilesPromise.value;
21 }
22 async computeMimeTypeFiles() {
23 const items = [];
24 for (const fileAssociation of this.packager.fileAssociations) {
25 if (!fileAssociation.mimeType) {
26 continue;
27 }
28 const data = `<mime-type type="${fileAssociation.mimeType}">
29 <glob pattern="*.${fileAssociation.ext}"/>
30 ${fileAssociation.description ? `<comment>${fileAssociation.description}</comment>` : ""}
31 <icon name="x-office-document" />
32</mime-type>`;
33 items.push(data);
34 }
35 if (items.length === 0) {
36 return null;
37 }
38 const file = await this.packager.getTempFile(".xml");
39 await (0, fs_extra_1.outputFile)(file, '<?xml version="1.0" encoding="utf-8"?>\n<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">\n' + items.join("\n") + "\n</mime-info>");
40 return file;
41 }
42 // must be name without spaces and other special characters, but not product name used
43 async computeDesktopIcons() {
44 var _a, _b, _c;
45 const packager = this.packager;
46 const { platformSpecificBuildOptions, config } = packager;
47 const sources = [platformSpecificBuildOptions.icon, (_b = (_a = config.mac) === null || _a === void 0 ? void 0 : _a.icon) !== null && _b !== void 0 ? _b : config.icon].filter(str => !!str);
48 // If no explicit sources are defined, fallback to buildResources directory, then default framework icon
49 let fallbackSources = [...(0, builder_util_1.asArray)(packager.getDefaultFrameworkIcon())];
50 const buildResources = (_c = config.directories) === null || _c === void 0 ? void 0 : _c.buildResources;
51 if (buildResources && (await (0, builder_util_1.exists)((0, path_1.join)(buildResources, "icons")))) {
52 fallbackSources = [buildResources, ...fallbackSources];
53 }
54 // need to put here and not as default because need to resolve image size
55 const result = await packager.resolveIcon(sources, fallbackSources, "set");
56 this.maxIconPath = result[result.length - 1].file;
57 return result;
58 }
59 getDescription(options) {
60 return options.description || this.packager.appInfo.description;
61 }
62 getSanitizedVersion(target) {
63 const { appInfo: { version }, } = this.packager;
64 switch (target) {
65 case "pacman":
66 return version.replace(/-/g, "_");
67 case "rpm":
68 case "deb":
69 return version.replace(/-/g, "~");
70 default:
71 return version;
72 }
73 }
74 async writeDesktopEntry(targetSpecificOptions, exec, destination, extra) {
75 const data = await this.computeDesktopEntry(targetSpecificOptions, exec, extra);
76 const file = destination || (await this.packager.getTempFile(`${this.packager.appInfo.productFilename}.desktop`));
77 await (0, fs_extra_1.outputFile)(file, data);
78 return file;
79 }
80 computeDesktopEntry(targetSpecificOptions, exec, extra) {
81 if (exec != null && exec.length === 0) {
82 throw new Error("Specified exec is empty");
83 }
84 // https://github.com/electron-userland/electron-builder/issues/3418
85 if (targetSpecificOptions.desktop != null && targetSpecificOptions.desktop.Exec != null) {
86 throw new Error("Please specify executable name as linux.executableName instead of linux.desktop.Exec");
87 }
88 const packager = this.packager;
89 const appInfo = packager.appInfo;
90 const executableArgs = targetSpecificOptions.executableArgs;
91 if (exec == null) {
92 exec = `${exports.installPrefix}/${appInfo.sanitizedProductName}/${packager.executableName}`;
93 if (!/^[/0-9A-Za-z._-]+$/.test(exec)) {
94 exec = `"${exec}"`;
95 }
96 if (executableArgs) {
97 exec += " ";
98 exec += executableArgs.join(" ");
99 }
100 // https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables
101 const execCodes = ["%f", "%u", "%F", "%U"];
102 if (executableArgs == null || executableArgs.findIndex(arg => execCodes.includes(arg)) === -1) {
103 exec += " %U";
104 }
105 }
106 const desktopMeta = {
107 Name: appInfo.productName,
108 Exec: exec,
109 Terminal: "false",
110 Type: "Application",
111 Icon: packager.executableName,
112 // https://askubuntu.com/questions/367396/what-represent-the-startupwmclass-field-of-a-desktop-file
113 // must be set to package.json name (because it is Electron set WM_CLASS)
114 // to get WM_CLASS of running window: xprop WM_CLASS
115 // StartupWMClass doesn't work for unicode
116 // https://github.com/electron/electron/blob/2-0-x/atom/browser/native_window_views.cc#L226
117 StartupWMClass: appInfo.productName,
118 ...extra,
119 ...targetSpecificOptions.desktop,
120 };
121 const description = this.getDescription(targetSpecificOptions);
122 if (!(0, builder_util_1.isEmptyOrSpaces)(description)) {
123 desktopMeta.Comment = description;
124 }
125 const mimeTypes = (0, builder_util_1.asArray)(targetSpecificOptions.mimeTypes);
126 for (const fileAssociation of packager.fileAssociations) {
127 if (fileAssociation.mimeType != null) {
128 mimeTypes.push(fileAssociation.mimeType);
129 }
130 }
131 for (const protocol of (0, builder_util_1.asArray)(packager.config.protocols).concat((0, builder_util_1.asArray)(packager.platformSpecificBuildOptions.protocols))) {
132 for (const scheme of (0, builder_util_1.asArray)(protocol.schemes)) {
133 mimeTypes.push(`x-scheme-handler/${scheme}`);
134 }
135 }
136 if (mimeTypes.length !== 0) {
137 desktopMeta.MimeType = mimeTypes.join(";") + ";";
138 }
139 let category = targetSpecificOptions.category;
140 if ((0, builder_util_1.isEmptyOrSpaces)(category)) {
141 const macCategory = (packager.config.mac || {}).category;
142 if (macCategory != null) {
143 category = macToLinuxCategory[macCategory];
144 }
145 if (category == null) {
146 // https://github.com/develar/onshape-desktop-shell/issues/48
147 if (macCategory != null) {
148 builder_util_1.log.warn({ macCategory }, "cannot map macOS category to Linux. If possible mapping is known for you, please file issue to add it.");
149 }
150 builder_util_1.log.warn({
151 reason: "linux.category is not set and cannot map from macOS",
152 docs: "https://www.electron.build/configuration/linux",
153 }, 'application Linux category is set to default "Utility"');
154 category = "Utility";
155 }
156 }
157 desktopMeta.Categories = `${category}${category.endsWith(";") ? "" : ";"}`;
158 let data = `[Desktop Entry]`;
159 for (const name of Object.keys(desktopMeta)) {
160 data += `\n${name}=${desktopMeta[name]}`;
161 }
162 data += "\n";
163 return Promise.resolve(data);
164 }
165}
166exports.LinuxTargetHelper = LinuxTargetHelper;
167const macToLinuxCategory = {
168 "public.app-category.graphics-design": "Graphics",
169 "public.app-category.developer-tools": "Development",
170 "public.app-category.education": "Education",
171 "public.app-category.games": "Game",
172 "public.app-category.video": "Video;AudioVideo",
173 "public.app-category.utilities": "Utility",
174 "public.app-category.social-networking": "Network;Chat",
175 "public.app-category.finance": "Office;Finance",
176};
177//# sourceMappingURL=LinuxTargetHelper.js.map
\No newline at end of file