tailprint 0.0.0-stage → 1.0.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 (87) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +160 -2
  3. package/dist/config/env.d.ts +77 -0
  4. package/dist/config/env.js +38 -0
  5. package/dist/config/env.js.map +1 -0
  6. package/dist/config/plans.d.ts +15 -0
  7. package/dist/config/plans.js +104 -0
  8. package/dist/config/plans.js.map +1 -0
  9. package/dist/config/templates.d.ts +10 -0
  10. package/dist/config/templates.js +746 -0
  11. package/dist/config/templates.js.map +1 -0
  12. package/dist/mcp/server.d.ts +10 -0
  13. package/dist/mcp/server.js +897 -0
  14. package/dist/mcp/server.js.map +1 -0
  15. package/dist/mcp/stdio.d.ts +2 -0
  16. package/dist/mcp/stdio.js +27 -0
  17. package/dist/mcp/stdio.js.map +1 -0
  18. package/dist/routes/dashboard.d.ts +2 -0
  19. package/dist/routes/dashboard.js +454 -0
  20. package/dist/routes/dashboard.js.map +1 -0
  21. package/dist/routes/mcp.d.ts +2 -0
  22. package/dist/routes/mcp.js +329 -0
  23. package/dist/routes/mcp.js.map +1 -0
  24. package/dist/routes/render.d.ts +2 -0
  25. package/dist/routes/render.js +444 -0
  26. package/dist/routes/render.js.map +1 -0
  27. package/dist/routes/scrape.d.ts +2 -0
  28. package/dist/routes/scrape.js +132 -0
  29. package/dist/routes/scrape.js.map +1 -0
  30. package/dist/routes/templates.d.ts +2 -0
  31. package/dist/routes/templates.js +2449 -0
  32. package/dist/routes/templates.js.map +1 -0
  33. package/dist/routes/usage.d.ts +31 -0
  34. package/dist/routes/usage.js +73 -0
  35. package/dist/routes/usage.js.map +1 -0
  36. package/dist/routes/webhooks.d.ts +2 -0
  37. package/dist/routes/webhooks.js +227 -0
  38. package/dist/routes/webhooks.js.map +1 -0
  39. package/dist/schemas/render.d.ts +422 -0
  40. package/dist/schemas/render.js +91 -0
  41. package/dist/schemas/render.js.map +1 -0
  42. package/dist/schemas/scrape.d.ts +65 -0
  43. package/dist/schemas/scrape.js +24 -0
  44. package/dist/schemas/scrape.js.map +1 -0
  45. package/dist/server.d.ts +2 -0
  46. package/dist/server.js +206 -0
  47. package/dist/server.js.map +1 -0
  48. package/dist/services/browser.d.ts +21 -0
  49. package/dist/services/browser.js +299 -0
  50. package/dist/services/browser.js.map +1 -0
  51. package/dist/services/carousel.d.ts +43 -0
  52. package/dist/services/carousel.js +300 -0
  53. package/dist/services/carousel.js.map +1 -0
  54. package/dist/services/chart.d.ts +29 -0
  55. package/dist/services/chart.js +129 -0
  56. package/dist/services/chart.js.map +1 -0
  57. package/dist/services/eInvoice.d.ts +62 -0
  58. package/dist/services/eInvoice.js +413 -0
  59. package/dist/services/eInvoice.js.map +1 -0
  60. package/dist/services/email.d.ts +24 -0
  61. package/dist/services/email.js +177 -0
  62. package/dist/services/email.js.map +1 -0
  63. package/dist/services/mockup.d.ts +14 -0
  64. package/dist/services/mockup.js +130 -0
  65. package/dist/services/mockup.js.map +1 -0
  66. package/dist/services/pdfStamper.d.ts +16 -0
  67. package/dist/services/pdfStamper.js +47 -0
  68. package/dist/services/pdfStamper.js.map +1 -0
  69. package/dist/services/qr.d.ts +20 -0
  70. package/dist/services/qr.js +44 -0
  71. package/dist/services/qr.js.map +1 -0
  72. package/dist/services/redis.d.ts +65 -0
  73. package/dist/services/redis.js +318 -0
  74. package/dist/services/redis.js.map +1 -0
  75. package/dist/services/scraper.d.ts +16 -0
  76. package/dist/services/scraper.js +138 -0
  77. package/dist/services/scraper.js.map +1 -0
  78. package/dist/services/storage.d.ts +38 -0
  79. package/dist/services/storage.js +123 -0
  80. package/dist/services/storage.js.map +1 -0
  81. package/dist/services/stripe.d.ts +32 -0
  82. package/dist/services/stripe.js +229 -0
  83. package/dist/services/stripe.js.map +1 -0
  84. package/dist/services/visualDiff.d.ts +33 -0
  85. package/dist/services/visualDiff.js +218 -0
  86. package/dist/services/visualDiff.js.map +1 -0
  87. package/package.json +74 -4
@@ -0,0 +1,33 @@
1
+ export interface CompareSnapshotsParams {
2
+ beforeUrl?: string;
3
+ beforeHtml?: string;
4
+ afterUrl?: string;
5
+ afterHtml?: string;
6
+ beforeImageBase64?: string;
7
+ afterImageBase64?: string;
8
+ width?: number;
9
+ height?: number;
10
+ threshold?: number;
11
+ generateComposite?: boolean;
12
+ delayMs?: number;
13
+ }
14
+ export interface CompareSnapshotsResult {
15
+ differentPixels: number;
16
+ totalPixels: number;
17
+ diffPercentage: number;
18
+ isIdentical: boolean;
19
+ diffImageBuffer: Buffer;
20
+ compositeImageBuffer: Buffer;
21
+ }
22
+ export declare class VisualDiffService {
23
+ private static instance;
24
+ private constructor();
25
+ static getInstance(): VisualDiffService;
26
+ private normalizePng;
27
+ /**
28
+ * Captures or decodes two snapshots, computes a pixel-by-pixel diff,
29
+ * and creates a studio 3-column visual regression inspection canvas.
30
+ */
31
+ compareSnapshots(params: CompareSnapshotsParams): Promise<CompareSnapshotsResult>;
32
+ }
33
+ export declare const visualDiffService: VisualDiffService;
@@ -0,0 +1,218 @@
1
+ import { PNG } from 'pngjs';
2
+ import pixelmatch from 'pixelmatch';
3
+ import { browserService } from './browser.js';
4
+ export class VisualDiffService {
5
+ static instance = null;
6
+ constructor() { }
7
+ static getInstance() {
8
+ if (!VisualDiffService.instance) {
9
+ VisualDiffService.instance = new VisualDiffService();
10
+ }
11
+ return VisualDiffService.instance;
12
+ }
13
+ normalizePng(src, targetWidth, targetHeight) {
14
+ if (src.width === targetWidth && src.height === targetHeight) {
15
+ return src;
16
+ }
17
+ const out = new PNG({ width: targetWidth, height: targetHeight });
18
+ out.data.fill(0); // Initialize transparent buffer
19
+ for (let y = 0; y < src.height && y < targetHeight; y++) {
20
+ for (let x = 0; x < src.width && x < targetWidth; x++) {
21
+ const srcIdx = (y * src.width + x) * 4;
22
+ const outIdx = (y * targetWidth + x) * 4;
23
+ out.data[outIdx] = src.data[srcIdx];
24
+ out.data[outIdx + 1] = src.data[srcIdx + 1];
25
+ out.data[outIdx + 2] = src.data[srcIdx + 2];
26
+ out.data[outIdx + 3] = src.data[srcIdx + 3];
27
+ }
28
+ }
29
+ return out;
30
+ }
31
+ /**
32
+ * Captures or decodes two snapshots, computes a pixel-by-pixel diff,
33
+ * and creates a studio 3-column visual regression inspection canvas.
34
+ */
35
+ async compareSnapshots(params) {
36
+ const width = Math.min(Math.max(params.width || 1200, 320), 2560);
37
+ const height = Math.min(Math.max(params.height || 800, 240), 2560);
38
+ const delayMs = params.delayMs !== undefined ? params.delayMs : 300;
39
+ const threshold = params.threshold !== undefined ? params.threshold : 0.1;
40
+ // 1. Resolve Before Snapshot Buffer
41
+ let beforeBuffer;
42
+ if (params.beforeImageBase64) {
43
+ const clean = params.beforeImageBase64.replace(/^data:image\/[a-z]+;base64,/, '').trim();
44
+ beforeBuffer = Buffer.from(clean, 'base64');
45
+ }
46
+ else if (params.beforeUrl || params.beforeHtml) {
47
+ beforeBuffer = await browserService.renderImage({
48
+ url: params.beforeUrl,
49
+ html: params.beforeHtml,
50
+ width,
51
+ height,
52
+ type: 'png',
53
+ delay_ms: delayMs,
54
+ });
55
+ }
56
+ else {
57
+ throw new Error('Must provide beforeUrl, beforeHtml, or beforeImageBase64');
58
+ }
59
+ // 2. Resolve After Snapshot Buffer
60
+ let afterBuffer;
61
+ if (params.afterImageBase64) {
62
+ const clean = params.afterImageBase64.replace(/^data:image\/[a-z]+;base64,/, '').trim();
63
+ afterBuffer = Buffer.from(clean, 'base64');
64
+ }
65
+ else if (params.afterUrl || params.afterHtml) {
66
+ afterBuffer = await browserService.renderImage({
67
+ url: params.afterUrl,
68
+ html: params.afterHtml,
69
+ width,
70
+ height,
71
+ type: 'png',
72
+ delay_ms: delayMs,
73
+ });
74
+ }
75
+ else {
76
+ throw new Error('Must provide afterUrl, afterHtml, or afterImageBase64');
77
+ }
78
+ // 3. Parse PNGs
79
+ let png1 = PNG.sync.read(beforeBuffer);
80
+ let png2 = PNG.sync.read(afterBuffer);
81
+ const targetWidth = Math.max(png1.width, png2.width);
82
+ const targetHeight = Math.max(png1.height, png2.height);
83
+ png1 = this.normalizePng(png1, targetWidth, targetHeight);
84
+ png2 = this.normalizePng(png2, targetWidth, targetHeight);
85
+ // 4. Compute pixel diff
86
+ const diffPng = new PNG({ width: targetWidth, height: targetHeight });
87
+ const differentPixels = pixelmatch(png1.data, png2.data, diffPng.data, targetWidth, targetHeight, {
88
+ threshold,
89
+ diffColor: [244, 63, 94], // Neon rose/pink #f43f5e for changed pixels
90
+ diffColorAlt: [56, 189, 248], // Sky blue #38bdf8
91
+ alpha: 0.25,
92
+ });
93
+ const totalPixels = targetWidth * targetHeight;
94
+ const diffPercentage = Number(((differentPixels / totalPixels) * 100).toFixed(2));
95
+ const isIdentical = differentPixels === 0;
96
+ const diffImageBuffer = PNG.sync.write(diffPng);
97
+ // 5. Generate 3-Panel Side-by-Side Visual Regression Studio Canvas
98
+ const beforeBase64 = PNG.sync.write(png1).toString('base64');
99
+ const afterBase64 = PNG.sync.write(png2).toString('base64');
100
+ const diffBase64 = diffImageBuffer.toString('base64');
101
+ const badgeColor = isIdentical
102
+ ? 'bg-emerald-500/20 text-emerald-400 border-emerald-500/40'
103
+ : diffPercentage < 1.0
104
+ ? 'bg-amber-500/20 text-amber-400 border-amber-500/40'
105
+ : 'bg-rose-500/20 text-rose-400 border-rose-500/40';
106
+ const badgeText = isIdentical
107
+ ? '✓ IDENTICAL (0% DIFF)'
108
+ : `⚠ ${diffPercentage}% DIFF (${differentPixels.toLocaleString()} PIXELS)`;
109
+ const compositeHtml = `<!DOCTYPE html>
110
+ <html>
111
+ <head>
112
+ <meta charset="utf-8" />
113
+ <script src="https://cdn.tailwindcss.com"></script>
114
+ </head>
115
+ <body class="bg-[#090d16] text-slate-100 p-8 font-sans antialiased m-0">
116
+ <div class="max-w-[1700px] mx-auto">
117
+
118
+ <!-- Top Header -->
119
+ <div class="flex items-center justify-between pb-6 border-b border-slate-800 mb-6">
120
+ <div class="flex items-center space-x-3">
121
+ <span class="text-2xl">🔍</span>
122
+ <div>
123
+ <h1 class="text-xl font-black tracking-tight text-white flex items-center space-x-2">
124
+ <span>Visual Regression Heatmap</span>
125
+ <span class="text-xs font-mono font-normal text-slate-400">(${targetWidth}×${targetHeight}px)</span>
126
+ </h1>
127
+ <p class="text-xs text-slate-400 mt-0.5">Pixelmatch comparison with highlighted layout and color shifts</p>
128
+ </div>
129
+ </div>
130
+ <div class="flex items-center space-x-4">
131
+ <div class="text-right">
132
+ <span class="text-[10px] uppercase font-bold tracking-wider text-slate-400 block">Status</span>
133
+ <span class="inline-block px-3 py-1 rounded-full text-xs font-black border ${badgeColor}">
134
+ ${badgeText}
135
+ </span>
136
+ </div>
137
+ </div>
138
+ </div>
139
+
140
+ <!-- 3-Column Panels -->
141
+ <div class="grid grid-cols-3 gap-6">
142
+
143
+ <!-- Panel 1: Baseline / Before -->
144
+ <div class="rounded-2xl bg-slate-900/90 border border-slate-800 overflow-hidden shadow-xl">
145
+ <div class="px-4 py-2.5 bg-slate-950/80 border-b border-slate-800 flex items-center justify-between text-xs">
146
+ <span class="font-bold text-slate-300 flex items-center space-x-1.5">
147
+ <span class="w-2 h-2 rounded-full bg-slate-400"></span>
148
+ <span>1. Baseline (Before)</span>
149
+ </span>
150
+ <span class="text-[10px] font-mono text-slate-400">Original</span>
151
+ </div>
152
+ <div class="p-3 bg-slate-950/40">
153
+ <img src="data:image/png;base64,${beforeBase64}" class="w-full h-auto rounded-lg shadow-inner object-contain max-h-[700px]" />
154
+ </div>
155
+ </div>
156
+
157
+ <!-- Panel 2: Diff Heatmap -->
158
+ <div class="rounded-2xl bg-slate-900/90 border border-rose-500/40 overflow-hidden shadow-2xl relative ring-1 ring-rose-500/30">
159
+ <div class="px-4 py-2.5 bg-rose-950/40 border-b border-rose-900/40 flex items-center justify-between text-xs">
160
+ <span class="font-bold text-rose-300 flex items-center space-x-1.5">
161
+ <span class="w-2 h-2 rounded-full bg-rose-500 animate-pulse"></span>
162
+ <span>2. Heatmap Diff Overlay</span>
163
+ </span>
164
+ <span class="text-[10px] font-mono text-rose-300 font-bold">${diffPercentage}% Changed</span>
165
+ </div>
166
+ <div class="p-3 bg-slate-950/40">
167
+ <img src="data:image/png;base64,${diffBase64}" class="w-full h-auto rounded-lg shadow-inner object-contain max-h-[700px]" />
168
+ </div>
169
+ </div>
170
+
171
+ <!-- Panel 3: Current / After -->
172
+ <div class="rounded-2xl bg-slate-900/90 border border-slate-800 overflow-hidden shadow-xl">
173
+ <div class="px-4 py-2.5 bg-slate-950/80 border-b border-slate-800 flex items-center justify-between text-xs">
174
+ <span class="font-bold text-indigo-300 flex items-center space-x-1.5">
175
+ <span class="w-2 h-2 rounded-full bg-indigo-400"></span>
176
+ <span>3. Current (After)</span>
177
+ </span>
178
+ <span class="text-[10px] font-mono text-slate-400">Modified</span>
179
+ </div>
180
+ <div class="p-3 bg-slate-950/40">
181
+ <img src="data:image/png;base64,${afterBase64}" class="w-full h-auto rounded-lg shadow-inner object-contain max-h-[700px]" />
182
+ </div>
183
+ </div>
184
+
185
+ </div>
186
+
187
+ <!-- Footer Stats Strip -->
188
+ <div class="mt-6 p-4 rounded-xl bg-slate-950 border border-slate-800/80 flex items-center justify-between text-xs font-mono text-slate-400">
189
+ <div class="flex items-center space-x-6">
190
+ <span>Total Pixels: <strong class="text-white">${totalPixels.toLocaleString()}</strong></span>
191
+ <span>Different Pixels: <strong class="${isIdentical ? 'text-emerald-400' : 'text-rose-400'}">${differentPixels.toLocaleString()}</strong></span>
192
+ <span>Matching Threshold: <strong class="text-white">${threshold}</strong></span>
193
+ </div>
194
+ <div class="text-[11px] text-slate-400">Generated by Tailprint Visual Inspector</div>
195
+ </div>
196
+
197
+ </div>
198
+ </body>
199
+ </html>`;
200
+ const compositeImageBuffer = await browserService.renderImage({
201
+ html: compositeHtml,
202
+ width: 1700,
203
+ height: 980,
204
+ type: 'png',
205
+ delay_ms: 150,
206
+ });
207
+ return {
208
+ differentPixels,
209
+ totalPixels,
210
+ diffPercentage,
211
+ isIdentical,
212
+ diffImageBuffer,
213
+ compositeImageBuffer,
214
+ };
215
+ }
216
+ }
217
+ export const visualDiffService = VisualDiffService.getInstance();
218
+ //# sourceMappingURL=visualDiff.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visualDiff.js","sourceRoot":"","sources":["../../src/services/visualDiff.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,76 @@
1
1
  {
2
2
  "name": "tailprint",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "Tailwind-Native Render & PDF Engine + AI Web Scraper (tailprint.com)",
5
+ "type": "module",
6
+ "main": "dist/server.js",
7
+ "bin": {
8
+ "tailprint": "dist/mcp/stdio.js",
9
+ "tailprint-mcp": "dist/mcp/stdio.js"
10
+ },
11
+ "files": [
12
+ "dist",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/coheroseb/tailprint.git"
19
+ },
20
+ "homepage": "https://tailprint.com",
21
+ "bugs": {
22
+ "url": "https://github.com/coheroseb/tailprint/issues"
23
+ },
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "start": "node dist/server.js",
27
+ "dev": "tsx watch src/server.ts",
28
+ "mcp": "tsx src/mcp/stdio.ts",
29
+ "test": "vitest run"
30
+ },
31
+ "keywords": [
32
+ "fastify",
33
+ "tailwind",
34
+ "pdf",
35
+ "screenshot",
36
+ "eaas",
37
+ "playwright"
38
+ ],
39
+ "author": "",
40
+ "license": "MIT",
41
+ "dependencies": {
42
+ "@fastify/swagger": "^9.4.2",
43
+ "@modelcontextprotocol/sdk": "^1.32.2",
44
+ "@mozilla/readability": "^0.6.0",
45
+ "@scalar/fastify-api-reference": "^1.25.105",
46
+ "@types/pixelmatch": "^5.2.6",
47
+ "@types/pngjs": "^6.0.5",
48
+ "@upstash/redis": "^1.34.4",
49
+ "cryptpdf": "^0.1.1",
50
+ "dotenv": "^16.4.7",
51
+ "fastify": "^5.2.1",
52
+ "fastify-raw-body": "^5.0.0",
53
+ "fastify-type-provider-zod": "^4.0.2",
54
+ "jsdom": "^29.1.1",
55
+ "nodemailer": "^10.5.0",
56
+ "p-limit": "^6.2.0",
57
+ "pdf-lib": "^1.17.1",
58
+ "pixelmatch": "^8.0.0",
59
+ "playwright": "^1.50.1",
60
+ "qrcode": "^1.5.4",
61
+ "stripe": "^17.7.0",
62
+ "turndown": "^7.2.5",
63
+ "turndown-plugin-gfm": "^1.0.2",
64
+ "zod": "^3.24.2"
65
+ },
66
+ "devDependencies": {
67
+ "@types/jsdom": "^30.0.0",
68
+ "@types/node": "^22.13.5",
69
+ "@types/nodemailer": "^8.0.2",
70
+ "@types/qrcode": "^1.5.6",
71
+ "@types/turndown": "^5.0.6",
72
+ "tsx": "^4.19.3",
73
+ "typescript": "^5.7.3",
74
+ "vitest": "^3.0.6"
75
+ }
76
+ }