feat: complete NutriScan redesign

This commit is contained in:
evandrodevbr committed 2026-07-16 16:31:50 -03:00
1 parent c1fe4af997
commit f71cd167b3
163 files changed
+30802 -14169

No files matched your search

+179
View File
@@ -0,0 +1,179 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>NutriScan · Redesign</title>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body { background: #f9f6f0; display: flex; align-items: center; justify-content: center; min-height: 100vh; font-family: -apple-system, BlinkMacSystemFont, sans-serif; }
#__bundler_loading { position: fixed; bottom: 20px; right: 20px; font: 13px/1.4 -apple-system, BlinkMacSystemFont, sans-serif; color: #666; background: #fff; padding: 8px 14px; border-radius: 8px; box-shadow: 0 1px 4px rgba(0,0,0,0.12); z-index: 10000; }
#__bundler_thumbnail { position: fixed; inset: 0; width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; background: #f9f6f0; z-index: 9999; }
#__bundler_thumbnail svg { width: 100%; height: 100%; object-fit: contain; }
#__bundler_placeholder { color: #999; font-size: 14px; }
</style>
<noscript>
<style>#__bundler_loading { display: none; }</style>
<div style="position:fixed;bottom:12px;left:12px;font:13px/1.4 -apple-system,BlinkMacSystemFont,sans-serif;color:#999;background:rgba(255,255,255,0.9);padding:6px 12px;border-radius:6px;box-shadow:0 1px 4px rgba(0,0,0,0.08);z-index:10000;">
This page requires JavaScript to display.
</div>
</noscript>
</head>
<body>
<div id="__bundler_thumbnail">
<svg viewBox="0 0 1200 800" xmlns="http://www.w3.org/2000/svg">
<rect width="1200" height="800" fill="#f9f6f0"></rect>
<circle cx="600" cy="400" r="180" fill="oklch(52% 0.11 155)"></circle>
<text x="600" y="470" font-family="Georgia, serif" font-size="220" text-anchor="middle" fill="#fff">N</text>
</svg>
</div>
<div id="__bundler_loading">Unpacking...</div>
<script>
document.addEventListener('DOMContentLoaded', async function() {
const loading = document.getElementById('__bundler_loading');
function setStatus(msg) { if (loading) loading.textContent = msg; }
// Error sink persists across replaceWith since it's on window, not the DOM.
window.addEventListener('error', function(e) {
var p = document.body || document.documentElement;
var d = document.getElementById('__bundler_err') || p.appendChild(document.createElement('div'));
d.id = '__bundler_err';
d.style.cssText = 'position:fixed;bottom:12px;left:12px;right:12px;font:12px/1.4 ui-monospace,monospace;background:#2a1215;color:#ff8a80;padding:10px 14px;border-radius:8px;border:1px solid #5c2b2e;z-index:99999;white-space:pre-wrap;max-height:40vh;overflow:auto';
d.textContent = (d.textContent ? d.textContent + String.fromCharCode(10) : '') +
'[bundle] ' + (e.message || e.type) +
(e.filename ? ' (' + e.filename.slice(0, 60) + ':' + e.lineno + ')' : '');
}, true);
try {
const manifestEl = document.querySelector('script[type="__bundler/manifest"]');
const templateEl = document.querySelector('script[type="__bundler/template"]');
if (!manifestEl || !templateEl) {
setStatus('Error: missing bundle data');
console.error('[bundler] Missing script tags — manifestEl:', !!manifestEl, 'templateEl:', !!templateEl);
return;
}
const manifest = JSON.parse(manifestEl.textContent);
let template = JSON.parse(templateEl.textContent);
const uuids = Object.keys(manifest);
setStatus('Unpacking ' + uuids.length + ' assets...');
const blobUrls = {};
await Promise.all(uuids.map(async (uuid) => {
const entry = manifest[uuid];
try {
const binaryStr = atob(entry.data);
const bytes = new Uint8Array(binaryStr.length);
for (let i = 0; i < binaryStr.length; i++) bytes[i] = binaryStr.charCodeAt(i);
let finalBytes = bytes;
if (entry.compressed) {
if (typeof DecompressionStream !== 'undefined') {
const ds = new DecompressionStream('gzip');
const writer = ds.writable.getWriter();
const reader = ds.readable.getReader();
writer.write(bytes);
writer.close();
const chunks = [];
let totalLen = 0;
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
totalLen += value.length;
}
finalBytes = new Uint8Array(totalLen);
let offset = 0;
for (const chunk of chunks) { finalBytes.set(chunk, offset); offset += chunk.length; }
} else {
console.warn('DecompressionStream not available, asset ' + uuid + ' may not render');
}
}
blobUrls[uuid] = URL.createObjectURL(new Blob([finalBytes], { type: entry.mime }));
} catch (err) {
console.error('Failed to decode asset ' + uuid + ':', err);
blobUrls[uuid] = URL.createObjectURL(new Blob([], { type: entry.mime }));
}
}));
const extResEl = document.querySelector('script[type="__bundler/ext_resources"]');
const extResources = extResEl ? JSON.parse(extResEl.textContent) : [];
const resourceMap = {};
for (const entry of extResources) {
if (blobUrls[entry.uuid]) resourceMap[entry.id] = blobUrls[entry.uuid];
}
setStatus('Rendering...');
for (const uuid of uuids) template = template.split(uuid).join(blobUrls[uuid]);
// Strip integrity + crossorigin — blob URLs from a file:// document inherit
// a null origin, so crossorigin forces a CORS fetch that SRI then rejects.
// The manifest bytes are ours; SRI protects against CDN compromise, not this.
template = template.replace(/\s+integrity="[^"]*"/gi, '').replace(/\s+crossorigin="[^"]*"/gi, '');
const resourceScript = '<script>window.__resources = ' +
JSON.stringify(resourceMap).split('</' + 'script>').join('<\\/' + 'script>') +
';</' + 'script>';
// Inject after <head> so the DOCTYPE stays first; prepending the script
// would push the parser into quirks mode. DOMParser always emits a <head>
// (synthesizing one if the source HTML omitted it) but may carry
// attributes through, so match the full opening tag. slice() rather than
// replace() keeps us clear of $-pattern substitution in resourceScript.
const headOpen = template.match(/<head[^>]*>/i);
if (headOpen) {
const i = headOpen.index + headOpen[0].length;
template = template.slice(0, i) + resourceScript + template.slice(i);
}
// Parse the template and swap the root element. Scripts inserted via
// DOMParser/replaceWith are inert per spec — re-create each with
// createElement so they execute, awaiting onload for src scripts to
// preserve ordering (React before ReactDOM before Babel before text/babel).
const doc = new DOMParser().parseFromString(template, 'text/html');
document.documentElement.replaceWith(doc.documentElement);
const dead = Array.from(document.scripts);
for (const old of dead) {
const s = document.createElement('script');
for (const a of old.attributes) s.setAttribute(a.name, a.value);
s.textContent = old.textContent;
// text/babel scripts with a src: fetch and inline. transformScriptTags
// does XHR against the src, but blob:null/ from a file:// origin is
// silently dropped. Inlining makes it a plain inline babel script,
// which transformScriptTags handles unconditionally.
if ((s.type === 'text/babel' || s.type === 'text/jsx') && s.src) {
const r = await fetch(s.src);
s.textContent = await r.text();
s.removeAttribute('src');
}
const p = s.src ? new Promise(function(r) { s.onload = s.onerror = r; }) : null;
old.replaceWith(s);
if (p) await p;
}
// Babel standalone auto-transforms type=text/babel on DOMContentLoaded,
// which fired before we swapped the document. Trigger manually if present.
if (window.Babel && typeof window.Babel.transformScriptTags === 'function') {
window.Babel.transformScriptTags();
}
} catch (err) {
setStatus('Error unpacking: ' + err.message);
console.error('Bundle unpack error:', err);
}
});
</script>
<script type="__bundler/manifest">
{"e785f210-fa4d-4569-be2d-fe96636d2fb3":{"mime":"text/javascript","compressed":true,"data":"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 truncated
</script>
<script type="__bundler/ext_resources">
[]
</script>
<script type="__bundler/template">
"<!DOCTYPE html>\n<html lang=\"pt-BR\"><head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <title>NutriScan · Redesign<\u002Ftitle>\n\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin=\"\">\n <style>/* latin-ext */\n@font-face {\n font-family: 'Instrument Serif';\n font-style: italic;\n font-weight: 400;\n font-display: swap;\n src: url(\"60fa588b-1760-4d48-b4cc-04aa12eb709f\") format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Instrument Serif';\n font-style: italic;\n font-weight: 400;\n font-display: swap;\n src: url(\"aaf27971-679d-4cf1-8dc2-75768121d40c\") format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Instrument Serif';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(\"129d834f-f5f8-4f19-af81-0920e9288457\") format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Instrument Serif';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(\"72b67702-a356-405e-8772-6f0a2a9b136f\") format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(\"66e75bcd-2938-4e43-b87c-4720c7ceb8df\") format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(\"64671880-b4e5-4ebc-8150-30f9a3eae5fa\") format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(\"cb114583-31ec-4a43-8c57-9946423fdd16\") format('woff2');\n unicode-range: U+1F00-1FFF;\n}\n/* greek */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(\"125ff4dd-646d-4f13-816d-177869568bce\") format('woff2');\n unicode-range: U+0370-0377, U+037A-037F, U+0384-038A, U+038C, U+038E-03A1, U+03A3-03FF;\n}\n/* vietnamese */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(\"28bdc14b-6ceb-424a-be18-8bebc3e41446\") format('woff2');\n unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+1EA0-1EF9, U+20AB;\n}\n/* latin-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(\"2fa653f7-680d-43f8-9aea-adfaac230e8f\") format('woff2');\n unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;\n}\n/* latin */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 400;\n font-display: swap;\n src: url(\"17662fa0-bb4d-46cc-b4f5-e2727b1192a7\") format('woff2');\n unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;\n}\n/* cyrillic-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(\"66e75bcd-2938-4e43-b87c-4720c7ceb8df\") format('woff2');\n unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;\n}\n/* cyrillic */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(\"64671880-b4e5-4ebc-8150-30f9a3eae5fa\") format('woff2');\n unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;\n}\n/* greek-ext */\n@font-face {\n font-family: 'Inter';\n font-style: normal;\n font-weight: 500;\n font-display: swap;\n src: url(\"cb114583-31ec-4a43-8c57-9946423fdd16\") format('woff2');\n unicode-range: U+1F0Line truncated
</script>
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 844 KiB

+16
View File
@@ -0,0 +1,16 @@
const fs = require('fs');
const path = require('path');
const html = fs.readFileSync(path.join(__dirname, 'NutriScan Redesign.html'), 'utf8');
// Find the template script tag
const start = html.indexOf('type="__bundler/template">');
const end = html.indexOf('</script>', start);
const raw = html.slice(start + 'type="__bundler/template">'.length, end).trim();
try {
const decoded = JSON.parse(raw);
fs.writeFileSync(path.join(__dirname, 'extracted-template.html'), decoded);
console.log('Written, length:', decoded.length);
} catch(e) {
console.log('Error:', e.message);
}
File diff suppressed because it is too large. Load diff