@juangadm/pre-post 0.1.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.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +227 -0
  3. package/dist/bin/cli.d.ts +3 -0
  4. package/dist/bin/cli.d.ts.map +1 -0
  5. package/dist/bin/cli.js +388 -0
  6. package/dist/bin/cli.js.map +1 -0
  7. package/dist/browser.d.ts +25 -0
  8. package/dist/browser.d.ts.map +1 -0
  9. package/dist/browser.js +82 -0
  10. package/dist/browser.js.map +1 -0
  11. package/dist/capture.d.ts +9 -0
  12. package/dist/capture.d.ts.map +1 -0
  13. package/dist/capture.js +52 -0
  14. package/dist/capture.js.map +1 -0
  15. package/dist/clipboard.d.ts +9 -0
  16. package/dist/clipboard.d.ts.map +1 -0
  17. package/dist/clipboard.js +26 -0
  18. package/dist/clipboard.js.map +1 -0
  19. package/dist/filename.d.ts +24 -0
  20. package/dist/filename.d.ts.map +1 -0
  21. package/dist/filename.js +76 -0
  22. package/dist/filename.js.map +1 -0
  23. package/dist/index.d.ts +25 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +69 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/routes/generic.d.ts +11 -0
  28. package/dist/routes/generic.d.ts.map +1 -0
  29. package/dist/routes/generic.js +106 -0
  30. package/dist/routes/generic.js.map +1 -0
  31. package/dist/routes/nextjs.d.ts +14 -0
  32. package/dist/routes/nextjs.d.ts.map +1 -0
  33. package/dist/routes/nextjs.js +196 -0
  34. package/dist/routes/nextjs.js.map +1 -0
  35. package/dist/routes.d.ts +21 -0
  36. package/dist/routes.d.ts.map +1 -0
  37. package/dist/routes.js +174 -0
  38. package/dist/routes.js.map +1 -0
  39. package/dist/types.d.ts +98 -0
  40. package/dist/types.d.ts.map +1 -0
  41. package/dist/types.js +9 -0
  42. package/dist/types.js.map +1 -0
  43. package/dist/upload.d.ts +35 -0
  44. package/dist/upload.d.ts.map +1 -0
  45. package/dist/upload.js +116 -0
  46. package/dist/upload.js.map +1 -0
  47. package/dist/viewport.d.ts +3 -0
  48. package/dist/viewport.d.ts.map +1 -0
  49. package/dist/viewport.js +11 -0
  50. package/dist/viewport.js.map +1 -0
  51. package/package.json +66 -0
  52. package/skill/SKILL.md +246 -0
  53. package/skill/scripts/adapters/0x0st.sh +36 -0
  54. package/skill/scripts/adapters/blob.sh +55 -0
  55. package/skill/scripts/adapters/gist.sh +59 -0
  56. package/skill/scripts/adapters/git-native.sh +75 -0
  57. package/skill/scripts/upload-and-copy.sh +183 -0
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Next.js route detection from changed files.
3
+ * Supports App Router and Pages Router conventions.
4
+ */
5
+ /** Files that should be skipped entirely (no visual output) */
6
+ const SKIP_PATTERNS = [
7
+ /^app\/api\//,
8
+ /^pages\/api\//,
9
+ /^middleware\.(ts|js|mjs)$/,
10
+ /^next\.config\.(ts|js|mjs)$/,
11
+ /^next-env\.d\.ts$/,
12
+ /\.(test|spec)\.(ts|tsx|js|jsx)$/,
13
+ /^__tests__\//,
14
+ ];
15
+ /** Global files that affect all pages — map to "/" */
16
+ const GLOBAL_PATTERNS = [
17
+ /^(app\/)?globals?\.css$/,
18
+ /^(app\/)?global\.(scss|less)$/,
19
+ /^tailwind\.config\.(ts|js|mjs|cjs)$/,
20
+ /^postcss\.config\.(ts|js|mjs|cjs)$/,
21
+ /^(app\/)?theme\.(ts|js)$/,
22
+ ];
23
+ /** Config files with no visual impact */
24
+ const CONFIG_PATTERNS = [
25
+ /^package\.json$/,
26
+ /^tsconfig.*\.json$/,
27
+ /^\.eslintrc/,
28
+ /^\.prettierrc/,
29
+ /^pnpm-lock\.yaml$/,
30
+ /^yarn\.lock$/,
31
+ /^package-lock\.json$/,
32
+ ];
33
+ /**
34
+ * Detect routes from changed files in a Next.js App Router project.
35
+ */
36
+ export function detectAppRouterRoutes(files) {
37
+ const routes = [];
38
+ for (const file of files) {
39
+ // Skip non-visual files
40
+ if (SKIP_PATTERNS.some(p => p.test(file)))
41
+ continue;
42
+ if (CONFIG_PATTERNS.some(p => p.test(file)))
43
+ continue;
44
+ // Global files → "/"
45
+ if (GLOBAL_PATTERNS.some(p => p.test(file))) {
46
+ routes.push({
47
+ path: '/',
48
+ sourceFile: file,
49
+ confidence: 'low',
50
+ reason: 'Global style file affects all pages',
51
+ });
52
+ continue;
53
+ }
54
+ // App Router: app/**/page.tsx → route
55
+ const pageMatch = file.match(/^app\/(.+\/)?page\.(tsx|ts|jsx|js)$/);
56
+ if (pageMatch) {
57
+ const routePath = buildRoutePath(pageMatch[1] || '');
58
+ routes.push({
59
+ path: routePath,
60
+ sourceFile: file,
61
+ confidence: 'high',
62
+ reason: 'Direct page file change',
63
+ });
64
+ continue;
65
+ }
66
+ // App Router: app/**/layout.tsx → route from directory
67
+ const layoutMatch = file.match(/^app\/(.+\/)?layout\.(tsx|ts|jsx|js)$/);
68
+ if (layoutMatch) {
69
+ const routePath = buildRoutePath(layoutMatch[1] || '');
70
+ routes.push({
71
+ path: routePath,
72
+ sourceFile: file,
73
+ confidence: 'medium',
74
+ reason: 'Layout file change affects route and children',
75
+ });
76
+ continue;
77
+ }
78
+ // App Router: app/**/loading.tsx, error.tsx, not-found.tsx → route from directory
79
+ const specialMatch = file.match(/^app\/(.+\/)?(loading|error|not-found|template)\.(tsx|ts|jsx|js)$/);
80
+ if (specialMatch) {
81
+ const routePath = buildRoutePath(specialMatch[1] || '');
82
+ routes.push({
83
+ path: routePath,
84
+ sourceFile: file,
85
+ confidence: 'medium',
86
+ reason: `${specialMatch[2]} file change`,
87
+ });
88
+ continue;
89
+ }
90
+ // App Router: components/files inside app/ → infer parent route
91
+ const appComponentMatch = file.match(/^app\/(.+\/)?(?:components?|ui|lib|hooks|utils)\/.+\.(tsx|ts|jsx|js)$/);
92
+ if (appComponentMatch) {
93
+ const routePath = buildRoutePath(appComponentMatch[1] || '');
94
+ routes.push({
95
+ path: routePath,
96
+ sourceFile: file,
97
+ confidence: 'medium',
98
+ reason: 'Component in app directory — parent route may be affected',
99
+ });
100
+ continue;
101
+ }
102
+ // Any other file inside app/ that isn't caught above
103
+ const appFileMatch = file.match(/^app\/(.+\/)?[^/]+\.(tsx|ts|jsx|js|css|scss)$/);
104
+ if (appFileMatch) {
105
+ const routePath = buildRoutePath(appFileMatch[1] || '');
106
+ routes.push({
107
+ path: routePath,
108
+ sourceFile: file,
109
+ confidence: 'low',
110
+ reason: 'File in app directory — may affect route',
111
+ });
112
+ continue;
113
+ }
114
+ }
115
+ return routes;
116
+ }
117
+ /**
118
+ * Detect routes from changed files in a Next.js Pages Router project.
119
+ */
120
+ export function detectPagesRouterRoutes(files) {
121
+ const routes = [];
122
+ for (const file of files) {
123
+ if (SKIP_PATTERNS.some(p => p.test(file)))
124
+ continue;
125
+ if (CONFIG_PATTERNS.some(p => p.test(file)))
126
+ continue;
127
+ if (GLOBAL_PATTERNS.some(p => p.test(file))) {
128
+ routes.push({
129
+ path: '/',
130
+ sourceFile: file,
131
+ confidence: 'low',
132
+ reason: 'Global style file affects all pages',
133
+ });
134
+ continue;
135
+ }
136
+ // Pages Router: _app.tsx, _document.tsx → / (must be checked before general page match)
137
+ const specialMatch = file.match(/^pages\/_(?:app|document)\.(tsx|ts|jsx|js)$/);
138
+ if (specialMatch) {
139
+ routes.push({
140
+ path: '/',
141
+ sourceFile: file,
142
+ confidence: 'medium',
143
+ reason: 'App wrapper change affects all pages',
144
+ });
145
+ continue;
146
+ }
147
+ // Pages Router: pages/index.tsx → /
148
+ const indexMatch = file.match(/^pages\/index\.(tsx|ts|jsx|js)$/);
149
+ if (indexMatch) {
150
+ routes.push({
151
+ path: '/',
152
+ sourceFile: file,
153
+ confidence: 'high',
154
+ reason: 'Index page change',
155
+ });
156
+ continue;
157
+ }
158
+ // Pages Router: pages/about.tsx → /about
159
+ const pageMatch = file.match(/^pages\/(.+)\.(tsx|ts|jsx|js)$/);
160
+ if (pageMatch) {
161
+ const routePath = '/' + pageMatch[1].replace(/\/index$/, '');
162
+ routes.push({
163
+ path: routePath,
164
+ sourceFile: file,
165
+ confidence: 'high',
166
+ reason: 'Direct page file change',
167
+ });
168
+ continue;
169
+ }
170
+ }
171
+ return routes;
172
+ }
173
+ /**
174
+ * Build a route path from an App Router directory path.
175
+ * Strips route groups like (marketing), preserves dynamic segments like [slug].
176
+ */
177
+ function buildRoutePath(dirPath) {
178
+ if (!dirPath || dirPath === '/')
179
+ return '/';
180
+ const segments = dirPath
181
+ .replace(/\/$/, '') // Remove trailing slash
182
+ .split('/')
183
+ .filter(seg => {
184
+ // Strip route groups: (marketing), (auth), etc.
185
+ if (/^\(.+\)$/.test(seg))
186
+ return false;
187
+ // Strip @parallel slots
188
+ if (seg.startsWith('@'))
189
+ return false;
190
+ return seg.length > 0;
191
+ });
192
+ if (segments.length === 0)
193
+ return '/';
194
+ return '/' + segments.join('/');
195
+ }
196
+ //# sourceMappingURL=nextjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nextjs.js","sourceRoot":"","sources":["../../src/routes/nextjs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Route detection from git diff output.
3
+ * Maps changed files to affected UI routes.
4
+ */
5
+ import { DetectedRoute, RouteDetectionOptions } from './types.js';
6
+ export type Framework = 'nextjs-app' | 'nextjs-pages' | 'generic';
7
+ /**
8
+ * Get changed files from git diff.
9
+ * Returns paths relative to the repo root.
10
+ */
11
+ export declare function getChangedFiles(diffTarget?: string, cwd?: string): string[];
12
+ /**
13
+ * Auto-detect the framework used in the project.
14
+ */
15
+ export declare function detectFramework(rootDir?: string): Framework;
16
+ /**
17
+ * Detect routes affected by changed files.
18
+ * Main entry point for route detection.
19
+ */
20
+ export declare function detectRoutes(changedFiles: string[], options?: RouteDetectionOptions): DetectedRoute[];
21
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAIlE,MAAM,MAAM,SAAS,GAAG,YAAY,GAAG,cAAc,GAAG,SAAS,CAAC;AAYlE;;;GAGG;AACH,wBAAgB,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,SAAgB,GAAG,MAAM,EAAE,CAUlF;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAa3D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EAAE,EACtB,OAAO,GAAE,qBAA0B,GAClC,aAAa,EAAE,CAoCjB"}
package/dist/routes.js ADDED
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Route detection from git diff output.
3
+ * Maps changed files to affected UI routes.
4
+ */
5
+ import { execSync } from 'child_process';
6
+ import fs from 'fs';
7
+ import path from 'path';
8
+ import { detectAppRouterRoutes, detectPagesRouterRoutes } from './routes/nextjs.js';
9
+ import { detectGenericRoutes } from './routes/generic.js';
10
+ const FRAMEWORK_SCAN_DEPTH = 2;
11
+ const SKIP_SCAN_DIRS = new Set([
12
+ '.git',
13
+ '.next',
14
+ '.turbo',
15
+ 'node_modules',
16
+ 'dist',
17
+ 'build',
18
+ 'coverage',
19
+ ]);
20
+ /**
21
+ * Get changed files from git diff.
22
+ * Returns paths relative to the repo root.
23
+ */
24
+ export function getChangedFiles(diffTarget, cwd = process.cwd()) {
25
+ const target = diffTarget || 'HEAD';
26
+ const files = new Set();
27
+ runGitNameOnly(`diff --name-only ${target}`, cwd).forEach((file) => files.add(file));
28
+ runGitNameOnly('diff --name-only --cached', cwd).forEach((file) => files.add(file));
29
+ runGitNameOnly('diff --name-only', cwd).forEach((file) => files.add(file));
30
+ runGitNameOnly('ls-files --others --exclude-standard', cwd).forEach((file) => files.add(file));
31
+ return Array.from(files);
32
+ }
33
+ /**
34
+ * Auto-detect the framework used in the project.
35
+ */
36
+ export function detectFramework(rootDir) {
37
+ const dir = rootDir || process.cwd();
38
+ const candidateRoots = collectCandidateRoots(dir, FRAMEWORK_SCAN_DEPTH);
39
+ for (const root of candidateRoots) {
40
+ if (hasNextAppRouter(root))
41
+ return 'nextjs-app';
42
+ }
43
+ for (const root of candidateRoots) {
44
+ if (hasNextPagesRouter(root))
45
+ return 'nextjs-pages';
46
+ }
47
+ return 'generic';
48
+ }
49
+ /**
50
+ * Detect routes affected by changed files.
51
+ * Main entry point for route detection.
52
+ */
53
+ export function detectRoutes(changedFiles, options = {}) {
54
+ if (changedFiles.length === 0)
55
+ return [];
56
+ const framework = options.framework || detectFramework();
57
+ let routes;
58
+ switch (framework) {
59
+ case 'nextjs-app':
60
+ routes = detectAppRouterRoutes(changedFiles);
61
+ break;
62
+ case 'nextjs-pages':
63
+ routes = detectPagesRouterRoutes(changedFiles);
64
+ break;
65
+ case 'generic':
66
+ default:
67
+ routes = detectGenericRoutes(changedFiles);
68
+ break;
69
+ }
70
+ // Deduplicate by path — keep highest confidence
71
+ routes = deduplicateRoutes(routes);
72
+ // Sort by confidence (high → medium → low)
73
+ const confidenceOrder = { high: 0, medium: 1, low: 2 };
74
+ routes.sort((a, b) => confidenceOrder[a.confidence] - confidenceOrder[b.confidence]);
75
+ // Cap at maxRoutes
76
+ const maxRoutes = options.maxRoutes ?? 5;
77
+ if (routes.length > maxRoutes) {
78
+ const originalCount = routes.length;
79
+ routes = routes.slice(0, maxRoutes);
80
+ // Add a note about truncation by keeping only the top N
81
+ console.warn(`Detected ${originalCount} routes, capping at ${maxRoutes}. Use --max-routes to increase.`);
82
+ }
83
+ return routes;
84
+ }
85
+ /**
86
+ * Deduplicate routes by path, keeping the highest confidence entry.
87
+ */
88
+ function deduplicateRoutes(routes) {
89
+ const byPath = new Map();
90
+ const confidenceOrder = { high: 0, medium: 1, low: 2 };
91
+ for (const route of routes) {
92
+ const existing = byPath.get(route.path);
93
+ if (!existing || confidenceOrder[route.confidence] < confidenceOrder[existing.confidence]) {
94
+ byPath.set(route.path, route);
95
+ }
96
+ }
97
+ return Array.from(byPath.values());
98
+ }
99
+ function runGitNameOnly(command, cwd) {
100
+ try {
101
+ const output = execSync(`git ${command}`, {
102
+ encoding: 'utf-8',
103
+ stdio: ['pipe', 'pipe', 'pipe'],
104
+ cwd,
105
+ }).trim();
106
+ return output ? output.split('\n').filter(Boolean) : [];
107
+ }
108
+ catch {
109
+ return [];
110
+ }
111
+ }
112
+ function collectCandidateRoots(baseDir, maxDepth) {
113
+ const roots = [baseDir];
114
+ function walk(dir, depth) {
115
+ if (depth === 0)
116
+ return;
117
+ let entries;
118
+ try {
119
+ entries = fs.readdirSync(dir, { withFileTypes: true });
120
+ }
121
+ catch {
122
+ return;
123
+ }
124
+ for (const entry of entries) {
125
+ if (!entry.isDirectory())
126
+ continue;
127
+ if (SKIP_SCAN_DIRS.has(entry.name))
128
+ continue;
129
+ const child = path.join(dir, entry.name);
130
+ roots.push(child);
131
+ walk(child, depth - 1);
132
+ }
133
+ }
134
+ walk(baseDir, maxDepth);
135
+ return roots;
136
+ }
137
+ function hasNextAppRouter(rootDir) {
138
+ const appDir = path.join(rootDir, 'app');
139
+ if (!fs.existsSync(appDir))
140
+ return false;
141
+ return hasAnyFile(appDir, [
142
+ 'page.tsx',
143
+ 'page.ts',
144
+ 'page.jsx',
145
+ 'page.js',
146
+ 'layout.tsx',
147
+ 'layout.ts',
148
+ 'layout.jsx',
149
+ 'layout.js',
150
+ ]);
151
+ }
152
+ function hasNextPagesRouter(rootDir) {
153
+ const pagesDir = path.join(rootDir, 'pages');
154
+ if (!fs.existsSync(pagesDir))
155
+ return false;
156
+ return hasAnyFile(pagesDir, [
157
+ 'index.tsx',
158
+ 'index.ts',
159
+ 'index.jsx',
160
+ 'index.js',
161
+ '_app.tsx',
162
+ '_app.ts',
163
+ '_app.jsx',
164
+ '_app.js',
165
+ '_document.tsx',
166
+ '_document.ts',
167
+ '_document.jsx',
168
+ '_document.js',
169
+ ]);
170
+ }
171
+ function hasAnyFile(dir, filenames) {
172
+ return filenames.some((filename) => fs.existsSync(path.join(dir, filename)));
173
+ }
174
+ //# sourceMappingURL=routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ export interface ViewportSize {
2
+ width: number;
3
+ height: number;
4
+ }
5
+ export type ViewportPreset = 'desktop' | 'tablet' | 'mobile';
6
+ export type ViewportConfig = ViewportPreset | ViewportSize;
7
+ export declare const VIEWPORT_PRESETS: Record<ViewportPreset, ViewportSize>;
8
+ export interface CaptureOptions {
9
+ /** URL to capture (file://, http://, https://) */
10
+ url: string;
11
+ /** Optional CSS selector - scrolls element into view before capture */
12
+ selector?: string;
13
+ /** Viewport size or preset name */
14
+ viewport?: ViewportConfig;
15
+ /** Capture full scrollable page instead of viewport. Default: false */
16
+ fullPage?: boolean;
17
+ }
18
+ export interface CaptureResult {
19
+ /** Raw PNG image data */
20
+ image: Buffer;
21
+ /** Viewport used for capture */
22
+ viewport: ViewportSize;
23
+ /** URL that was captured */
24
+ url: string;
25
+ /** CSS selector used, if any */
26
+ selector?: string;
27
+ }
28
+ export interface BeforeAfterCaptureOptions {
29
+ before: CaptureOptions | string;
30
+ after: CaptureOptions | string;
31
+ /** Viewport applied to both captures unless overridden individually */
32
+ viewport?: ViewportConfig;
33
+ }
34
+ export interface BeforeAfterCaptureResult {
35
+ before: CaptureResult;
36
+ after: CaptureResult;
37
+ }
38
+ export type ImageInput = string | Buffer;
39
+ export interface FromImagesOptions {
40
+ /** Before image (file path or Buffer) */
41
+ before: ImageInput;
42
+ /** After image (file path or Buffer) */
43
+ after: ImageInput;
44
+ /** Labels for markdown output */
45
+ labels?: {
46
+ before?: string;
47
+ after?: string;
48
+ };
49
+ }
50
+ export interface FromImagesResult {
51
+ /** Markdown table for PR comments */
52
+ markdown: string;
53
+ /** Before image buffer */
54
+ beforeImage: Buffer;
55
+ /** After image buffer */
56
+ afterImage: Buffer;
57
+ }
58
+ export interface BeforeAndAfterOptions {
59
+ /** Default viewport for all operations */
60
+ viewport?: ViewportConfig;
61
+ /** Output directory for saved screenshots */
62
+ outputDir?: string;
63
+ }
64
+ export interface DetectedRoute {
65
+ /** Route path, e.g., "/dashboard" */
66
+ path: string;
67
+ /** Source file that triggered detection, e.g., "app/dashboard/page.tsx" */
68
+ sourceFile: string;
69
+ /** How confident is the detection */
70
+ confidence: 'high' | 'medium' | 'low';
71
+ /** Human-readable reason for detection */
72
+ reason: string;
73
+ }
74
+ export interface RouteDetectionOptions {
75
+ /** Force a specific framework instead of auto-detecting */
76
+ framework?: 'nextjs-app' | 'nextjs-pages' | 'generic';
77
+ /** Maximum number of routes to return (default: 5) */
78
+ maxRoutes?: number;
79
+ /** Git diff target, e.g., "main...HEAD" or "HEAD~1" */
80
+ diffTarget?: string;
81
+ }
82
+ export interface CompareOptions {
83
+ /** Base URL for "before" state (e.g., production URL) */
84
+ beforeBase: string;
85
+ /** Base URL for "after" state (e.g., localhost) */
86
+ afterBase: string;
87
+ /** Routes to capture */
88
+ routes: string[];
89
+ /** Capture at desktop + mobile viewports */
90
+ responsive?: boolean;
91
+ /** Viewport override (used when not in responsive mode) */
92
+ viewport?: ViewportConfig;
93
+ /** Output directory for screenshots */
94
+ output?: string;
95
+ /** Generate markdown output */
96
+ markdown?: boolean;
97
+ }
98
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,9 @@
1
+ // ============================================================
2
+ // Viewport
3
+ // ============================================================
4
+ export const VIEWPORT_PRESETS = {
5
+ desktop: { width: 1280, height: 800 },
6
+ tablet: { width: 768, height: 1024 },
7
+ mobile: { width: 375, height: 812 },
8
+ };
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,WAAW;AACX,+DAA+D;AAW/D,MAAM,CAAC,MAAM,gBAAgB,GAAyC;IACpE,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;IACrC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;IACpC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;CACpC,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Image upload for generating shareable URLs.
3
+ * Default: git-native (commits to .pre-post/ on current branch).
4
+ * Opt-in: 0x0.st, Vercel Blob, generic PUT via --upload-url.
5
+ */
6
+ /**
7
+ * Upload an image and return a public URL.
8
+ * Auto-detects upload method from URL pattern.
9
+ */
10
+ export declare function uploadImage(image: Buffer, filename: string, uploadUrl?: string): Promise<string>;
11
+ /**
12
+ * Write an image to .pre-post/ in the repo root, stage it, and return
13
+ * the raw.githubusercontent.com URL it will resolve to after push.
14
+ */
15
+ export declare function uploadGitNative(image: Buffer, filename: string): string;
16
+ /**
17
+ * Commit and push all staged .pre-post/ screenshots in one batch.
18
+ */
19
+ export declare function commitAndPushScreenshots(): void;
20
+ /**
21
+ * Upload before/after images and return URLs.
22
+ * When uploadUrl is provided, uses the HTTP-based upload path.
23
+ * Otherwise, uses git-native (commit to .pre-post/).
24
+ */
25
+ export declare function uploadBeforeAfter(before: {
26
+ image: Buffer;
27
+ filename: string;
28
+ }, after: {
29
+ image: Buffer;
30
+ filename: string;
31
+ }, uploadUrl?: string): Promise<{
32
+ beforeUrl: string;
33
+ afterUrl: string;
34
+ }>;
35
+ //# sourceMappingURL=upload.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../src/upload.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAA2B,GACrC,OAAO,CAAC,MAAM,CAAC,CAajB;AAuDD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAkBvE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAG/C;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC3C,KAAK,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAC1C,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAgBlD"}