@contentstorage/core 2.2.1 → 3.0.1

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.
@@ -3,6 +3,7 @@ import chalk from 'chalk';
3
3
  import { pullContent } from './pull.js';
4
4
  import { generateTypes } from './generate-types.js';
5
5
  import { showStats } from './stats.js';
6
+ import { captureScreenshot } from './screenshot.js';
6
7
  const COMMANDS = {
7
8
  pull: {
8
9
  name: 'pull',
@@ -37,6 +38,15 @@ const COMMANDS = {
37
38
  ' --pending-changes Analyze pending/draft content',
38
39
  ],
39
40
  },
41
+ screenshot: {
42
+ name: 'screenshot',
43
+ description: 'Open browser in live-editor mode for screenshots',
44
+ usage: 'contentstorage screenshot --url <url> [options]',
45
+ options: [
46
+ ' --url <url> Dev server URL (e.g., http://localhost:3000)',
47
+ ' --content-key <key> Content key for your project',
48
+ ],
49
+ },
40
50
  };
41
51
  function showHelp() {
42
52
  console.log(chalk.bold('\nContentstorage CLI'));
@@ -99,6 +109,9 @@ async function main() {
99
109
  case 'stats':
100
110
  await showStats();
101
111
  break;
112
+ case 'screenshot':
113
+ await captureScreenshot();
114
+ break;
102
115
  default:
103
116
  console.error(chalk.red(`Unknown command: ${command}\n`));
104
117
  console.log(chalk.dim('Run "contentstorage --help" for usage'));
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function captureScreenshot(): Promise<void>;
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+ import { exec } from 'child_process';
3
+ import chalk from 'chalk';
4
+ import { loadConfig } from '../core/config-loader.js';
5
+ export async function captureScreenshot() {
6
+ console.log(chalk.blue('Starting screenshot mode...'));
7
+ // Parse CLI arguments
8
+ const config = await parseArguments();
9
+ // Validate configuration
10
+ if (!validateConfig(config)) {
11
+ process.exit(1);
12
+ }
13
+ // Build URL with live-editor params
14
+ const liveEditorUrl = buildLiveEditorUrl(config.url, config.contentKey);
15
+ console.log(chalk.blue(`Opening browser with live-editor mode...`));
16
+ console.log(chalk.dim(`URL: ${liveEditorUrl}`));
17
+ // Open in default browser
18
+ openInBrowser(liveEditorUrl);
19
+ console.log(chalk.green('\nBrowser opened successfully!'));
20
+ console.log(chalk.dim('Use the Contentstorage UI to capture screenshots.'));
21
+ }
22
+ async function parseArguments() {
23
+ const args = process.argv.slice(2);
24
+ const cliConfig = {};
25
+ for (let i = 0; i < args.length; i++) {
26
+ const arg = args[i];
27
+ if (arg.startsWith('--')) {
28
+ const key = arg.substring(2);
29
+ const value = args[i + 1];
30
+ if (value && !value.startsWith('--')) {
31
+ if (key === 'url') {
32
+ cliConfig.url = value;
33
+ }
34
+ else if (key === 'content-key') {
35
+ cliConfig.contentKey = value;
36
+ }
37
+ i++;
38
+ }
39
+ }
40
+ }
41
+ // Load file config for contentKey fallback
42
+ let fileConfig = {};
43
+ try {
44
+ fileConfig = await loadConfig();
45
+ }
46
+ catch {
47
+ console.log(chalk.yellow('Could not load configuration file. Using CLI arguments only.'));
48
+ }
49
+ return {
50
+ url: cliConfig.url || '',
51
+ contentKey: cliConfig.contentKey || fileConfig.contentKey,
52
+ };
53
+ }
54
+ function validateConfig(config) {
55
+ if (!config.url) {
56
+ console.error(chalk.red('Error: --url argument is required.'));
57
+ console.log(chalk.dim('Usage: contentstorage screenshot --url http://localhost:3000'));
58
+ console.log(chalk.dim(' contentstorage screenshot --url http://localhost:5173'));
59
+ return false;
60
+ }
61
+ try {
62
+ new URL(config.url);
63
+ }
64
+ catch {
65
+ console.error(chalk.red(`Error: Invalid URL format: ${config.url}`));
66
+ return false;
67
+ }
68
+ if (!config.contentKey) {
69
+ console.error(chalk.red('Error: content-key is required.'));
70
+ console.log(chalk.dim('Provide via --content-key or in contentstorage.config.js'));
71
+ return false;
72
+ }
73
+ return true;
74
+ }
75
+ function buildLiveEditorUrl(baseUrl, contentKey) {
76
+ const url = new URL(baseUrl);
77
+ url.searchParams.set('contentstorage_live_editor', 'true');
78
+ url.searchParams.set('screenshot_mode', 'true');
79
+ if (contentKey) {
80
+ url.searchParams.set('contentstorage_key', contentKey);
81
+ }
82
+ return url.toString();
83
+ }
84
+ function openInBrowser(url) {
85
+ const platform = process.platform;
86
+ let command;
87
+ if (platform === 'darwin') {
88
+ command = `open "${url}"`;
89
+ }
90
+ else if (platform === 'win32') {
91
+ command = `start "" "${url}"`;
92
+ }
93
+ else {
94
+ command = `xdg-open "${url}"`;
95
+ }
96
+ exec(command, (error) => {
97
+ if (error) {
98
+ console.error(chalk.red(`Failed to open browser: ${error.message}`));
99
+ console.log(chalk.yellow(`Please open this URL manually: ${url}`));
100
+ }
101
+ });
102
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Find Chrome executable on the system
3
+ * @returns Path to Chrome executable or null if not found
4
+ */
5
+ export declare function findChrome(): string | null;
6
+ /**
7
+ * Get helpful error message when Chrome is not found
8
+ */
9
+ export declare function getChromeNotFoundMessage(): string;
@@ -0,0 +1,58 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ /**
4
+ * Common Chrome installation paths by platform
5
+ */
6
+ const CHROME_PATHS = {
7
+ darwin: [
8
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
9
+ '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
10
+ '/Applications/Chromium.app/Contents/MacOS/Chromium',
11
+ ],
12
+ win32: [
13
+ 'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
14
+ 'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe',
15
+ process.env.LOCALAPPDATA
16
+ ? path.join(process.env.LOCALAPPDATA, 'Google\\Chrome\\Application\\chrome.exe')
17
+ : '',
18
+ ].filter(Boolean),
19
+ linux: [
20
+ '/usr/bin/google-chrome',
21
+ '/usr/bin/google-chrome-stable',
22
+ '/usr/bin/chromium',
23
+ '/usr/bin/chromium-browser',
24
+ '/snap/bin/chromium',
25
+ ],
26
+ };
27
+ /**
28
+ * Find Chrome executable on the system
29
+ * @returns Path to Chrome executable or null if not found
30
+ */
31
+ export function findChrome() {
32
+ const platform = process.platform;
33
+ const paths = CHROME_PATHS[platform] || [];
34
+ for (const chromePath of paths) {
35
+ if (chromePath && fs.existsSync(chromePath)) {
36
+ return chromePath;
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ /**
42
+ * Get helpful error message when Chrome is not found
43
+ */
44
+ export function getChromeNotFoundMessage() {
45
+ const platform = process.platform;
46
+ const installInstructions = {
47
+ darwin: 'Download from https://www.google.com/chrome/ or install via: brew install --cask google-chrome',
48
+ win32: 'Download from https://www.google.com/chrome/',
49
+ linux: 'Install via: sudo apt install google-chrome-stable (Debian/Ubuntu) or sudo dnf install google-chrome-stable (Fedora)',
50
+ };
51
+ return `Chrome not found on your system.
52
+
53
+ Searched locations:
54
+ ${(CHROME_PATHS[platform] || []).map((p) => ` - ${p}`).join('\n')}
55
+
56
+ To install Chrome:
57
+ ${installInstructions[platform] || 'Download from https://www.google.com/chrome/'}`;
58
+ }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@contentstorage/core",
3
3
  "author": "Kaido Hussar <kaido@contentstorage.app>",
4
4
  "homepage": "https://contentstorage.app",
5
- "version": "2.2.1",
5
+ "version": "3.0.1",
6
6
  "type": "module",
7
7
  "description": "Contentstorage CLI for managing translations and generating TypeScript types",
8
8
  "license": "MIT",
@@ -23,7 +23,7 @@
23
23
  "release": "npx release-it"
24
24
  },
25
25
  "dependencies": {
26
- "axios": "^1.7.2",
26
+ "axios": "^1.13.2",
27
27
  "chalk": "^4.1.2",
28
28
  "pluralize": "^8.0.0"
29
29
  },