pake-cli 0.0.1-beta.9 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.ecrc.json +3 -0
- package/.editorconfig +24 -0
- package/.github/FUNDING.yml +2 -2
- package/.github/ISSUE_TEMPLATE/bug.md +13 -0
- package/.github/workflows/editorconfig-check.yml +23 -0
- package/.github/workflows/main.yml +17 -0
- package/.github/workflows/rust-code-quality-check.yml +89 -0
- package/.prettierignore +4 -0
- package/.vscode/settings.json +3 -6
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +26 -0
- package/LICENSE +21 -0
- package/README.md +195 -54
- package/README_EN.md +91 -53
- package/app.csv +9 -0
- package/bin/README.md +72 -0
- package/bin/builders/MacBuilder.ts +14 -15
- package/bin/builders/base.ts +10 -1
- package/bin/builders/common.ts +9 -4
- package/bin/cli.ts +12 -5
- package/bin/defaults.ts +1 -0
- package/bin/options/icon.ts +38 -46
- package/bin/options/index.ts +3 -5
- package/bin/types.ts +3 -3
- package/bin/utils/shell.ts +9 -8
- package/bin/utils/tlds.ts +1489 -0
- package/bin/utils/url.ts +26 -0
- package/dist/twitter.css +176 -0
- package/icns2png.py +38 -0
- package/package.json +10 -8
- package/pake-default.icns +0 -0
- package/rollup.config.js +1 -1
- package/script/build.bat +80 -0
- package/script/build.sh +122 -0
- package/script/sd-apple-x64 +0 -0
- package/script/sd-linux-x64 +0 -0
- package/script/sd.exe +0 -0
- package/src-tauri/Cargo.lock +344 -65
- package/src-tauri/Cargo.toml +14 -6
- package/src-tauri/assets/com-tw93-weread.desktop +10 -0
- package/src-tauri/build.rs +1 -1
- package/src-tauri/icons/icon.icns +0 -0
- package/src-tauri/icons/reference.icns +0 -0
- package/src-tauri/icons/translate.icns +0 -0
- package/src-tauri/icons/twitter.icns +0 -0
- package/src-tauri/icons/{weRead.icns → weread.icns} +0 -0
- package/src-tauri/icons/youtube.icns +0 -0
- package/src-tauri/png/code_256.ico +0 -0
- package/src-tauri/png/code_32.ico +0 -0
- package/src-tauri/png/code_512.png +0 -0
- package/src-tauri/png/flomo_256.ico +0 -0
- package/src-tauri/png/flomo_32.ico +0 -0
- package/src-tauri/png/flomo_512.png +0 -0
- package/src-tauri/png/reference_256.ico +0 -0
- package/src-tauri/png/reference_32.ico +0 -0
- package/src-tauri/png/reference_512.png +0 -0
- package/src-tauri/png/tool_256.ico +0 -0
- package/src-tauri/png/tool_32.ico +0 -0
- package/src-tauri/png/tool_512.png +0 -0
- package/src-tauri/png/translate_256.ico +0 -0
- package/src-tauri/png/translate_32.ico +0 -0
- package/src-tauri/png/translate_512.png +0 -0
- package/src-tauri/png/twitter_256.ico +0 -0
- package/src-tauri/png/twitter_32.ico +0 -0
- package/src-tauri/png/twitter_512.png +0 -0
- package/src-tauri/png/weread_256.ico +0 -0
- package/src-tauri/png/weread_32.ico +0 -0
- package/src-tauri/png/weread_512.png +0 -0
- package/src-tauri/png/witeboard_256.ico +0 -0
- package/src-tauri/png/witeboard_32.ico +0 -0
- package/src-tauri/png/witeboard_512.png +0 -0
- package/src-tauri/png/youtube_256.ico +0 -0
- package/src-tauri/png/youtube_32.ico +0 -0
- package/src-tauri/png/youtube_512.png +0 -0
- package/src-tauri/png/yuque_256.ico +0 -0
- package/src-tauri/png/yuque_32.ico +0 -0
- package/src-tauri/png/yuque_512.png +0 -0
- package/src-tauri/src/main.rs +128 -25
- package/src-tauri/src/pake.js +140 -77
- package/src-tauri/tauri.conf.json +31 -14
- package/bin/options/title.ts +0 -14
- package/dist/cli.js +0 -399
- package/src-tauri/icons/anymind.icns +0 -0
- package/src-tauri/icons/fanfou.icns +0 -0
- package/src-tauri/icons/fone.icns +0 -0
- package/src-tauri/icons/jdread.icns +0 -0
- package/src-tauri/icons/jike.icns +0 -0
- package/src-tauri/icons/roam.icns +0 -0
- package/src-tauri/icons/vercel.icns +0 -0
- package/src-tauri/icons/whatsapp.icns +0 -0
|
@@ -4,22 +4,20 @@ import prompts from 'prompts';
|
|
|
4
4
|
import { checkRustInstalled, installRust } from '@/helpers/rust.js';
|
|
5
5
|
import { PakeAppOptions } from '@/types.js';
|
|
6
6
|
import { IBuilder } from './base.js';
|
|
7
|
-
import appRootPath from 'app-root-path';
|
|
8
7
|
import { shellExec } from '@/utils/shell.js';
|
|
9
8
|
import tauriConf from '../../src-tauri/tauri.conf.json';
|
|
10
|
-
import {
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import log from 'loglevel';
|
|
11
11
|
|
|
12
12
|
export default class MacBuilder implements IBuilder {
|
|
13
13
|
async prepare() {
|
|
14
14
|
if (checkRustInstalled()) {
|
|
15
|
-
console.log('Rust has been installed');
|
|
16
15
|
return;
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
console.warn('Rust is not installed, show prompt');
|
|
20
18
|
const res = await prompts({
|
|
21
19
|
type: 'confirm',
|
|
22
|
-
message: '
|
|
20
|
+
message: 'We detected that you have not installed Rust. Install it now?',
|
|
23
21
|
name: 'value',
|
|
24
22
|
});
|
|
25
23
|
|
|
@@ -27,40 +25,41 @@ export default class MacBuilder implements IBuilder {
|
|
|
27
25
|
// TODO 国内有可能会超时
|
|
28
26
|
await installRust();
|
|
29
27
|
} else {
|
|
30
|
-
|
|
28
|
+
log.error('Error: Pake need Rust to package your webapp!!!');
|
|
31
29
|
process.exit(2);
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
32
|
|
|
35
33
|
async build(url: string, options: PakeAppOptions) {
|
|
36
|
-
|
|
34
|
+
log.debug('PakeAppOptions', options);
|
|
37
35
|
|
|
38
|
-
const { width, height, fullscreen, transparent,
|
|
36
|
+
const { width, height, fullscreen, transparent, resizable, identifier, name } = options;
|
|
39
37
|
|
|
40
38
|
const tauriConfWindowOptions = {
|
|
41
39
|
width,
|
|
42
40
|
height,
|
|
43
41
|
fullscreen,
|
|
44
42
|
transparent,
|
|
45
|
-
title,
|
|
46
43
|
resizable,
|
|
47
44
|
};
|
|
48
45
|
|
|
46
|
+
// TODO 下面这块逻辑还可以再拆 目前比较简单
|
|
49
47
|
Object.assign(tauriConf.tauri.windows[0], { url, ...tauriConfWindowOptions });
|
|
50
48
|
tauriConf.package.productName = name;
|
|
51
49
|
tauriConf.tauri.bundle.identifier = identifier;
|
|
52
50
|
tauriConf.tauri.bundle.icon = [options.icon];
|
|
53
51
|
|
|
54
|
-
const
|
|
55
|
-
const configJsonPath =
|
|
52
|
+
const npmDirectory = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
53
|
+
const configJsonPath = path.join(npmDirectory, 'src-tauri/tauri.conf.json');
|
|
56
54
|
await fs.writeFile(configJsonPath, Buffer.from(JSON.stringify(tauriConf), 'utf-8'));
|
|
57
55
|
|
|
58
|
-
const code = await shellExec(`
|
|
56
|
+
const code = await shellExec(`cd ${npmDirectory} && npm run build`);
|
|
59
57
|
const dmgName = `${name}_${'0.2.0'}_universal.dmg`;
|
|
60
|
-
|
|
58
|
+
const appPath = this.getBuildedAppPath(npmDirectory, dmgName);
|
|
59
|
+
await fs.copyFile(appPath, path.resolve(`${name}_universal.dmg`));
|
|
61
60
|
}
|
|
62
61
|
|
|
63
|
-
getBuildedAppPath(dmgName: string) {
|
|
64
|
-
return path.join(
|
|
62
|
+
getBuildedAppPath(npmDirectory: string, dmgName: string) {
|
|
63
|
+
return path.join(npmDirectory, 'src-tauri/target/universal-apple-darwin/release/bundle/dmg', dmgName);
|
|
65
64
|
}
|
|
66
65
|
}
|
package/bin/builders/base.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import { PakeAppOptions } from '@/types.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Builder接口
|
|
5
|
+
* 不同平台打包过程需要实现 prepare 和 build 方法
|
|
6
|
+
*/
|
|
3
7
|
export interface IBuilder {
|
|
8
|
+
/** 前置检查 */
|
|
4
9
|
prepare(): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* 开始打包
|
|
12
|
+
* @param url 打包url
|
|
13
|
+
* @param options 配置参数
|
|
14
|
+
*/
|
|
5
15
|
build(url: string, options: PakeAppOptions): Promise<void>;
|
|
6
|
-
// getIcon(icon?: string): Promise<string>;
|
|
7
16
|
}
|
package/bin/builders/common.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import
|
|
2
|
-
import appRootPath from 'app-root-path';
|
|
1
|
+
import prompts from 'prompts';
|
|
3
2
|
|
|
4
|
-
export function
|
|
5
|
-
|
|
3
|
+
export async function promptText(message: string, initial?: string) {
|
|
4
|
+
const response = await prompts({
|
|
5
|
+
type: 'text',
|
|
6
|
+
name: 'content',
|
|
7
|
+
message,
|
|
8
|
+
initial,
|
|
9
|
+
});
|
|
10
|
+
return response.content;
|
|
6
11
|
}
|
package/bin/cli.ts
CHANGED
|
@@ -4,20 +4,27 @@ import { PakeCliOptions } from './types.js';
|
|
|
4
4
|
import { validateNumberInput, validateUrlInput } from './utils/validate.js';
|
|
5
5
|
import handleInputOptions from './options/index.js';
|
|
6
6
|
import BuilderFactory from './builders/BuilderFactory.js';
|
|
7
|
+
import log from 'loglevel';
|
|
7
8
|
|
|
8
|
-
program.version('0.0.1').description('A cli application can
|
|
9
|
+
program.version('0.0.1').description('A cli application can package a web page to desktop application');
|
|
9
10
|
|
|
10
11
|
program
|
|
12
|
+
.showHelpAfterError()
|
|
11
13
|
.argument('<url>', 'the web url you want to package', validateUrlInput)
|
|
12
14
|
.option('--name <string>', 'application name')
|
|
13
|
-
.option('--title <string>', 'application window title')
|
|
14
15
|
.option('--icon <string>', 'application icon', DEFAULT_PAKE_OPTIONS.icon)
|
|
15
|
-
.option('--height <number>', '
|
|
16
|
-
.option('--width <number>', '
|
|
17
|
-
.option('--no-resizable', 'whether the
|
|
16
|
+
.option('--height <number>', 'window height', validateNumberInput, DEFAULT_PAKE_OPTIONS.height)
|
|
17
|
+
.option('--width <number>', 'window width', validateNumberInput, DEFAULT_PAKE_OPTIONS.width)
|
|
18
|
+
.option('--no-resizable', 'whether the window can be resizable', DEFAULT_PAKE_OPTIONS.resizable)
|
|
18
19
|
.option('--fullscreen', 'makes the packaged app start in full screen', DEFAULT_PAKE_OPTIONS.fullscreen)
|
|
19
20
|
.option('--transparent', 'transparent title bar', DEFAULT_PAKE_OPTIONS.transparent)
|
|
21
|
+
.option('--debug', 'debug', DEFAULT_PAKE_OPTIONS.transparent)
|
|
20
22
|
.action(async (url: string, options: PakeCliOptions) => {
|
|
23
|
+
log.setDefaultLevel('info')
|
|
24
|
+
if (options.debug) {
|
|
25
|
+
log.setLevel('debug');
|
|
26
|
+
}
|
|
27
|
+
|
|
21
28
|
const builder = BuilderFactory.create();
|
|
22
29
|
await builder.prepare();
|
|
23
30
|
|
package/bin/defaults.ts
CHANGED
package/bin/options/icon.ts
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import { fileTypeFromBuffer } from 'file-type';
|
|
3
|
-
import url from 'url';
|
|
4
3
|
import { PakeAppOptions } from '../types.js';
|
|
5
|
-
import { dir
|
|
4
|
+
import { dir } from 'tmp-promise';
|
|
6
5
|
import path from 'path';
|
|
7
|
-
import pageIcon from 'page-icon';
|
|
8
|
-
import png2icons from 'png2icons';
|
|
9
|
-
import ICO from 'icojs';
|
|
10
6
|
import fs from 'fs/promises';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import log from 'loglevel';
|
|
11
9
|
|
|
12
10
|
export async function handleIcon(options: PakeAppOptions, url: string) {
|
|
13
|
-
console.log(options.icon);
|
|
14
11
|
if (options.icon) {
|
|
15
12
|
if (options.icon.startsWith('http')) {
|
|
16
13
|
return downloadIcon(options.icon);
|
|
@@ -24,52 +21,47 @@ export async function handleIcon(options: PakeAppOptions, url: string) {
|
|
|
24
21
|
}
|
|
25
22
|
|
|
26
23
|
export async function inferIcon(name: string, url: string) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
if (!icon) {
|
|
32
|
-
// TODO default icon
|
|
33
|
-
}
|
|
34
|
-
return icon;
|
|
24
|
+
log.info('You have not provided an app icon, use the default icon(can use --icon option to assign an icon)')
|
|
25
|
+
const npmDirectory = path.join(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
26
|
+
return path.join(npmDirectory, 'pake-default.icns');
|
|
35
27
|
}
|
|
36
28
|
|
|
37
|
-
export async function getIconFromPageUrl(url: string) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
29
|
+
// export async function getIconFromPageUrl(url: string) {
|
|
30
|
+
// const icon = await pageIcon(url);
|
|
31
|
+
// console.log(icon);
|
|
32
|
+
// if (icon.ext === '.ico') {
|
|
33
|
+
// const a = await ICO.parse(icon.data);
|
|
34
|
+
// icon.data = Buffer.from(a[0].buffer);
|
|
35
|
+
// }
|
|
44
36
|
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
// const iconDir = (await dir()).path;
|
|
38
|
+
// const iconPath = path.join(iconDir, `/icon.icns`);
|
|
47
39
|
|
|
48
|
-
|
|
40
|
+
// const out = png2icons.createICNS(icon.data, png2icons.BILINEAR, 0);
|
|
49
41
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
42
|
+
// await fs.writeFile(iconPath, out);
|
|
43
|
+
// return iconPath;
|
|
44
|
+
// }
|
|
53
45
|
|
|
54
|
-
export async function getIconFromMacosIcons(name: string) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
46
|
+
// export async function getIconFromMacosIcons(name: string) {
|
|
47
|
+
// const data = {
|
|
48
|
+
// query: name,
|
|
49
|
+
// filters: 'approved:true',
|
|
50
|
+
// hitsPerPage: 10,
|
|
51
|
+
// page: 1,
|
|
52
|
+
// };
|
|
53
|
+
// const res = await axios.post('https://p1txh7zfb3-2.algolianet.com/1/indexes/macOSicons/query?x-algolia-agent=Algolia%20for%20JavaScript%20(4.13.1)%3B%20Browser', data, {
|
|
54
|
+
// headers: {
|
|
55
|
+
// 'x-algolia-api-key': '0ba04276e457028f3e11e38696eab32c',
|
|
56
|
+
// 'x-algolia-application-id': 'P1TXH7ZFB3',
|
|
57
|
+
// },
|
|
58
|
+
// });
|
|
59
|
+
// if (!res.data.hits.length) {
|
|
60
|
+
// return '';
|
|
61
|
+
// } else {
|
|
62
|
+
// return downloadIcon(res.data.hits[0].icnsUrl);
|
|
63
|
+
// }
|
|
64
|
+
// }
|
|
73
65
|
|
|
74
66
|
export async function downloadIcon(iconUrl: string) {
|
|
75
67
|
let iconResponse;
|
package/bin/options/index.ts
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
|
+
import { promptText } from '@/builders/common.js';
|
|
2
|
+
import { getDomain } from '@/utils/url.js';
|
|
1
3
|
import { getIdentifier } from '../helpers/tauriConfig.js';
|
|
2
4
|
import { PakeAppOptions, PakeCliOptions } from '../types.js';
|
|
3
5
|
import { handleIcon } from './icon.js';
|
|
4
|
-
import { getTitleByURL } from './title.js';
|
|
5
6
|
|
|
6
7
|
export default async function handleOptions(options: PakeCliOptions, url: string): Promise<PakeAppOptions> {
|
|
7
8
|
const appOptions: PakeAppOptions = {
|
|
8
9
|
...options,
|
|
9
10
|
identifier: '',
|
|
10
11
|
};
|
|
11
|
-
if (!appOptions.title) {
|
|
12
|
-
appOptions.title = await getTitleByURL(url);
|
|
13
|
-
}
|
|
14
12
|
|
|
15
13
|
if (!appOptions.name) {
|
|
16
|
-
appOptions.name =
|
|
14
|
+
appOptions.name = await promptText('please input your application name', getDomain(url));
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
appOptions.identifier = getIdentifier(appOptions.name, url);
|
package/bin/types.ts
CHANGED
|
@@ -2,9 +2,6 @@ export interface PakeCliOptions {
|
|
|
2
2
|
/** 应用名称 */
|
|
3
3
|
name?: string;
|
|
4
4
|
|
|
5
|
-
/** 不填会取 url 的 title,取不到默认 webapp */
|
|
6
|
-
title?: string;
|
|
7
|
-
|
|
8
5
|
/** 应用icon */
|
|
9
6
|
icon: string;
|
|
10
7
|
|
|
@@ -22,6 +19,9 @@ export interface PakeCliOptions {
|
|
|
22
19
|
|
|
23
20
|
/** 是否开启沉浸式头部,默认为 false 不开启 ƒ*/
|
|
24
21
|
transparent: boolean;
|
|
22
|
+
|
|
23
|
+
/** 调试模式,会输出更多日志 */
|
|
24
|
+
debug: boolean;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
export interface PakeAppOptions extends PakeCliOptions {
|
package/bin/utils/shell.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import shelljs from
|
|
1
|
+
import shelljs from "shelljs";
|
|
2
|
+
|
|
2
3
|
export function shellExec(command: string) {
|
|
3
4
|
return new Promise<number>((resolve, reject) => {
|
|
4
|
-
shelljs.exec(command, { async: true, silent: false}, (code) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
shelljs.exec(command, { async: true, silent: false }, (code) => {
|
|
6
|
+
if (code === 0) {
|
|
7
|
+
resolve(0);
|
|
8
|
+
} else {
|
|
9
|
+
reject(new Error(`${code}`));
|
|
10
|
+
}
|
|
11
|
+
});
|
|
11
12
|
});
|
|
12
13
|
}
|