@sambitcreate/parsely-cli 2.0.0 → 2.2.0
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/README.md +114 -113
- package/dist/app.js +104 -26
- package/dist/cli.js +36 -2
- package/dist/components/Banner.d.ts +9 -1
- package/dist/components/Banner.js +18 -8
- package/dist/components/ErrorDisplay.js +3 -2
- package/dist/components/Footer.d.ts +2 -1
- package/dist/components/Footer.js +28 -4
- package/dist/components/LandingScreen.d.ts +8 -0
- package/dist/components/LandingScreen.js +89 -0
- package/dist/components/LoadingScreen.d.ts +6 -0
- package/dist/components/LoadingScreen.js +19 -0
- package/dist/components/Panel.d.ts +9 -0
- package/dist/components/Panel.js +6 -0
- package/dist/components/PhaseRail.d.ts +9 -0
- package/dist/components/PhaseRail.js +88 -0
- package/dist/components/RecipeCard.d.ts +4 -1
- package/dist/components/RecipeCard.js +202 -12
- package/dist/components/ScrapingStatus.d.ts +2 -1
- package/dist/components/ScrapingStatus.js +25 -8
- package/dist/components/URLInput.d.ts +4 -1
- package/dist/components/URLInput.js +46 -18
- package/dist/components/Welcome.d.ts +6 -1
- package/dist/components/Welcome.js +5 -2
- package/dist/hooks/useDisplayPalette.d.ts +1 -0
- package/dist/hooks/useDisplayPalette.js +15 -0
- package/dist/hooks/useTerminalViewport.d.ts +6 -0
- package/dist/hooks/useTerminalViewport.js +23 -0
- package/dist/services/scraper.d.ts +9 -1
- package/dist/services/scraper.js +290 -58
- package/dist/theme.d.ts +88 -28
- package/dist/theme.js +122 -27
- package/dist/utils/helpers.d.ts +4 -0
- package/dist/utils/helpers.js +30 -0
- package/dist/utils/shortcuts.d.ts +6 -0
- package/dist/utils/shortcuts.js +15 -0
- package/dist/utils/terminal.d.ts +8 -0
- package/dist/utils/terminal.js +114 -0
- package/dist/utils/text-layout.d.ts +1 -0
- package/dist/utils/text-layout.js +63 -0
- package/package.json +12 -8
- package/public/parsely-logo.svg +1 -0
package/dist/theme.js
CHANGED
|
@@ -1,30 +1,125 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
const symbols = {
|
|
5
|
+
bullet: '\u2022',
|
|
6
|
+
arrow: '\u2192',
|
|
7
|
+
check: '\u2713',
|
|
8
|
+
cross: '\u2717',
|
|
9
|
+
dot: '\u00B7',
|
|
10
|
+
ellipsis: '\u2026',
|
|
11
|
+
line: '\u2500',
|
|
12
|
+
active: '\u25c9',
|
|
13
|
+
pending: '\u25cb',
|
|
14
|
+
skip: '\u2212',
|
|
15
|
+
};
|
|
16
|
+
const themes = {
|
|
17
|
+
light: {
|
|
18
|
+
mode: 'light',
|
|
19
|
+
colors: {
|
|
20
|
+
brand: '#009c3f',
|
|
21
|
+
primary: '#0aa043',
|
|
22
|
+
secondary: '#ffbf69',
|
|
23
|
+
accent: '#ff7f50',
|
|
24
|
+
text: '#17311d',
|
|
25
|
+
muted: '#5f7564',
|
|
26
|
+
subtle: '#7a8b7a',
|
|
27
|
+
error: '#c24141',
|
|
28
|
+
success: '#0aa043',
|
|
29
|
+
warning: '#b7791f',
|
|
30
|
+
info: '#2563eb',
|
|
31
|
+
banner: '#009c3f',
|
|
32
|
+
border: '#b7cbb3',
|
|
33
|
+
borderFocus: '#0aa043',
|
|
34
|
+
label: '#b7791f',
|
|
35
|
+
chip: '#e4efe0',
|
|
36
|
+
recipePaper: '#FDFFF7',
|
|
37
|
+
recipeText: '#0aa043',
|
|
38
|
+
recipeMuted: '#5f7564',
|
|
39
|
+
recipeSubtle: '#43684b',
|
|
40
|
+
recipeBorder: '#0aa043',
|
|
41
|
+
recipeSoft: '#dcead5',
|
|
42
|
+
recipePanel: '#f7fbef',
|
|
43
|
+
},
|
|
44
|
+
symbols,
|
|
20
45
|
},
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
46
|
+
dark: {
|
|
47
|
+
mode: 'dark',
|
|
48
|
+
colors: {
|
|
49
|
+
brand: '#009c3f',
|
|
50
|
+
primary: '#86c06c',
|
|
51
|
+
secondary: '#ffbf69',
|
|
52
|
+
accent: '#ff7f50',
|
|
53
|
+
text: '#e7eef8',
|
|
54
|
+
muted: '#97a3b0',
|
|
55
|
+
subtle: '#64748b',
|
|
56
|
+
error: '#ff7b7b',
|
|
57
|
+
success: '#7bd389',
|
|
58
|
+
warning: '#ffd166',
|
|
59
|
+
info: '#6ec5ff',
|
|
60
|
+
banner: '#e7eef8',
|
|
61
|
+
border: '#2c394d',
|
|
62
|
+
borderFocus: '#86c06c',
|
|
63
|
+
label: '#ffbf69',
|
|
64
|
+
chip: '#192132',
|
|
65
|
+
recipePaper: '#0F1729',
|
|
66
|
+
recipeText: '#8de58b',
|
|
67
|
+
recipeMuted: '#b7c2d4',
|
|
68
|
+
recipeSubtle: '#8b99ad',
|
|
69
|
+
recipeBorder: '#009c3f',
|
|
70
|
+
recipeSoft: '#2b3c34',
|
|
71
|
+
recipePanel: '#111b30',
|
|
72
|
+
},
|
|
73
|
+
symbols,
|
|
29
74
|
},
|
|
30
75
|
};
|
|
76
|
+
function inferThemeModeFromColorEnv(env) {
|
|
77
|
+
const colorfgbg = env['COLORFGBG'];
|
|
78
|
+
if (!colorfgbg) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
const backgroundCode = Number.parseInt(colorfgbg.split(';').at(-1) ?? '', 10);
|
|
82
|
+
if (!Number.isFinite(backgroundCode)) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
return backgroundCode <= 6 || backgroundCode === 8 ? 'dark' : 'light';
|
|
86
|
+
}
|
|
87
|
+
export function resolveInitialThemeMode(env = process.env) {
|
|
88
|
+
const override = env['PARSELY_THEME'];
|
|
89
|
+
if (override === 'light' || override === 'dark') {
|
|
90
|
+
return override;
|
|
91
|
+
}
|
|
92
|
+
return inferThemeModeFromColorEnv(env) ?? 'light';
|
|
93
|
+
}
|
|
94
|
+
export async function detectPreferredThemeMode(env = process.env) {
|
|
95
|
+
const initial = resolveInitialThemeMode(env);
|
|
96
|
+
if (env['PARSELY_THEME'] === 'light' || env['PARSELY_THEME'] === 'dark' || env['COLORFGBG']) {
|
|
97
|
+
return initial;
|
|
98
|
+
}
|
|
99
|
+
if (process.platform !== 'darwin') {
|
|
100
|
+
return initial;
|
|
101
|
+
}
|
|
102
|
+
try {
|
|
103
|
+
const { stdout } = await execFileAsync('defaults', ['read', '-g', 'AppleInterfaceStyle']);
|
|
104
|
+
return stdout.trim() === 'Dark' ? 'dark' : 'light';
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
return initial;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
let activeTheme = themes[resolveInitialThemeMode()];
|
|
111
|
+
export function getTheme(mode) {
|
|
112
|
+
return themes[mode];
|
|
113
|
+
}
|
|
114
|
+
export function setActiveTheme(mode) {
|
|
115
|
+
activeTheme = themes[mode];
|
|
116
|
+
return activeTheme;
|
|
117
|
+
}
|
|
118
|
+
export function toggleThemeMode(mode) {
|
|
119
|
+
return mode === 'dark' ? 'light' : 'dark';
|
|
120
|
+
}
|
|
121
|
+
export const theme = new Proxy({}, {
|
|
122
|
+
get(_target, property) {
|
|
123
|
+
return activeTheme[property];
|
|
124
|
+
},
|
|
125
|
+
});
|
package/dist/utils/helpers.d.ts
CHANGED
|
@@ -13,6 +13,10 @@ export declare function formatMinutes(mins: number): string;
|
|
|
13
13
|
export declare function loadConfig(): {
|
|
14
14
|
openaiApiKey?: string;
|
|
15
15
|
};
|
|
16
|
+
export declare function sanitizeTerminalText(input: string): string;
|
|
17
|
+
export declare function sanitizeSingleLineInput(input: string): string;
|
|
18
|
+
export declare function normalizeRecipeUrl(input: string): string | null;
|
|
19
|
+
export declare function getUrlHost(url?: string): string;
|
|
16
20
|
/**
|
|
17
21
|
* Basic URL validation.
|
|
18
22
|
*/
|
package/dist/utils/helpers.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { config } from 'dotenv';
|
|
2
2
|
import { resolve } from 'path';
|
|
3
|
+
const ANSI_ESCAPE_PATTERN = /\u001B(?:\][^\u0007\u001B]*(?:\u0007|\u001B\\)|\[[0-?]*[ -/]*[@-~]|[@-Z\\-_])/g;
|
|
4
|
+
const CONTROL_CHAR_PATTERN = /[\u0000-\u0008\u000B-\u001A\u001C-\u001F\u007F-\u009F]/g;
|
|
3
5
|
/**
|
|
4
6
|
* Convert an ISO 8601 duration string (e.g. "PT1H30M") to total minutes.
|
|
5
7
|
* Returns -1 when the input is not parseable.
|
|
@@ -37,6 +39,34 @@ export function loadConfig() {
|
|
|
37
39
|
openaiApiKey: process.env['OPENAI_API_KEY'],
|
|
38
40
|
};
|
|
39
41
|
}
|
|
42
|
+
export function sanitizeTerminalText(input) {
|
|
43
|
+
return input
|
|
44
|
+
.replace(ANSI_ESCAPE_PATTERN, '')
|
|
45
|
+
.replace(CONTROL_CHAR_PATTERN, '');
|
|
46
|
+
}
|
|
47
|
+
export function sanitizeSingleLineInput(input) {
|
|
48
|
+
return input.replace(/[\r\n]+/g, '');
|
|
49
|
+
}
|
|
50
|
+
export function normalizeRecipeUrl(input) {
|
|
51
|
+
const trimmed = input.trim();
|
|
52
|
+
if (!trimmed)
|
|
53
|
+
return null;
|
|
54
|
+
if (/^[a-z][a-z\d+.-]*:/i.test(trimmed) && !/^https?:\/\//i.test(trimmed)) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
const url = /^https?:\/\//.test(trimmed) ? trimmed : `https://${trimmed}`;
|
|
58
|
+
return isValidUrl(url) ? url : null;
|
|
59
|
+
}
|
|
60
|
+
export function getUrlHost(url) {
|
|
61
|
+
if (!url)
|
|
62
|
+
return '';
|
|
63
|
+
try {
|
|
64
|
+
return new URL(url).host.replace(/^www\./, '');
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return url;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
40
70
|
/**
|
|
41
71
|
* Basic URL validation.
|
|
42
72
|
*/
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function toCtrlCharacter(letter) {
|
|
2
|
+
const normalized = letter.trim().toLowerCase();
|
|
3
|
+
if (!/^[a-z]$/.test(normalized)) {
|
|
4
|
+
throw new Error(`Unsupported control shortcut: ${letter}`);
|
|
5
|
+
}
|
|
6
|
+
return String.fromCharCode(normalized.charCodeAt(0) - 96);
|
|
7
|
+
}
|
|
8
|
+
export function isCtrlShortcut(input, key, letter) {
|
|
9
|
+
const normalized = letter.trim().toLowerCase();
|
|
10
|
+
return (key.ctrl === true && input.toLowerCase() === normalized) ||
|
|
11
|
+
input === toCtrlCharacter(normalized);
|
|
12
|
+
}
|
|
13
|
+
export function isThemeToggleShortcut(input, key) {
|
|
14
|
+
return isCtrlShortcut(input, key, 't');
|
|
15
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type EnvMap = Record<string, string | undefined>;
|
|
2
|
+
export declare function getRenderableHeight(rows: number): number;
|
|
3
|
+
export declare function shouldUseSynchronizedOutput(env?: EnvMap): boolean;
|
|
4
|
+
export declare function shouldUseDisplayPalette(env?: EnvMap): boolean;
|
|
5
|
+
export declare function setDefaultTerminalBackground(color: string): string;
|
|
6
|
+
export declare function resetDefaultTerminalBackground(): string;
|
|
7
|
+
export declare function createSynchronizedWriteProxy<T extends NodeJS.WriteStream>(stdout: T): T;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
const SYNC_OUTPUT_START = '\u001B[?2026h';
|
|
2
|
+
const SYNC_OUTPUT_END = '\u001B[?2026l';
|
|
3
|
+
const OSC = '\u001B]';
|
|
4
|
+
const ST = '\u001B\\';
|
|
5
|
+
const SYNCHRONIZED_OUTPUT_TERM_PROGRAMS = new Set([
|
|
6
|
+
'ghostty',
|
|
7
|
+
'WezTerm',
|
|
8
|
+
]);
|
|
9
|
+
const SYNCHRONIZED_OUTPUT_TERMS = [
|
|
10
|
+
'xterm-kitty',
|
|
11
|
+
'xterm-ghostty',
|
|
12
|
+
];
|
|
13
|
+
const DISPLAY_PALETTE_TERM_PROGRAMS = new Set([
|
|
14
|
+
'ghostty',
|
|
15
|
+
'Apple_Terminal',
|
|
16
|
+
'iTerm.app',
|
|
17
|
+
'WezTerm',
|
|
18
|
+
'WarpTerminal',
|
|
19
|
+
]);
|
|
20
|
+
const DISPLAY_PALETTE_TERMS = [
|
|
21
|
+
'alacritty',
|
|
22
|
+
'foot',
|
|
23
|
+
'foot-extra',
|
|
24
|
+
'xterm-ghostty',
|
|
25
|
+
'xterm-kitty',
|
|
26
|
+
];
|
|
27
|
+
function getTerm(env) {
|
|
28
|
+
return env['TERM']?.toLowerCase() ?? '';
|
|
29
|
+
}
|
|
30
|
+
function isMultiplexer(env) {
|
|
31
|
+
const term = getTerm(env);
|
|
32
|
+
return Boolean(env['TMUX'] || env['STY'] || term.startsWith('screen') || term.startsWith('tmux'));
|
|
33
|
+
}
|
|
34
|
+
function isPaletteBlocked(env) {
|
|
35
|
+
const term = getTerm(env);
|
|
36
|
+
return term === 'dumb' || term === 'linux' || env['TERM_PROGRAM'] === 'vscode' || env['TERMINAL_EMULATOR'] === 'JetBrains-JediTerm' || isMultiplexer(env);
|
|
37
|
+
}
|
|
38
|
+
export function getRenderableHeight(rows) {
|
|
39
|
+
if (!Number.isFinite(rows) || rows <= 1) {
|
|
40
|
+
return 1;
|
|
41
|
+
}
|
|
42
|
+
return Math.floor(rows) - 1;
|
|
43
|
+
}
|
|
44
|
+
export function shouldUseSynchronizedOutput(env = process.env) {
|
|
45
|
+
if (env['PARSELY_SYNC_OUTPUT'] === '0') {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (env['PARSELY_SYNC_OUTPUT'] === '1') {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
if (isMultiplexer(env)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
const termProgram = env['TERM_PROGRAM'] ?? '';
|
|
55
|
+
if (SYNCHRONIZED_OUTPUT_TERM_PROGRAMS.has(termProgram)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
const term = getTerm(env);
|
|
59
|
+
return SYNCHRONIZED_OUTPUT_TERMS.some((candidate) => term.startsWith(candidate));
|
|
60
|
+
}
|
|
61
|
+
export function shouldUseDisplayPalette(env = process.env) {
|
|
62
|
+
if (env['PARSELY_DISPLAY_PALETTE'] === '0') {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
if (env['PARSELY_DISPLAY_PALETTE'] === '1') {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
if (isPaletteBlocked(env)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
const termProgram = env['TERM_PROGRAM'] ?? '';
|
|
72
|
+
if (DISPLAY_PALETTE_TERM_PROGRAMS.has(termProgram)) {
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
const term = getTerm(env);
|
|
76
|
+
return DISPLAY_PALETTE_TERMS.some((candidate) => term.startsWith(candidate));
|
|
77
|
+
}
|
|
78
|
+
export function setDefaultTerminalBackground(color) {
|
|
79
|
+
return `${OSC}11;${color}${ST}`;
|
|
80
|
+
}
|
|
81
|
+
export function resetDefaultTerminalBackground() {
|
|
82
|
+
return `${OSC}111${ST}`;
|
|
83
|
+
}
|
|
84
|
+
function wrapChunk(chunk) {
|
|
85
|
+
if (typeof chunk === 'string') {
|
|
86
|
+
return `${SYNC_OUTPUT_START}${chunk}${SYNC_OUTPUT_END}`;
|
|
87
|
+
}
|
|
88
|
+
return Buffer.concat([
|
|
89
|
+
Buffer.from(SYNC_OUTPUT_START),
|
|
90
|
+
Buffer.from(chunk),
|
|
91
|
+
Buffer.from(SYNC_OUTPUT_END),
|
|
92
|
+
]);
|
|
93
|
+
}
|
|
94
|
+
export function createSynchronizedWriteProxy(stdout) {
|
|
95
|
+
const originalWrite = stdout.write.bind(stdout);
|
|
96
|
+
return new Proxy(stdout, {
|
|
97
|
+
get(target, prop) {
|
|
98
|
+
if (prop !== 'write') {
|
|
99
|
+
const value = Reflect.get(target, prop, target);
|
|
100
|
+
return typeof value === 'function' ? value.bind(target) : value;
|
|
101
|
+
}
|
|
102
|
+
return (chunk, encoding, callback) => {
|
|
103
|
+
const wrappedChunk = wrapChunk(chunk);
|
|
104
|
+
if (typeof encoding === 'function') {
|
|
105
|
+
return originalWrite(wrappedChunk, encoding);
|
|
106
|
+
}
|
|
107
|
+
if (encoding) {
|
|
108
|
+
return originalWrite(wrappedChunk, encoding, callback);
|
|
109
|
+
}
|
|
110
|
+
return originalWrite(wrappedChunk, callback);
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function wrapText(text: string, width: number, initialIndent?: string, continuationIndent?: string): string[];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
function getWidth(value) {
|
|
2
|
+
return Array.from(value).length;
|
|
3
|
+
}
|
|
4
|
+
function chunkWord(word, width) {
|
|
5
|
+
if (width <= 0) {
|
|
6
|
+
return [word];
|
|
7
|
+
}
|
|
8
|
+
const chunks = [];
|
|
9
|
+
let remaining = word;
|
|
10
|
+
while (getWidth(remaining) > width) {
|
|
11
|
+
const segment = Array.from(remaining).slice(0, width).join('');
|
|
12
|
+
chunks.push(segment);
|
|
13
|
+
remaining = Array.from(remaining).slice(width).join('');
|
|
14
|
+
}
|
|
15
|
+
if (remaining) {
|
|
16
|
+
chunks.push(remaining);
|
|
17
|
+
}
|
|
18
|
+
return chunks;
|
|
19
|
+
}
|
|
20
|
+
export function wrapText(text, width, initialIndent = '', continuationIndent = initialIndent) {
|
|
21
|
+
const normalized = text.replace(/\s+/g, ' ').trim();
|
|
22
|
+
if (!normalized) {
|
|
23
|
+
return [initialIndent.trimEnd()];
|
|
24
|
+
}
|
|
25
|
+
const words = normalized.split(' ');
|
|
26
|
+
const lines = [];
|
|
27
|
+
let prefix = initialIndent;
|
|
28
|
+
let current = '';
|
|
29
|
+
const flush = () => {
|
|
30
|
+
lines.push(`${prefix}${current}`.trimEnd());
|
|
31
|
+
prefix = continuationIndent;
|
|
32
|
+
current = '';
|
|
33
|
+
};
|
|
34
|
+
for (const word of words) {
|
|
35
|
+
const available = Math.max(1, width - getWidth(prefix));
|
|
36
|
+
if (getWidth(word) > available) {
|
|
37
|
+
if (current) {
|
|
38
|
+
flush();
|
|
39
|
+
}
|
|
40
|
+
const chunks = chunkWord(word, available);
|
|
41
|
+
chunks.forEach((chunk, index) => {
|
|
42
|
+
lines.push(`${prefix}${chunk}`.trimEnd());
|
|
43
|
+
if (index < chunks.length - 1) {
|
|
44
|
+
prefix = continuationIndent;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
prefix = continuationIndent;
|
|
48
|
+
current = '';
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const candidate = current ? `${current} ${word}` : word;
|
|
52
|
+
if (getWidth(prefix) + getWidth(candidate) <= width) {
|
|
53
|
+
current = candidate;
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
flush();
|
|
57
|
+
current = word;
|
|
58
|
+
}
|
|
59
|
+
if (current || lines.length === 0) {
|
|
60
|
+
lines.push(`${prefix}${current}`.trimEnd());
|
|
61
|
+
}
|
|
62
|
+
return lines;
|
|
63
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sambitcreate/parsely-cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "A smart recipe scraper CLI with interactive TUI built on Ink",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/cli.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dev": "tsx watch src/cli.tsx",
|
|
13
13
|
"build": "tsc",
|
|
14
14
|
"prepublishOnly": "npm run build",
|
|
15
|
-
"test": "
|
|
15
|
+
"test": "tsx --test test/**/*.test.ts",
|
|
16
16
|
"typecheck": "tsc --noEmit"
|
|
17
17
|
},
|
|
18
18
|
"keywords": [
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
},
|
|
30
30
|
"files": [
|
|
31
31
|
"dist",
|
|
32
|
+
"public/parsely-logo.svg",
|
|
32
33
|
"package.json",
|
|
33
34
|
"README.md",
|
|
34
35
|
"LICENSE"
|
|
@@ -42,19 +43,22 @@
|
|
|
42
43
|
},
|
|
43
44
|
"homepage": "https://github.com/sambitcreate/parsely-cli#readme",
|
|
44
45
|
"dependencies": {
|
|
46
|
+
"cheerio": "^1.0.0",
|
|
47
|
+
"cfonts": "^3.1.1",
|
|
48
|
+
"dotenv": "^16.4.7",
|
|
45
49
|
"ink": "^5.1.0",
|
|
50
|
+
"ink-big-text": "^2.0.0",
|
|
46
51
|
"ink-spinner": "^5.0.0",
|
|
47
52
|
"ink-text-input": "^6.0.0",
|
|
48
|
-
"react": "^18.3.1",
|
|
49
|
-
"puppeteer-core": "^24.2.1",
|
|
50
53
|
"openai": "^4.82.0",
|
|
51
|
-
"
|
|
52
|
-
"
|
|
54
|
+
"puppeteer-core": "^24.2.1",
|
|
55
|
+
"react": "^18.3.1"
|
|
53
56
|
},
|
|
54
57
|
"devDependencies": {
|
|
55
|
-
"
|
|
58
|
+
"@types/react": "^18.3.18",
|
|
59
|
+
"@types/ink-big-text": "^1.2.4",
|
|
56
60
|
"tsx": "^4.19.2",
|
|
57
|
-
"
|
|
61
|
+
"typescript": "^5.7.3"
|
|
58
62
|
},
|
|
59
63
|
"packageManager": "pnpm@10.28.1+sha512.7d7dbbca9e99447b7c3bf7a73286afaaf6be99251eb9498baefa7d406892f67b879adb3a1d7e687fc4ccc1a388c7175fbaae567a26ab44d1067b54fcb0d6a316"
|
|
60
64
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg fill="none" height="80" viewBox="0 0 331 80" width="331" xmlns="http://www.w3.org/2000/svg"><g fill="#009c3f"><path d="m34.6022 5.02498c10.1256 0 17.1729 1.7941 21.1417 5.38232 3.9689 3.5377 5.9533 8.5409 5.9533 15.0098 0 4.4474-.7887 8.2377-2.3661 11.3711-1.5773 3.0828-4.3504 5.5086-8.3193 7.2775-3.9688 1.7182-9.4387 2.5774-16.4096 2.5774h-14.6931c-.653 0-1.1823.5258-1.1823 1.1743v10.9934c0 .6486-.5294 1.1743-1.1823 1.1743h-16.36132c-.672092 0-1.2089086-.5561-1.18222669-1.2231.37382169-9.3451.56073269-18.11.56073269-26.2948s-.186911-16.9498-.56073268-26.29487c-.02668182-.66701.51013468-1.22315 1.18222668-1.22315h17.50542c.0211 0 .0382.01697.0382.0379s.0171.0379.0382.0379zm-5.3427 26.98732c4.2233 0 7.378-.1516 9.4642-.4548 2.137-.3538 3.6126-.9602 4.4268-1.8194.865-.8591 1.2975-2.1226 1.2975-3.7904 0-1.6677-.4071-2.9059-1.2212-3.7145-.7633-.8591-2.2134-1.4403-4.3505-1.7436-2.0862-.3032-5.2918-.4548-9.6168-.4548h-9.3504c-.653 0-1.1823.5258-1.1823 1.1743v9.6289c0 .6486.5293 1.1743 1.1823 1.1743z"/><path d="m110.596 47.4012c0 1.7183.203 2.9312.61 3.6387.295.5127.804.9193 1.527 1.2197.517.2153.899.6963.875 1.2533l-.223 5.2073c-.024.5592-.442 1.025-1 1.1051-1.235.1775-2.34.3065-3.316.3873-1.17.101-2.747.1516-4.732.1516-4.3757 0-7.276-.9602-8.7007-2.8807-1.4247-1.971-2.1371-4.4726-2.1371-7.5049 0-.3656-.5507-.4664-.6975-.1311-1.4308 3.2662-3.3608 5.761-5.79 7.4844-2.7986 2.0215-6.3858 3.0323-10.7617 3.0323-5.0882 0-8.9299-1.0108-11.5249-3.0323-2.5441-2.0215-3.8162-5.0285-3.8162-9.021 0-3.285 1.094-5.8625 3.2819-7.7324 1.7056-1.4576 4.1377-2.5621 7.2964-3.3134 1.0318-.2454 1.3424-1.6081.462-2.1962-2.6517-1.7713-5.3034-3.3762-7.9551-4.8148-.6491-.3521-.8311-1.201-.3517-1.7602 2.8323-3.3039 6.0172-5.8457 9.5547-7.6252 3.9179-2.0216 8.6754-3.0323 14.2725-3.0323 7.836 0 13.6364 1.693 17.4014 5.0791 3.817 3.3355 5.725 8.4904 5.725 15.4646zm-21.5236-16.2228c-2.595 0-4.8847.4296-6.8691 1.2888-1.0622.4598-2.0661 1.0428-3.0117 1.7489-.8743.6528-.2725 1.9073.8187 1.833 2.4118-.1643 5.1781-.2464 8.2989-.2464 1.8827 0 3.2056-.2274 3.9688-.6823.7633-.4548 1.1449-1.036 1.1449-1.7436 0-.6064-.3816-1.1118-1.1449-1.5161-.7632-.4548-1.8317-.6823-3.2056-.6823zm-8.014 16.8292c2.8494 0 5.419-.5306 7.7087-1.5919 2.1946-1.0657 3.7348-2.433 4.6206-4.1022.0758-.1428.1115-.3027.1115-.4641 0-.7929-.8448-1.316-1.5909-1.0341-.7747.2926-1.5928.5422-2.4542.7487-1.4756.3032-3.2565.6065-5.3427.9097l-2.7477.4548c-2.8494.556-4.2741 1.5162-4.2741 2.8807 0 1.4656 1.3229 2.1984 3.9688 2.1984z"/><path d="m132.683 25.0205c.247 1.2097 2.23 1.3516 2.864.2896 2.76-4.6287 7.449-6.9431 14.066-6.9431 1.063 0 2.098.0524 3.108.1571.647.0672 1.092.663 1 1.3027l-2.068 14.3777c-.107.7429-.878 1.1957-1.593.9525-3.042-1.0351-5.582-1.5527-7.621-1.5527-2.9 0-5.037.8591-6.411 2.5774s-2.061 4.0178-2.061 6.8985v-.0758l-.076 5.0032c0 3.2512.083 6.8342.25 10.7492.029.6691-.509 1.2283-1.183 1.2283h-15.754c-.678 0-1.218-.5665-1.182-1.2397.362-6.8195.543-13.2794.543-19.3798 0-6.0886-.18-12.5801-.541-19.4746-.036-.694.538-1.2689 1.237-1.2397 2.726.1137 4.86.1706 6.402.1706 1.683 0 3.915-.0606 6.696-.1817.583-.0254 1.099.3733 1.214.9411z"/><path d="m179.291 60.7432c-4.274 0-8.625-.5812-13.051-1.7435-3.971-1.1006-7.732-2.7005-11.284-4.7997-.589-.3482-.736-1.1249-.33-1.6737l6.571-8.889c.383-.5187 1.114-.6317 1.66-.2844 2.139 1.362 4.64 2.4587 7.504 3.2902 3.307.9097 6.157 1.3645 8.548 1.3645 2.29 0 4.045-.3032 5.267-.9097 1.272-.657 1.908-1.4908 1.908-2.5016 0-.8086-.306-1.4403-.916-1.8952-.611-.4548-1.45-.6822-2.519-.6822-.661 0-1.425.0252-2.29.0758-.814.0505-1.475.101-1.984.1516-2.646.3032-5.368.4548-8.167.4548-4.528 0-8.217-.8339-11.067-2.5016-2.798-1.7183-4.197-4.4979-4.197-8.3388 0-4.4473 2.111-7.8839 6.334-10.3098 4.224-2.4763 10.431-3.7145 18.624-3.7145 4.019 0 8.064.5812 12.135 1.7435 3.636.981 6.897 2.4144 9.78 4.3002.606.396.674 1.2403.164 1.7516l-7.191 7.2038c-.366.3667-.93.4514-1.394.2192-2.61-1.3054-5.073-2.234-7.389-2.7859-2.493-.657-5.012-.9855-7.556-.9855-1.781 0-3.307.3537-4.579 1.0613-1.272.7075-1.908 1.5161-1.908 2.4258 0 .7075.254 1.2634.763 1.6677.56.4043 1.272.6065 2.137.6065s2.061-.0758 3.587-.2274c3.715-.2527 6.488-.3791 8.32-.3791 5.291 0 9.388.8845 12.288 2.6533s4.35 4.4726 4.35 8.1114c0 5.4581-2.137 9.4253-6.411 11.9017-4.274 2.4258-10.176 3.6387-17.707 3.6387z"/><path d="m222.608 41.0334c-.737 0-1.3.6669-1.077 1.3652.517 1.6148 1.396 2.9791 2.637 4.0929 1.628 1.3645 3.918 2.0468 6.869 2.0468 2.137 0 4.147-.4043 6.03-1.2129 1.553-.7088 2.847-1.6412 3.88-2.7971.381-.4259.997-.5817 1.516-.3384 3.03 1.4224 6.855 2.9344 11.473 4.536.655.227.982.9631.648 1.5672-1.658 3.007-4.342 5.4543-8.053 7.342-4.121 2.0721-9.515 3.1081-16.181 3.1081-8.65 0-15.061-1.971-19.233-5.9129-4.122-3.9925-6.182-9.2232-6.182-15.6921 0-6.3173 2.06-11.4469 6.182-15.3889 4.121-3.9419 10.533-5.9129 19.233-5.9129 5.191 0 9.694.8591 13.51 2.5774s6.742 4.1189 8.777 7.2017c2.035 3.0323 3.053 6.5194 3.053 10.4614 0 .762-.017 1.4135-.051 1.9546-.037.5785-.532 1.0019-1.116 1.0019zm8.811-11.7501c-2.544 0-4.63.4801-6.259 1.4403-1.095.6458-1.971 1.4517-2.629 2.4177-.467.6859.098 1.5243.931 1.5243h14.57c.826 0 1.394-.8233.96-1.5211-.575-.9263-1.319-1.708-2.23-2.3451-1.374-1.0108-3.155-1.5161-5.343-1.5161z"/><path d="m276.649 29.6623c-.051 3.0323-.076 7.6818-.076 13.9485 0 6.6918.04 11.7473.121 15.1664.015.6621-.52 1.2079-1.186 1.2079h-15.602c-.657 0-1.188-.5321-1.182-1.1847l.066-7.3815c.101-9.4.152-16.6523.152-21.7566 0-4.8517-.051-11.7248-.152-20.61954l-.066-7.00198c-.006-.65278.525-1.185189 1.182-1.185189h15.621c.659 0 1.191.536539 1.182 1.191499-.091 6.63641-.136 12.10161-.136 16.39571 0 5.0539.025 8.7937.076 11.2195z"/><path d="m329.816 18.5945c.835 0 1.407.8363 1.1 1.6072l-1.114 2.7896c-4.834 12.7861-9.897 25.1174-15.189 36.9938-2.747 6.0646-6.716 10.9163-11.906 14.555-4.985 3.5433-11.19 5.3151-18.615 5.3155-.543 0-1.009-.3783-1.131-.9035-.877-3.7699-1.622-6.7567-2.236-8.9604-.425-1.6193-.949-3.2509-1.572-4.8948-.341-.9011.465-1.8519 1.419-1.6841 1.951.3429 3.808.5143 5.572.5143 3.571 0 6.482-.6748 8.735-2.0245.445-.2664.617-.8106.45-1.299-1.771-5.1734-3.84-10.7113-6.208-16.6138-2.364-5.8939-5.734-13.8097-10.111-23.7474-.342-.7763.23-1.6479 1.083-1.6479h15.347c.546 0 1.021.3722 1.154.8987.587 2.316 1.352 4.9476 2.297 7.8949 1.068 3.3355 2.137 6.5447 3.205 9.6275.305.9602.789 2.4258 1.45 4.3968.175.4701.34.9221.496 1.3559.388 1.0779 1.984 1.0794 2.344-.0079l.824-2.4851c3.503-10.0661 5.698-16.9814 6.586-20.7459.128-.5439.611-.9349 1.173-.9349z"/></g></svg>
|