loopwind 0.9.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.
- package/FONTS.md +156 -0
- package/HELPERS_DEMO.md +134 -0
- package/PROJECT_STRUCTURE.md +286 -0
- package/PUBLISHING.md +171 -0
- package/README.md +1020 -0
- package/REGISTRY_SETUP.md +427 -0
- package/SHADCN_INTEGRATION.md +269 -0
- package/TAILWIND.md +228 -0
- package/TEMPLATE_SOURCES.md +363 -0
- package/_dsgn/templates/banner-hero/banner-hero.tsx +57 -0
- package/_dsgn/templates/banner-hero/meta.json +14 -0
- package/_dsgn/templates/composite-card/meta.json +16 -0
- package/_dsgn/templates/composite-card/template.tsx +44 -0
- package/_dsgn/templates/image/meta.json +13 -0
- package/_dsgn/templates/image/template.tsx +28 -0
- package/_dsgn/templates/kitchen-sink/meta.json +13 -0
- package/_dsgn/templates/kitchen-sink/template.tsx +72 -0
- package/_dsgn/templates/qr-card/meta.json +14 -0
- package/_dsgn/templates/qr-card/template.tsx +39 -0
- package/_dsgn/templates/test-parent/child/meta.json +11 -0
- package/_dsgn/templates/test-parent/child/template.tsx +27 -0
- package/_dsgn/templates/test-parent/meta.json +12 -0
- package/_dsgn/templates/test-parent/template.tsx +30 -0
- package/_dsgn/templates/test-sibling/meta.json +11 -0
- package/_dsgn/templates/test-sibling/template.tsx +20 -0
- package/_dsgn/templates/video/.tmp/template-1763421345296.mjs +43 -0
- package/_dsgn/templates/video/.tmp/template-1763421362228.mjs +43 -0
- package/_dsgn/templates/video/.tmp/template-1763421377706.mjs +43 -0
- package/_dsgn/templates/video/meta.json +17 -0
- package/_dsgn/templates/video/template.tsx +48 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +70 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/add.d.ts +6 -0
- package/dist/commands/add.d.ts.map +1 -0
- package/dist/commands/add.js +86 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/default.d.ts +2 -0
- package/dist/commands/default.d.ts.map +1 -0
- package/dist/commands/default.js +69 -0
- package/dist/commands/default.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +75 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.d.ts +2 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +83 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/preview.d.ts +3 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +296 -0
- package/dist/commands/preview.js.map +1 -0
- package/dist/commands/render.d.ts +10 -0
- package/dist/commands/render.d.ts.map +1 -0
- package/dist/commands/render.js +204 -0
- package/dist/commands/render.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +107 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/default-templates/AGENTS.md +229 -0
- package/dist/default-templates/image/meta.json +13 -0
- package/dist/default-templates/image/template.d.ts +20 -0
- package/dist/default-templates/image/template.d.ts.map +1 -0
- package/dist/default-templates/image/template.js +18 -0
- package/dist/default-templates/image/template.js.map +1 -0
- package/dist/default-templates/image/template.tsx +20 -0
- package/dist/default-templates/image-template/meta.json +13 -0
- package/dist/default-templates/image-template/template.tsx +19 -0
- package/dist/default-templates/kitchen-sink/meta.json +13 -0
- package/dist/default-templates/kitchen-sink/template.tsx +64 -0
- package/dist/default-templates/page/meta.json +17 -0
- package/dist/default-templates/page/template.tsx +37 -0
- package/dist/default-templates/video/meta.json +17 -0
- package/dist/default-templates/video/template.d.ts +26 -0
- package/dist/default-templates/video/template.d.ts.map +1 -0
- package/dist/default-templates/video/template.js +33 -0
- package/dist/default-templates/video/template.js.map +1 -0
- package/dist/default-templates/video/template.tsx +37 -0
- package/dist/default-templates/video-template/meta.json +17 -0
- package/dist/default-templates/video-template/template.tsx +36 -0
- package/dist/default-templates/website/meta.json +16 -0
- package/dist/default-templates/website/pages/home.tsx +17 -0
- package/dist/default-templates/website/parts/footer.tsx +17 -0
- package/dist/default-templates/website/parts/header.tsx +17 -0
- package/dist/default-templates/website/template.tsx +17 -0
- package/dist/default-templates/website-template/meta.json +16 -0
- package/dist/default-templates/website-template/pages/home.tsx +16 -0
- package/dist/default-templates/website-template/parts/footer.tsx +16 -0
- package/dist/default-templates/website-template/parts/header.tsx +16 -0
- package/dist/default-templates/website-template/template.tsx +16 -0
- package/dist/lib/config.d.ts +34 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +248 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/constants.d.ts +7 -0
- package/dist/lib/constants.d.ts.map +1 -0
- package/dist/lib/constants.js +12 -0
- package/dist/lib/constants.js.map +1 -0
- package/dist/lib/helpers.d.ts +29 -0
- package/dist/lib/helpers.d.ts.map +1 -0
- package/dist/lib/helpers.js +159 -0
- package/dist/lib/helpers.js.map +1 -0
- package/dist/lib/installer.d.ts +51 -0
- package/dist/lib/installer.d.ts.map +1 -0
- package/dist/lib/installer.js +215 -0
- package/dist/lib/installer.js.map +1 -0
- package/dist/lib/renderer.d.ts +51 -0
- package/dist/lib/renderer.d.ts.map +1 -0
- package/dist/lib/renderer.js +524 -0
- package/dist/lib/renderer.js.map +1 -0
- package/dist/lib/tailwind-config-loader.d.ts +47 -0
- package/dist/lib/tailwind-config-loader.d.ts.map +1 -0
- package/dist/lib/tailwind-config-loader.js +432 -0
- package/dist/lib/tailwind-config-loader.js.map +1 -0
- package/dist/lib/tailwind-detector.d.ts +36 -0
- package/dist/lib/tailwind-detector.d.ts.map +1 -0
- package/dist/lib/tailwind-detector.js +156 -0
- package/dist/lib/tailwind-detector.js.map +1 -0
- package/dist/lib/tailwind.d.ts +8 -0
- package/dist/lib/tailwind.d.ts.map +1 -0
- package/dist/lib/tailwind.js +994 -0
- package/dist/lib/tailwind.js.map +1 -0
- package/dist/lib/template-validator.d.ts +22 -0
- package/dist/lib/template-validator.d.ts.map +1 -0
- package/dist/lib/template-validator.js +174 -0
- package/dist/lib/template-validator.js.map +1 -0
- package/dist/lib/utils.d.ts +44 -0
- package/dist/lib/utils.d.ts.map +1 -0
- package/dist/lib/utils.js +207 -0
- package/dist/lib/utils.js.map +1 -0
- package/dist/lib/version-check.d.ts +16 -0
- package/dist/lib/version-check.d.ts.map +1 -0
- package/dist/lib/version-check.js +88 -0
- package/dist/lib/version-check.js.map +1 -0
- package/dist/lib/video-renderer.d.ts +32 -0
- package/dist/lib/video-renderer.d.ts.map +1 -0
- package/dist/lib/video-renderer.js +226 -0
- package/dist/lib/video-renderer.js.map +1 -0
- package/dist/sdk/index.d.ts +58 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +119 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/template.d.ts +40 -0
- package/dist/sdk/template.d.ts.map +1 -0
- package/dist/sdk/template.js +60 -0
- package/dist/sdk/template.js.map +1 -0
- package/dist/types/config.d.ts +62 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +47 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/template.d.ts +79 -0
- package/dist/types/template.d.ts.map +1 -0
- package/dist/types/template.js +2 -0
- package/dist/types/template.js.map +1 -0
- package/examples/nextjs-api/README.md +180 -0
- package/examples/nextjs-api/package.json +21 -0
- package/examples/nextjs-api/pages/api/intro-video.ts +53 -0
- package/examples/nextjs-api/pages/api/og-image.ts +50 -0
- package/netlify.toml +13 -0
- package/package.json +84 -0
- package/patches/satori+0.18.3.patch +13 -0
- package/test-templates/TESTS.md +63 -0
- package/test-templates/_dsgn/templates/absolute-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/absolute-spin/template.tsx +16 -0
- package/test-templates/_dsgn/templates/animated-intro/.tmp/template-1763468771640.mjs +7 -0
- package/test-templates/_dsgn/templates/animated-intro/meta.json +10 -0
- package/test-templates/_dsgn/templates/animated-intro/template.tsx +23 -0
- package/test-templates/_dsgn/templates/centered-spin/.tmp/template-1763468525386.mjs +7 -0
- package/test-templates/_dsgn/templates/centered-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/centered-spin/template.tsx +11 -0
- package/test-templates/_dsgn/templates/composite/.tmp/template-1763468815645.mjs +7 -0
- package/test-templates/_dsgn/templates/composite/meta.json +9 -0
- package/test-templates/_dsgn/templates/composite/template.tsx +23 -0
- package/test-templates/_dsgn/templates/easing-test/.tmp/template-1763468824501.mjs +7 -0
- package/test-templates/_dsgn/templates/easing-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/easing-test/template.tsx +47 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466364336.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466584319.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466667797.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466746504.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763466930225.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467004552.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467060334.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467124493.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467174690.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467359134.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467451928.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467758275.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763467985201.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468020563.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468090428.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468211036.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/.tmp/template-1763468394057.mjs +10 -0
- package/test-templates/_dsgn/templates/minimal-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/minimal-spin/template.tsx +13 -0
- package/test-templates/_dsgn/templates/no-origin-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/no-origin-spin/template.tsx +10 -0
- package/test-templates/_dsgn/templates/opacity-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/opacity-test/template.tsx +9 -0
- package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468758954.mjs +17 -0
- package/test-templates/_dsgn/templates/qr-code/.tmp/template-1763468815672.mjs +17 -0
- package/test-templates/_dsgn/templates/qr-code/meta.json +9 -0
- package/test-templates/_dsgn/templates/qr-code/template.tsx +20 -0
- package/test-templates/_dsgn/templates/rotation-abs-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/rotation-abs-test/template.tsx +15 -0
- package/test-templates/_dsgn/templates/rotation-corner/meta.json +7 -0
- package/test-templates/_dsgn/templates/rotation-corner/template.tsx +12 -0
- package/test-templates/_dsgn/templates/rotation-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/rotation-test/template.tsx +12 -0
- package/test-templates/_dsgn/templates/shake-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/shake-test/template.tsx +12 -0
- package/test-templates/_dsgn/templates/static-image/.tmp/template-1763468746271.mjs +7 -0
- package/test-templates/_dsgn/templates/static-image/meta.json +9 -0
- package/test-templates/_dsgn/templates/static-image/template.tsx +19 -0
- package/test-templates/_dsgn/templates/translate-test/meta.json +7 -0
- package/test-templates/_dsgn/templates/translate-test/template.tsx +9 -0
- package/test-templates/_dsgn/templates/video-loops/.tmp/template-1763468793192.mjs +15 -0
- package/test-templates/_dsgn/templates/video-loops/meta.json +9 -0
- package/test-templates/_dsgn/templates/video-loops/template.tsx +39 -0
- package/test-templates/_dsgn/templates/wrapped-spin/meta.json +7 -0
- package/test-templates/_dsgn/templates/wrapped-spin/template.tsx +17 -0
- package/test-templates/compare-svgs.mjs +30 -0
- package/test-templates/convert-frames.mjs +15 -0
- package/test-templates/debug-rotation.mjs +25 -0
- package/test-templates/run-tests.sh +39 -0
- package/test-templates/test-sdk.mjs +115 -0
- package/website/.astro/settings.json +5 -0
- package/website/.astro/types.d.ts +1 -0
- package/website/README.md +112 -0
- package/website/astro.config.mjs +18 -0
- package/website/dist/_astro/fonts.DHdiHGBO.css +1 -0
- package/website/dist/fonts/index.html +193 -0
- package/website/dist/helpers/index.html +166 -0
- package/website/dist/images/index.html +314 -0
- package/website/dist/index.html +219 -0
- package/website/dist/llm.txt +2448 -0
- package/website/dist/styling/index.html +365 -0
- package/website/dist/templates/index.html +124 -0
- package/website/dist/video/index.html +636 -0
- package/website/package-lock.json +7606 -0
- package/website/package.json +23 -0
- package/website/public/robots.txt +5 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
import satori from 'satori';
|
|
2
|
+
import { Resvg } from '@resvg/resvg-js';
|
|
3
|
+
import fs from 'fs/promises';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { pathToFileURL, fileURLToPath } from 'url';
|
|
6
|
+
import { build } from 'esbuild';
|
|
7
|
+
import sharp from 'sharp';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import { getTemplatePathAsync, loadTemplateMeta } from './utils.js';
|
|
10
|
+
import { loadConfig } from './config.js';
|
|
11
|
+
import { tw } from './tailwind.js';
|
|
12
|
+
import { loadTailwindConfig } from './tailwind-config-loader.js';
|
|
13
|
+
import { qr, image, extractVideoFramesForCache } from './helpers.js';
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
/**
|
|
17
|
+
* Template cache to avoid re-transpiling the same template
|
|
18
|
+
* Key: template path, Value: loaded module and path
|
|
19
|
+
*/
|
|
20
|
+
const templateCache = new Map();
|
|
21
|
+
/**
|
|
22
|
+
* Loading promises to prevent cache stampede during parallel video frame rendering
|
|
23
|
+
* Key: cache key, Value: loading promise
|
|
24
|
+
*/
|
|
25
|
+
const loadingPromises = new Map();
|
|
26
|
+
/**
|
|
27
|
+
* Load a template module dynamically
|
|
28
|
+
* Transpiles TSX to JS on-the-fly using esbuild
|
|
29
|
+
* @param templateName - Template name or relative path
|
|
30
|
+
* @param relativeTo - Optional path to resolve relative paths against
|
|
31
|
+
* @returns The loaded template module and its resolved path
|
|
32
|
+
*/
|
|
33
|
+
export async function loadTemplate(templateName, relativeTo) {
|
|
34
|
+
// Check cache first
|
|
35
|
+
const cacheKey = relativeTo ? `${templateName}::${relativeTo}` : templateName;
|
|
36
|
+
if (templateCache.has(cacheKey)) {
|
|
37
|
+
return templateCache.get(cacheKey);
|
|
38
|
+
}
|
|
39
|
+
// Check if already loading (prevents cache stampede during parallel video rendering)
|
|
40
|
+
if (loadingPromises.has(cacheKey)) {
|
|
41
|
+
return loadingPromises.get(cacheKey);
|
|
42
|
+
}
|
|
43
|
+
// Create loading promise
|
|
44
|
+
const loadingPromise = (async () => {
|
|
45
|
+
const templatePath = await getTemplatePathAsync(templateName, relativeTo);
|
|
46
|
+
// Create a temporary output file
|
|
47
|
+
const tmpDir = path.join(path.dirname(templatePath), '.tmp');
|
|
48
|
+
const baseName = path.basename(templatePath, '.tsx');
|
|
49
|
+
const tmpFile = path.join(tmpDir, `${baseName}-${Date.now()}.mjs`);
|
|
50
|
+
try {
|
|
51
|
+
// Ensure tmp directory exists
|
|
52
|
+
await fs.mkdir(tmpDir, { recursive: true });
|
|
53
|
+
// Transpile TSX to JS using esbuild
|
|
54
|
+
await build({
|
|
55
|
+
entryPoints: [templatePath],
|
|
56
|
+
bundle: false, // Don't bundle - just transpile
|
|
57
|
+
format: 'esm',
|
|
58
|
+
outfile: tmpFile,
|
|
59
|
+
jsx: 'automatic', // Use automatic JSX runtime
|
|
60
|
+
jsxImportSource: 'react',
|
|
61
|
+
platform: 'node',
|
|
62
|
+
target: 'node18',
|
|
63
|
+
});
|
|
64
|
+
// Read the transpiled file and inject React at runtime
|
|
65
|
+
let code = await fs.readFile(tmpFile, 'utf-8');
|
|
66
|
+
// Replace react imports with dynamically resolved imports
|
|
67
|
+
const reactPath = await import.meta.resolve('react');
|
|
68
|
+
const jsxRuntimePath = await import.meta.resolve('react/jsx-runtime');
|
|
69
|
+
code = code.replace(/from\s+["']react["']/g, `from "${reactPath}"`);
|
|
70
|
+
code = code.replace(/from\s+["']react\/jsx-runtime["']/g, `from "${jsxRuntimePath}"`);
|
|
71
|
+
// If React.createElement is used but React is not imported, inject it
|
|
72
|
+
if (code.includes('React.createElement') && !code.includes('import') && !code.includes('from')) {
|
|
73
|
+
code = `import * as React from "${reactPath}";\n` + code;
|
|
74
|
+
}
|
|
75
|
+
// Write back the modified code
|
|
76
|
+
await fs.writeFile(tmpFile, code);
|
|
77
|
+
// Import the transpiled file
|
|
78
|
+
const fileUrl = pathToFileURL(tmpFile).href;
|
|
79
|
+
const module = await import(fileUrl + '?t=' + Date.now()); // Cache busting
|
|
80
|
+
const result = { module, templatePath };
|
|
81
|
+
// Cache the result for reuse (especially important for video rendering)
|
|
82
|
+
templateCache.set(cacheKey, result);
|
|
83
|
+
// Don't clean up - we need the transpiled files for the cache
|
|
84
|
+
// They'll be cleaned up when the process exits or can be manually removed from .tmp directories
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
})();
|
|
91
|
+
// Store the loading promise
|
|
92
|
+
loadingPromises.set(cacheKey, loadingPromise);
|
|
93
|
+
try {
|
|
94
|
+
const result = await loadingPromise;
|
|
95
|
+
return result;
|
|
96
|
+
}
|
|
97
|
+
finally {
|
|
98
|
+
// Clean up loading promise after completion
|
|
99
|
+
loadingPromises.delete(cacheKey);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Render a template to SVG using Satori
|
|
104
|
+
*/
|
|
105
|
+
export async function renderToSVG(templateName, props = {}) {
|
|
106
|
+
// Load template and config
|
|
107
|
+
const { module: template, templatePath: currentTemplatePath } = await loadTemplate(templateName);
|
|
108
|
+
const meta = await loadTemplateMeta(templateName);
|
|
109
|
+
const dsgnConfig = await loadConfig();
|
|
110
|
+
const tailwindConfig = await loadTailwindConfig();
|
|
111
|
+
// Get the component
|
|
112
|
+
const Component = template.default;
|
|
113
|
+
if (!Component) {
|
|
114
|
+
throw new Error(`Template ${templateName} does not export a default component`);
|
|
115
|
+
}
|
|
116
|
+
// Pre-generate QR codes for caching
|
|
117
|
+
// This allows templates to use qr() synchronously
|
|
118
|
+
const qrCache = new Map();
|
|
119
|
+
const qrHelper = (text, options) => {
|
|
120
|
+
// Check cache first - use just text as key since options are presentation-only
|
|
121
|
+
// The QR code data is the same regardless of styling options
|
|
122
|
+
if (qrCache.has(text)) {
|
|
123
|
+
return qrCache.get(text);
|
|
124
|
+
}
|
|
125
|
+
// For synchronous use, we need to pre-generate
|
|
126
|
+
// Templates should call qr() with predictable values from props
|
|
127
|
+
throw new Error(`QR code not pre-generated for: "${text}". ` +
|
|
128
|
+
`QR codes must be generated from prop values. ` +
|
|
129
|
+
`Make sure to pass the URL/text as a prop.`);
|
|
130
|
+
};
|
|
131
|
+
// Pre-generate QR codes for all string props that look like they might be URLs or text to encode
|
|
132
|
+
// This way templates can use qr(url) synchronously
|
|
133
|
+
const qrPromises = [];
|
|
134
|
+
for (const [key, value] of Object.entries(props)) {
|
|
135
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
136
|
+
// Pre-generate QR code for this prop - use text as key
|
|
137
|
+
const promise = qr(value).then(dataUri => {
|
|
138
|
+
qrCache.set(value, dataUri);
|
|
139
|
+
});
|
|
140
|
+
qrPromises.push(promise);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Wait for all QR codes to be generated
|
|
144
|
+
await Promise.all(qrPromises);
|
|
145
|
+
// Pre-generate images and videos for caching
|
|
146
|
+
const imageCache = new Map();
|
|
147
|
+
const videoCache = new Map();
|
|
148
|
+
const requestedVideos = new Set();
|
|
149
|
+
// Image helper - pre-generates data URIs for image files
|
|
150
|
+
const imageHelper = (filePath) => {
|
|
151
|
+
if (!imageCache.has(filePath)) {
|
|
152
|
+
throw new Error(`Image not pre-loaded: "${filePath}". ` +
|
|
153
|
+
`Images must be passed as props or discovered in first render pass.`);
|
|
154
|
+
}
|
|
155
|
+
return imageCache.get(filePath);
|
|
156
|
+
};
|
|
157
|
+
// Video helper - returns frame matching current frame number
|
|
158
|
+
const videoHelper = (filePath) => {
|
|
159
|
+
// Mark video as requested for pre-generation
|
|
160
|
+
requestedVideos.add(filePath);
|
|
161
|
+
// If not cached yet, return placeholder (will be replaced in second pass)
|
|
162
|
+
if (!videoCache.has(filePath)) {
|
|
163
|
+
return 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==';
|
|
164
|
+
}
|
|
165
|
+
const frames = videoCache.get(filePath);
|
|
166
|
+
const currentFrame = props.frame ?? 0;
|
|
167
|
+
const frameIndex = currentFrame % frames.length;
|
|
168
|
+
return frames[frameIndex];
|
|
169
|
+
};
|
|
170
|
+
// Pre-load images from props (any prop ending in .jpg, .png, .gif, .webp, .svg)
|
|
171
|
+
const imagePromises = [];
|
|
172
|
+
for (const [key, value] of Object.entries(props)) {
|
|
173
|
+
if (typeof value === 'string' && /\.(jpg|jpeg|png|gif|webp|svg)$/i.test(value)) {
|
|
174
|
+
const promise = image(value).then(dataUri => {
|
|
175
|
+
imageCache.set(value, dataUri);
|
|
176
|
+
}).catch(err => {
|
|
177
|
+
console.warn(`Failed to load image ${value}:`, err.message);
|
|
178
|
+
});
|
|
179
|
+
imagePromises.push(promise);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
await Promise.all(imagePromises);
|
|
183
|
+
// Template composition helper - loads templates on-demand with two-pass rendering
|
|
184
|
+
const templateComponentCache = new Map();
|
|
185
|
+
// Map of template name -> parent template path (for relative resolution)
|
|
186
|
+
const requestedTemplates = new Map();
|
|
187
|
+
// Create a template helper factory that knows its context
|
|
188
|
+
const createTemplateHelper = (contextPath) => {
|
|
189
|
+
return (name, templateProps) => {
|
|
190
|
+
// If template not loaded yet, mark it as requested with its context
|
|
191
|
+
if (!templateComponentCache.has(name)) {
|
|
192
|
+
requestedTemplates.set(name, contextPath);
|
|
193
|
+
// Return a placeholder that will be replaced in second pass
|
|
194
|
+
return React.createElement('div', {
|
|
195
|
+
style: { display: 'flex' },
|
|
196
|
+
'data-template-placeholder': name
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
const cached = templateComponentCache.get(name);
|
|
200
|
+
// Build full props for the embedded template (include helpers)
|
|
201
|
+
// Create a new template helper with the embedded template's path as context
|
|
202
|
+
const embeddedFrame = templateProps?.frame ?? props.frame ?? 0;
|
|
203
|
+
const embeddedProgress = templateProps?.progress ?? props.progress ?? 0;
|
|
204
|
+
const embeddedFullProps = {
|
|
205
|
+
...(templateProps || {}),
|
|
206
|
+
tw: (classes) => tw(classes, tailwindConfig, dsgnConfig, { progress: embeddedProgress, frame: embeddedFrame }),
|
|
207
|
+
qr: qrHelper,
|
|
208
|
+
image: imageHelper,
|
|
209
|
+
video: videoHelper,
|
|
210
|
+
template: createTemplateHelper(cached.templatePath), // Allow nested templates with proper context
|
|
211
|
+
config: dsgnConfig,
|
|
212
|
+
};
|
|
213
|
+
// Return JSX wrapped in a sized container (using template's own meta.json size)
|
|
214
|
+
return React.createElement('div', { style: { width: cached.meta.size.width, height: cached.meta.size.height, display: 'flex' } }, cached.Component(embeddedFullProps));
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
// Create the root template helper with the current template's path as context
|
|
218
|
+
const templateHelper = createTemplateHelper(currentTemplatePath);
|
|
219
|
+
// First pass: render to collect template and video dependencies
|
|
220
|
+
Component({
|
|
221
|
+
...props,
|
|
222
|
+
tw: () => ({}),
|
|
223
|
+
qr: () => '',
|
|
224
|
+
image: () => '',
|
|
225
|
+
video: videoHelper,
|
|
226
|
+
template: templateHelper,
|
|
227
|
+
config: dsgnConfig
|
|
228
|
+
});
|
|
229
|
+
// Load all requested videos in parallel
|
|
230
|
+
if (requestedVideos.size > 0) {
|
|
231
|
+
const fps = meta.video?.fps ?? 30; // Default to 30fps if not a video template
|
|
232
|
+
const videoPromises = Array.from(requestedVideos).map(async (videoPath) => {
|
|
233
|
+
try {
|
|
234
|
+
// Extract all frames from the video and cache them
|
|
235
|
+
const frames = await extractVideoFramesForCache(videoPath, fps);
|
|
236
|
+
videoCache.set(videoPath, frames);
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
console.warn(`Failed to load video ${videoPath}:`, err.message);
|
|
240
|
+
}
|
|
241
|
+
});
|
|
242
|
+
await Promise.all(videoPromises);
|
|
243
|
+
}
|
|
244
|
+
// Load all requested templates in parallel
|
|
245
|
+
if (requestedTemplates.size > 0) {
|
|
246
|
+
const loadPromises = Array.from(requestedTemplates.entries()).map(async ([templateName, parentTemplatePath]) => {
|
|
247
|
+
const { module: embeddedTemplate, templatePath: embeddedTemplatePath } = await loadTemplate(templateName, parentTemplatePath);
|
|
248
|
+
const embeddedMeta = await loadTemplateMeta(templateName, parentTemplatePath);
|
|
249
|
+
const EmbeddedComponent = embeddedTemplate.default;
|
|
250
|
+
if (!EmbeddedComponent) {
|
|
251
|
+
throw new Error(`Template ${templateName} does not export a default component`);
|
|
252
|
+
}
|
|
253
|
+
templateComponentCache.set(templateName, {
|
|
254
|
+
Component: EmbeddedComponent,
|
|
255
|
+
meta: embeddedMeta,
|
|
256
|
+
templatePath: embeddedTemplatePath,
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
await Promise.all(loadPromises);
|
|
260
|
+
}
|
|
261
|
+
// Add frame, progress, config, tw, qr, image, video, and template utilities
|
|
262
|
+
const frame = props.frame ?? 0;
|
|
263
|
+
const progress = props.progress ?? 0;
|
|
264
|
+
const fullProps = {
|
|
265
|
+
...props,
|
|
266
|
+
frame,
|
|
267
|
+
progress,
|
|
268
|
+
config: dsgnConfig, // Pass the design config to the template
|
|
269
|
+
tw: (classes) => tw(classes, tailwindConfig, dsgnConfig, { progress, frame }), // Tailwind class converter with animation context
|
|
270
|
+
qr: qrHelper, // QR code generator (cached)
|
|
271
|
+
image: imageHelper, // Image loader (cached)
|
|
272
|
+
video: videoHelper, // Video frame loader (cached)
|
|
273
|
+
template: templateHelper, // Template embedder (cached)
|
|
274
|
+
};
|
|
275
|
+
// Load fonts (template-specific or default)
|
|
276
|
+
const fonts = await loadTemplateFonts(templateName, meta);
|
|
277
|
+
// Render to SVG using Satori at the base size
|
|
278
|
+
// Scale will be applied during PNG conversion
|
|
279
|
+
const svg = await satori(Component(fullProps), {
|
|
280
|
+
width: meta.size.width,
|
|
281
|
+
height: meta.size.height,
|
|
282
|
+
fonts,
|
|
283
|
+
});
|
|
284
|
+
return svg;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Render a template to PNG
|
|
288
|
+
*/
|
|
289
|
+
export async function renderToPNG(templateName, props = {}, options = {}) {
|
|
290
|
+
const svg = await renderToSVG(templateName, props);
|
|
291
|
+
const meta = await loadTemplateMeta(templateName);
|
|
292
|
+
// Get scale for high-resolution rendering
|
|
293
|
+
// For video frames, use 1x scale (faster, compression reduces quality anyway)
|
|
294
|
+
// For images, use 2x scale for sharp text
|
|
295
|
+
const scale = options.scale ?? meta.size.scale ?? 2;
|
|
296
|
+
// Convert SVG to PNG using Resvg with scale multiplier
|
|
297
|
+
// This renders the SVG at a higher resolution for sharper output
|
|
298
|
+
const resvg = new Resvg(svg, {
|
|
299
|
+
fitTo: {
|
|
300
|
+
mode: 'width',
|
|
301
|
+
value: Math.round(meta.size.width * scale),
|
|
302
|
+
},
|
|
303
|
+
});
|
|
304
|
+
const pngData = resvg.render();
|
|
305
|
+
const pngBuffer = pngData.asPng();
|
|
306
|
+
return pngBuffer;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Render a template to JPEG (faster for video frames)
|
|
310
|
+
*/
|
|
311
|
+
export async function renderToJPEG(templateName, props = {}, options = {}) {
|
|
312
|
+
const svg = await renderToSVG(templateName, props);
|
|
313
|
+
const meta = await loadTemplateMeta(templateName);
|
|
314
|
+
const scale = options.scale ?? meta.size.scale ?? 1; // Default 1x for JPEG (video use)
|
|
315
|
+
const quality = options.quality ?? 85; // JPEG quality (85 is good balance)
|
|
316
|
+
// Convert SVG to PNG using Resvg first
|
|
317
|
+
const resvg = new Resvg(svg, {
|
|
318
|
+
fitTo: {
|
|
319
|
+
mode: 'width',
|
|
320
|
+
value: Math.round(meta.size.width * scale),
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
const pngData = resvg.render();
|
|
324
|
+
const pngBuffer = pngData.asPng();
|
|
325
|
+
// Convert PNG to JPEG using Sharp (faster encoding, smaller files)
|
|
326
|
+
const jpegBuffer = await sharp(pngBuffer)
|
|
327
|
+
.jpeg({ quality })
|
|
328
|
+
.toBuffer();
|
|
329
|
+
return jpegBuffer;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Render a template to WebP
|
|
333
|
+
*/
|
|
334
|
+
export async function renderToWebP(templateName, props = {}) {
|
|
335
|
+
// First render to PNG
|
|
336
|
+
const pngBuffer = await renderToPNG(templateName, props);
|
|
337
|
+
// Convert PNG to WebP using sharp
|
|
338
|
+
const webpBuffer = await sharp(pngBuffer)
|
|
339
|
+
.webp({ quality: 90 }) // High quality WebP
|
|
340
|
+
.toBuffer();
|
|
341
|
+
return webpBuffer;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Save rendered output to file
|
|
345
|
+
*/
|
|
346
|
+
export async function saveToFile(data, outputPath) {
|
|
347
|
+
await fs.writeFile(outputPath, data);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Load fonts for a template
|
|
351
|
+
* Priority: 1) dsgn.json fonts 2) template meta.json fonts 3) default Noto Sans
|
|
352
|
+
*/
|
|
353
|
+
async function loadTemplateFonts(templateName, meta) {
|
|
354
|
+
// First try to load fonts from dsgn.json
|
|
355
|
+
const dsgnConfig = await loadConfig();
|
|
356
|
+
if (dsgnConfig.fonts) {
|
|
357
|
+
const dsgnFonts = await loadFontsFromConfig(dsgnConfig);
|
|
358
|
+
if (dsgnFonts.length > 0) {
|
|
359
|
+
return dsgnFonts;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
// Then try template-specific fonts
|
|
363
|
+
if (meta.fonts && meta.fonts.length > 0) {
|
|
364
|
+
try {
|
|
365
|
+
return await loadCustomFonts(templateName, meta.fonts);
|
|
366
|
+
}
|
|
367
|
+
catch (error) {
|
|
368
|
+
console.warn(`Warning: Failed to load template fonts, falling back to defaults: ${error.message}`);
|
|
369
|
+
return await loadDefaultFonts();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
// Finally fall back to default fonts
|
|
373
|
+
return await loadDefaultFonts();
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Load custom fonts from template directory (cached)
|
|
377
|
+
*/
|
|
378
|
+
async function loadCustomFonts(templateName, fontMetadata) {
|
|
379
|
+
// Create cache key from template name and font metadata
|
|
380
|
+
const cacheKey = `${templateName}:${JSON.stringify(fontMetadata)}`;
|
|
381
|
+
// Return cached fonts if available
|
|
382
|
+
if (fontCache.has(cacheKey)) {
|
|
383
|
+
return fontCache.get(cacheKey);
|
|
384
|
+
}
|
|
385
|
+
const templatePath = await getTemplatePathAsync(templateName);
|
|
386
|
+
const templateDir = path.dirname(templatePath);
|
|
387
|
+
const fonts = [];
|
|
388
|
+
for (const fontMeta of fontMetadata) {
|
|
389
|
+
const fontPath = path.join(templateDir, fontMeta.path);
|
|
390
|
+
try {
|
|
391
|
+
const fontData = await fs.readFile(fontPath);
|
|
392
|
+
fonts.push({
|
|
393
|
+
name: fontMeta.name,
|
|
394
|
+
data: fontData,
|
|
395
|
+
weight: fontMeta.weight,
|
|
396
|
+
style: fontMeta.style,
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
catch (error) {
|
|
400
|
+
throw new Error(`Failed to load font ${fontMeta.name} from ${fontMeta.path}: ${error.message}`);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
// Cache the fonts
|
|
404
|
+
fontCache.set(cacheKey, fonts);
|
|
405
|
+
return fonts;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Font cache to avoid re-downloading/re-reading fonts
|
|
409
|
+
*/
|
|
410
|
+
const fontCache = new Map();
|
|
411
|
+
/**
|
|
412
|
+
* Load fonts from dsgn.json config
|
|
413
|
+
*/
|
|
414
|
+
async function loadFontsFromConfig(config) {
|
|
415
|
+
const cacheKey = `config-fonts:${JSON.stringify(config.fonts)}`;
|
|
416
|
+
// Return cached fonts if available
|
|
417
|
+
if (fontCache.has(cacheKey)) {
|
|
418
|
+
return fontCache.get(cacheKey);
|
|
419
|
+
}
|
|
420
|
+
const fonts = [];
|
|
421
|
+
// Iterate through font families (sans, serif, mono, etc.)
|
|
422
|
+
for (const [key, value] of Object.entries(config.fonts || {})) {
|
|
423
|
+
if (!value)
|
|
424
|
+
continue;
|
|
425
|
+
// Check if it's the new object format with files
|
|
426
|
+
if (typeof value === 'object' && !Array.isArray(value)) {
|
|
427
|
+
const fontDef = value;
|
|
428
|
+
if (fontDef.files && fontDef.files.length > 0) {
|
|
429
|
+
const fontName = fontDef.family[0]; // Use first font in family as the name
|
|
430
|
+
for (const fileDef of fontDef.files) {
|
|
431
|
+
try {
|
|
432
|
+
// Resolve path relative to CWD (where dsgn.json is)
|
|
433
|
+
const fontPath = path.resolve(fileDef.path);
|
|
434
|
+
const fontData = await fs.readFile(fontPath);
|
|
435
|
+
fonts.push({
|
|
436
|
+
name: fontName,
|
|
437
|
+
data: fontData,
|
|
438
|
+
weight: fileDef.weight || 400,
|
|
439
|
+
style: fileDef.style || 'normal',
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
catch (error) {
|
|
443
|
+
console.warn(`Warning: Failed to load font ${fontName} from ${fileDef.path}: ${error.message}`);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
// Cache the fonts
|
|
450
|
+
if (fonts.length > 0) {
|
|
451
|
+
fontCache.set(cacheKey, fonts);
|
|
452
|
+
}
|
|
453
|
+
return fonts;
|
|
454
|
+
}
|
|
455
|
+
/**
|
|
456
|
+
* Load default fonts for Satori
|
|
457
|
+
* Fetches a basic font from jsdelivr CDN (cached)
|
|
458
|
+
*/
|
|
459
|
+
async function loadDefaultFonts() {
|
|
460
|
+
const cacheKey = 'default-fonts';
|
|
461
|
+
// Return cached fonts if available
|
|
462
|
+
if (fontCache.has(cacheKey)) {
|
|
463
|
+
return fontCache.get(cacheKey);
|
|
464
|
+
}
|
|
465
|
+
try {
|
|
466
|
+
// Fetch Noto Sans from jsDelivr (reliable CDN)
|
|
467
|
+
const fontUrl = 'https://cdn.jsdelivr.net/npm/@fontsource/noto-sans@5.0.18/files/noto-sans-latin-400-normal.woff';
|
|
468
|
+
const response = await fetch(fontUrl);
|
|
469
|
+
if (!response.ok) {
|
|
470
|
+
throw new Error(`Font download failed: ${response.statusText}`);
|
|
471
|
+
}
|
|
472
|
+
const fontData = await response.arrayBuffer();
|
|
473
|
+
const fonts = [
|
|
474
|
+
{
|
|
475
|
+
name: 'Noto Sans',
|
|
476
|
+
data: fontData,
|
|
477
|
+
weight: 400,
|
|
478
|
+
style: 'normal',
|
|
479
|
+
},
|
|
480
|
+
];
|
|
481
|
+
// Cache the fonts
|
|
482
|
+
fontCache.set(cacheKey, fonts);
|
|
483
|
+
return fonts;
|
|
484
|
+
}
|
|
485
|
+
catch (error) {
|
|
486
|
+
throw new Error(`Failed to load fonts: ${error.message}`);
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
/**
|
|
490
|
+
* Main render function
|
|
491
|
+
*/
|
|
492
|
+
export async function render(options) {
|
|
493
|
+
const { templateName, props = {}, format = 'png' } = options;
|
|
494
|
+
if (format === 'svg') {
|
|
495
|
+
const svg = await renderToSVG(templateName, props);
|
|
496
|
+
if (options.outputPath) {
|
|
497
|
+
await saveToFile(svg, options.outputPath);
|
|
498
|
+
}
|
|
499
|
+
return svg;
|
|
500
|
+
}
|
|
501
|
+
else if (format === 'png') {
|
|
502
|
+
const png = await renderToPNG(templateName, props);
|
|
503
|
+
if (options.outputPath) {
|
|
504
|
+
await saveToFile(png, options.outputPath);
|
|
505
|
+
}
|
|
506
|
+
return png;
|
|
507
|
+
}
|
|
508
|
+
else if (format === 'webp') {
|
|
509
|
+
const webp = await renderToWebP(templateName, props);
|
|
510
|
+
if (options.outputPath) {
|
|
511
|
+
await saveToFile(webp, options.outputPath);
|
|
512
|
+
}
|
|
513
|
+
return webp;
|
|
514
|
+
}
|
|
515
|
+
else if (format === 'jpg' || format === 'jpeg') {
|
|
516
|
+
const jpeg = await renderToJPEG(templateName, props);
|
|
517
|
+
if (options.outputPath) {
|
|
518
|
+
await saveToFile(jpeg, options.outputPath);
|
|
519
|
+
}
|
|
520
|
+
return jpeg;
|
|
521
|
+
}
|
|
522
|
+
throw new Error(`Unsupported format: ${format}`);
|
|
523
|
+
}
|
|
524
|
+
//# sourceMappingURL=renderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"renderer.js","sourceRoot":"","sources":["../../src/lib/renderer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tailwind config interface (simplified)
|
|
3
|
+
*/
|
|
4
|
+
export interface TailwindConfig {
|
|
5
|
+
theme?: {
|
|
6
|
+
extend?: {
|
|
7
|
+
colors?: Record<string, any>;
|
|
8
|
+
spacing?: Record<string, string>;
|
|
9
|
+
fontSize?: Record<string, any>;
|
|
10
|
+
fontFamily?: Record<string, string[]>;
|
|
11
|
+
borderRadius?: Record<string, string>;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
};
|
|
14
|
+
colors?: Record<string, any>;
|
|
15
|
+
spacing?: Record<string, string>;
|
|
16
|
+
fontSize?: Record<string, any>;
|
|
17
|
+
fontFamily?: Record<string, string[]>;
|
|
18
|
+
borderRadius?: Record<string, string>;
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
};
|
|
21
|
+
[key: string]: any;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Load and parse Tailwind config
|
|
25
|
+
*/
|
|
26
|
+
export declare function loadTailwindConfig(): Promise<TailwindConfig | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve a color from Tailwind config
|
|
29
|
+
* Supports: primary, blue-500, slate-200, etc.
|
|
30
|
+
*/
|
|
31
|
+
export declare function resolveColor(colorName: string, tailwindConfig: TailwindConfig | null): string | null;
|
|
32
|
+
/**
|
|
33
|
+
* Resolve spacing value from Tailwind config
|
|
34
|
+
*/
|
|
35
|
+
export declare function resolveSpacing(value: string, tailwindConfig: TailwindConfig | null): string | null;
|
|
36
|
+
/**
|
|
37
|
+
* Resolve font size from Tailwind config
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveFontSize(size: string, tailwindConfig: TailwindConfig | null): {
|
|
40
|
+
fontSize: string;
|
|
41
|
+
lineHeight?: string;
|
|
42
|
+
} | null;
|
|
43
|
+
/**
|
|
44
|
+
* Resolve border radius from Tailwind config
|
|
45
|
+
*/
|
|
46
|
+
export declare function resolveBorderRadius(value: string, tailwindConfig: TailwindConfig | null): string | null;
|
|
47
|
+
//# sourceMappingURL=tailwind-config-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tailwind-config-loader.d.ts","sourceRoot":"","sources":["../../src/lib/tailwind-config-loader.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE;QACN,MAAM,CAAC,EAAE;YACP,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YAC/B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YACtC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;YACtC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;SACpB,CAAC;QACF,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC/B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACtC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAyBD;;GAEG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC,CA0BzE;AAySD;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,cAAc,GAAG,IAAI,GACpC,MAAM,GAAG,IAAI,CA+Bf;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,cAAc,GAAG,IAAI,GACpC,MAAM,GAAG,IAAI,CAWf;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,cAAc,EAAE,cAAc,GAAG,IAAI,GACpC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CA6BlD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,cAAc,EAAE,cAAc,GAAG,IAAI,GACpC,MAAM,GAAG,IAAI,CAWf"}
|