improve banner perfs and responsiveness | lazyload iframes | cleanup files
Browse files- app/src/components/Hero.astro +9 -0
- app/src/content/embeds/banner.html +22 -7
- app/src/content/embeds/transformers/dependency-graph.html +1 -0
- app/src/content/embeds/transformers/loc-growth.html +1 -0
- app/src/content/embeds/transformers/model-timeline.html +1 -0
- package-lock.json +0 -0
- package.json +0 -42
- webpack.config.js +0 -354
app/src/components/Hero.astro
CHANGED
|
@@ -208,6 +208,15 @@ const pdfFilename = `${slugify(pdfBase)}.pdf`;
|
|
| 208 |
padding: 48px 16px 16px;
|
| 209 |
text-align: center;
|
| 210 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 211 |
.hero-title {
|
| 212 |
font-size: clamp(28px, 4vw, 48px);
|
| 213 |
font-weight: 800;
|
|
|
|
| 208 |
padding: 48px 16px 16px;
|
| 209 |
text-align: center;
|
| 210 |
}
|
| 211 |
+
.hero :global(.html-embed) {
|
| 212 |
+
margin-bottom: 0;
|
| 213 |
+
}
|
| 214 |
+
@media (max-width: 768px) {
|
| 215 |
+
.hero :global(.html-embed) {
|
| 216 |
+
padding: 0 16px;
|
| 217 |
+
}
|
| 218 |
+
}
|
| 219 |
+
|
| 220 |
.hero-title {
|
| 221 |
font-size: clamp(28px, 4vw, 48px);
|
| 222 |
font-weight: 800;
|
app/src/content/embeds/banner.html
CHANGED
|
@@ -3,7 +3,7 @@
|
|
| 3 |
|
| 4 |
.banner-container {
|
| 5 |
width: 100%;
|
| 6 |
-
height:
|
| 7 |
position: relative;
|
| 8 |
overflow: visible;
|
| 9 |
margin: 0 auto;
|
|
@@ -153,19 +153,34 @@ const sim = d3.forceSimulation(graph.nodes)
|
|
| 153 |
.force('y', d3.forceY((_,i) => (Math.floor(i/12)%3) * (H/3) + H/6).strength(0.25))
|
| 154 |
.force('collide', d => d3.forceCollide(d.id === 'llama' ? rBase(d) + 100 : rBase(d) + 20));
|
| 155 |
|
| 156 |
-
|
|
|
|
| 157 |
link
|
| 158 |
.attr('x1', d=>d.source.x).attr('y1', d=>d.source.y)
|
| 159 |
.attr('x2', d=>d.target.x).attr('y2', d=>d.target.y);
|
| 160 |
node.attr('transform', d=>`translate(${d.x},${d.y})`);
|
| 161 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 162 |
|
| 163 |
-
|
| 164 |
-
sim.alphaTarget(0.04);
|
| 165 |
|
| 166 |
-
function dragStart(e,d){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 167 |
function dragged(e,d){ d.fx=e.x; d.fy=e.y; }
|
| 168 |
-
function dragEnd(e,d){
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
// Initialize color palettes
|
| 171 |
function initializeColorPalettes() {
|
|
|
|
| 3 |
|
| 4 |
.banner-container {
|
| 5 |
width: 100%;
|
| 6 |
+
min-height: 200px;
|
| 7 |
position: relative;
|
| 8 |
overflow: visible;
|
| 9 |
margin: 0 auto;
|
|
|
|
| 153 |
.force('y', d3.forceY((_,i) => (Math.floor(i/12)%3) * (H/3) + H/6).strength(0.25))
|
| 154 |
.force('collide', d => d3.forceCollide(d.id === 'llama' ? rBase(d) + 100 : rBase(d) + 20));
|
| 155 |
|
| 156 |
+
// Tick handler that updates node/link positions
|
| 157 |
+
function tickHandler() {
|
| 158 |
link
|
| 159 |
.attr('x1', d=>d.source.x).attr('y1', d=>d.source.y)
|
| 160 |
.attr('x2', d=>d.target.x).attr('y2', d=>d.target.y);
|
| 161 |
node.attr('transform', d=>`translate(${d.x},${d.y})`);
|
| 162 |
+
|
| 163 |
+
// Stop ticking when simulation stabilizes (performance optimization)
|
| 164 |
+
if (sim.alpha() < 0.01) {
|
| 165 |
+
sim.on('tick', null); // Remove tick listener to save CPU
|
| 166 |
+
}
|
| 167 |
+
}
|
| 168 |
|
| 169 |
+
sim.on('tick', tickHandler);
|
|
|
|
| 170 |
|
| 171 |
+
function dragStart(e,d){
|
| 172 |
+
if(!e.active) {
|
| 173 |
+
sim.alphaTarget(.3).restart();
|
| 174 |
+
// Re-attach tick handler when dragging starts
|
| 175 |
+
sim.on('tick', tickHandler);
|
| 176 |
+
}
|
| 177 |
+
d.fx=d.x; d.fy=d.y;
|
| 178 |
+
}
|
| 179 |
function dragged(e,d){ d.fx=e.x; d.fy=e.y; }
|
| 180 |
+
function dragEnd(e,d){
|
| 181 |
+
if(!e.active) sim.alphaTarget(0);
|
| 182 |
+
d.fx=d.fy=null;
|
| 183 |
+
}
|
| 184 |
|
| 185 |
// Initialize color palettes
|
| 186 |
function initializeColorPalettes() {
|
app/src/content/embeds/transformers/dependency-graph.html
CHANGED
|
@@ -3,4 +3,5 @@ src="https://molbap-dependencies-1.hf.space"
|
|
| 3 |
style="width:100%; height:680px; border:0"
|
| 4 |
allow="clipboard-read; clipboard-write; fullscreen"
|
| 5 |
referrerpolicy="no-referrer-when-downgrade"
|
|
|
|
| 6 |
></iframe>
|
|
|
|
| 3 |
style="width:100%; height:680px; border:0"
|
| 4 |
allow="clipboard-read; clipboard-write; fullscreen"
|
| 5 |
referrerpolicy="no-referrer-when-downgrade"
|
| 6 |
+
loading="lazy"
|
| 7 |
></iframe>
|
app/src/content/embeds/transformers/loc-growth.html
CHANGED
|
@@ -3,4 +3,5 @@ src="https://molbap-loc-1.hf.space"
|
|
| 3 |
style="width:100%; height:900px; border:0"
|
| 4 |
allow="clipboard-read; clipboard-write; fullscreen"
|
| 5 |
referrerpolicy="no-referrer-when-downgrade"
|
|
|
|
| 6 |
></iframe>
|
|
|
|
| 3 |
style="width:100%; height:900px; border:0"
|
| 4 |
allow="clipboard-read; clipboard-write; fullscreen"
|
| 5 |
referrerpolicy="no-referrer-when-downgrade"
|
| 6 |
+
loading="lazy"
|
| 7 |
></iframe>
|
app/src/content/embeds/transformers/model-timeline.html
CHANGED
|
@@ -3,4 +3,5 @@
|
|
| 3 |
style="width:100%; height:680px; border:0"
|
| 4 |
allow="clipboard-read; clipboard-write; fullscreen"
|
| 5 |
referrerpolicy="no-referrer-when-downgrade"
|
|
|
|
| 6 |
></iframe>
|
|
|
|
| 3 |
style="width:100%; height:680px; border:0"
|
| 4 |
allow="clipboard-read; clipboard-write; fullscreen"
|
| 5 |
referrerpolicy="no-referrer-when-downgrade"
|
| 6 |
+
loading="lazy"
|
| 7 |
></iframe>
|
package-lock.json
DELETED
|
The diff for this file is too large to render.
See raw diff
|
|
|
package.json
DELETED
|
@@ -1,42 +0,0 @@
|
|
| 1 |
-
{
|
| 2 |
-
"dependencies": {
|
| 3 |
-
"d3": "^7.9.0",
|
| 4 |
-
"katex": "^0.16.11",
|
| 5 |
-
"lodash": "^4.17.21",
|
| 6 |
-
"papaparse": "^5.4.1",
|
| 7 |
-
"plotly.js-basic-dist-min": "^2.33.0",
|
| 8 |
-
"markdown-it": "^13.0.1"
|
| 9 |
-
},
|
| 10 |
-
"name": "scaling-insanity",
|
| 11 |
-
"version": "1.0.0",
|
| 12 |
-
"description": "A peek into software engineering for the transformers library",
|
| 13 |
-
"main": "index.js",
|
| 14 |
-
"scripts": {
|
| 15 |
-
"dev": "webpack serve --open --hot",
|
| 16 |
-
"build": "NODE_ENV=production webpack"
|
| 17 |
-
},
|
| 18 |
-
"author": "",
|
| 19 |
-
"license": "ISC",
|
| 20 |
-
"devDependencies": {
|
| 21 |
-
"@babel/preset-env": "^7.24.6",
|
| 22 |
-
"@swc/html": "^1.10.17",
|
| 23 |
-
"babel-loader": "^9.1.3",
|
| 24 |
-
"clean-webpack-plugin": "^4.0.0",
|
| 25 |
-
"compression-webpack-plugin": "^11.1.0",
|
| 26 |
-
"copy-webpack-plugin": "^12.0.2",
|
| 27 |
-
"css-loader": "^7.1.2",
|
| 28 |
-
"fs": "^0.0.1-security",
|
| 29 |
-
"handlebars": "^4.7.8",
|
| 30 |
-
"html-minimizer-webpack-plugin": "^5.0.0",
|
| 31 |
-
"html-webpack-change-assets-extension-plugin": "^1.3.1",
|
| 32 |
-
"html-webpack-plugin": "^5.6.0",
|
| 33 |
-
"image-minimizer-webpack-plugin": "^4.1.3",
|
| 34 |
-
"sharp": "^0.33.5",
|
| 35 |
-
"style-loader": "^4.0.0",
|
| 36 |
-
"svgo": "^3.3.2",
|
| 37 |
-
"webpack": "^5.91.0",
|
| 38 |
-
"webpack-bundle-analyzer": "^4.10.2",
|
| 39 |
-
"webpack-cli": "^5.1.4",
|
| 40 |
-
"webpack-dev-server": "^5.0.4"
|
| 41 |
-
}
|
| 42 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
webpack.config.js
DELETED
|
@@ -1,354 +0,0 @@
|
|
| 1 |
-
const path = require("path");
|
| 2 |
-
const { CleanWebpackPlugin } = require("clean-webpack-plugin");
|
| 3 |
-
const CopyPlugin = require("copy-webpack-plugin");
|
| 4 |
-
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
|
| 5 |
-
const Handlebars = require("handlebars");
|
| 6 |
-
const fs = require("fs");
|
| 7 |
-
|
| 8 |
-
// Load app configuration
|
| 9 |
-
const appConfig = JSON.parse(fs.readFileSync(path.resolve(__dirname, "config/app.json"), "utf8"));
|
| 10 |
-
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");
|
| 11 |
-
const HtmlMinimizerPlugin = require("html-minimizer-webpack-plugin");
|
| 12 |
-
|
| 13 |
-
const FRAGMENTS_PATH = "src/fragments";
|
| 14 |
-
|
| 15 |
-
// Load the fragments from the fragments directory and caches it
|
| 16 |
-
const loadFragmentsMap = (() => {
|
| 17 |
-
let cachedFragments = null;
|
| 18 |
-
return async () => {
|
| 19 |
-
if (cachedFragments === null) {
|
| 20 |
-
cachedFragments = {};
|
| 21 |
-
const walkDir = async (dir, basePath = '') => {
|
| 22 |
-
const files = fs.readdirSync(dir);
|
| 23 |
-
await Promise.all(files.map(async file => {
|
| 24 |
-
const filePath = path.join(dir, file);
|
| 25 |
-
const relativePath = path.join(basePath, file);
|
| 26 |
-
if (fs.statSync(filePath).isDirectory()) {
|
| 27 |
-
await walkDir(filePath, relativePath);
|
| 28 |
-
} else {
|
| 29 |
-
const nameWithoutExt = relativePath.replace(/\.html$/, '');
|
| 30 |
-
const dottedPath = 'fragment-' + nameWithoutExt.replace(/\\/g, '-').replace(/\//g, '-').replace(/\./g, '-');
|
| 31 |
-
const content = fs.readFileSync(filePath, "utf8");
|
| 32 |
-
let minifiedContent;
|
| 33 |
-
|
| 34 |
-
if (content.trim().startsWith('<!DOCTYPE') || content.trim().startsWith('<html')) {
|
| 35 |
-
minifiedContent = content;
|
| 36 |
-
} else {
|
| 37 |
-
try {
|
| 38 |
-
const minifiedRes = await HtmlMinimizerPlugin.swcMinifyFragment({"tmp.html": content})
|
| 39 |
-
if (minifiedRes.errors) {
|
| 40 |
-
minifiedContent = content;
|
| 41 |
-
} else {
|
| 42 |
-
minifiedContent = minifiedRes.code;
|
| 43 |
-
}
|
| 44 |
-
} catch (error) {
|
| 45 |
-
minifiedContent = content;
|
| 46 |
-
}
|
| 47 |
-
}
|
| 48 |
-
cachedFragments[dottedPath] = minifiedContent;
|
| 49 |
-
}
|
| 50 |
-
}));
|
| 51 |
-
};
|
| 52 |
-
await walkDir(FRAGMENTS_PATH);
|
| 53 |
-
}
|
| 54 |
-
return cachedFragments;
|
| 55 |
-
};
|
| 56 |
-
})();
|
| 57 |
-
|
| 58 |
-
const transformMarkdownWithFragments = async (data, filepath) => {
|
| 59 |
-
const fragments = await loadFragmentsMap();
|
| 60 |
-
console.log(`Available fragments: ${Object.keys(fragments).join(', ')}`);
|
| 61 |
-
|
| 62 |
-
// Read the markdown file
|
| 63 |
-
const markdown = require('markdown-it')({
|
| 64 |
-
html: true,
|
| 65 |
-
linkify: true,
|
| 66 |
-
typographer: true
|
| 67 |
-
});
|
| 68 |
-
|
| 69 |
-
const markdownContent = data.toString('utf8');
|
| 70 |
-
const htmlContent = markdown.render(markdownContent);
|
| 71 |
-
|
| 72 |
-
// Process with Handlebars for fragment insertion
|
| 73 |
-
const template = Handlebars.compile(htmlContent);
|
| 74 |
-
return template(fragments);
|
| 75 |
-
};
|
| 76 |
-
|
| 77 |
-
module.exports = {
|
| 78 |
-
entry: {
|
| 79 |
-
distill: "./src/distill.js",
|
| 80 |
-
main: "./src/index.js",
|
| 81 |
-
},
|
| 82 |
-
output: {
|
| 83 |
-
filename: "[name].bundle.js",
|
| 84 |
-
path: path.resolve(__dirname, "dist"),
|
| 85 |
-
},
|
| 86 |
-
module: {
|
| 87 |
-
rules: [
|
| 88 |
-
{ test: /\.css$/, use: ["style-loader", "css-loader"] },
|
| 89 |
-
{
|
| 90 |
-
test: /\.(js|mjs)$/,
|
| 91 |
-
exclude: /node_modules/,
|
| 92 |
-
use: {
|
| 93 |
-
loader: "babel-loader",
|
| 94 |
-
options: {
|
| 95 |
-
presets: ["@babel/preset-env"],
|
| 96 |
-
},
|
| 97 |
-
},
|
| 98 |
-
}
|
| 99 |
-
],
|
| 100 |
-
},
|
| 101 |
-
plugins: [
|
| 102 |
-
new CleanWebpackPlugin(),
|
| 103 |
-
new CopyPlugin({
|
| 104 |
-
patterns: [
|
| 105 |
-
{ from: "src/fragments/*", to: "fragments/[name].html" },
|
| 106 |
-
{ from: "src/style.css", to: "style.css" },
|
| 107 |
-
{ from: "src/transformers-custom.css", to: "transformers-custom.css" },
|
| 108 |
-
{ from: "content/*.png", to: "static/[name][ext]" },
|
| 109 |
-
{ from: "content/*.svg", to: "static/[name][ext]" },
|
| 110 |
-
{ from: "content/*.html", to: "static/[name][ext]" },
|
| 111 |
-
{ from: "content/hf-logo.svg", to: "hf-logo.svg" },
|
| 112 |
-
{
|
| 113 |
-
from: "content/article.md",
|
| 114 |
-
to: "index.html",
|
| 115 |
-
transform: async (content, path) => {
|
| 116 |
-
const fragments = await loadFragmentsMap();
|
| 117 |
-
|
| 118 |
-
// Convert markdown to HTML
|
| 119 |
-
const markdown = require('markdown-it')({
|
| 120 |
-
html: true,
|
| 121 |
-
linkify: true,
|
| 122 |
-
typographer: true
|
| 123 |
-
});
|
| 124 |
-
|
| 125 |
-
const markdownContent = content.toString('utf8');
|
| 126 |
-
const htmlContent = markdown.render(markdownContent);
|
| 127 |
-
|
| 128 |
-
// Extract headings for TOC generation
|
| 129 |
-
const tocScript = `
|
| 130 |
-
<script>
|
| 131 |
-
function initializeTOC() {
|
| 132 |
-
const article = document.querySelector('d-article');
|
| 133 |
-
const toc = document.querySelector('d-contents');
|
| 134 |
-
if (toc) {
|
| 135 |
-
const headings = [...article.querySelectorAll('h1, h2, h3, h4')].filter(h => !h.hasAttribute('data-no-toc'));
|
| 136 |
-
let ToC = '<nav role="navigation" class="l-text figcaption">';
|
| 137 |
-
ToC += '<div class="toc-header"><span class="toc-title">Table of Contents</span></div>';
|
| 138 |
-
ToC += '<div class="toc-content">';
|
| 139 |
-
|
| 140 |
-
headings.forEach((heading, index) => {
|
| 141 |
-
const id = heading.id || 'heading-' + index;
|
| 142 |
-
if (!heading.id) heading.id = id;
|
| 143 |
-
const level = parseInt(heading.tagName.charAt(1));
|
| 144 |
-
const indent = level === 1 ? '' : 'style="margin-left: ' + ((level - 1) * 1.2) + 'em;"';
|
| 145 |
-
ToC += '<div ' + indent + '><a href="#' + id + '">' + heading.textContent + '</a></div>';
|
| 146 |
-
});
|
| 147 |
-
|
| 148 |
-
ToC += '</div></nav>';
|
| 149 |
-
toc.innerHTML = ToC;
|
| 150 |
-
toc.setAttribute('prerendered', 'true');
|
| 151 |
-
|
| 152 |
-
// Extract tenet text for tooltips
|
| 153 |
-
const tenetTooltips = {
|
| 154 |
-
'source-of-truth': 'We aim be a source of truth for all model definitions. Model implementations should be reliable, reproducible, and faithful to the original performances.',
|
| 155 |
-
'one-model-one-file': 'All inference and training core logic has to be visible, top‑to‑bottom, to maximize each model\\'s hackability.',
|
| 156 |
-
'code-is-product': 'Optimize for reading, diffing, and tweaking, our users are power users. Variables can be explicit, full words, even several words, readability is primordial.',
|
| 157 |
-
'standardize-dont-abstract': 'If it\\'s model behavior, keep it in the file; abstractions only for generic infra.',
|
| 158 |
-
'do-repeat-yourself': 'Copy when it helps users; keep successors in sync without centralizing behavior.',
|
| 159 |
-
'minimal-user-api': 'Config, model, preprocessing; from_pretrained, save_pretrained, push_to_hub. We want the least amount of codepaths.',
|
| 160 |
-
'backwards-compatibility': 'Evolve by additive standardization, never break public APIs.',
|
| 161 |
-
'consistent-public-surface': 'Same argument names, same outputs, hidden states and attentions exposed, enforced by tests.',
|
| 162 |
-
};
|
| 163 |
-
|
| 164 |
-
// Add smooth scrolling and custom tooltips to all tenet links (TOC and article)
|
| 165 |
-
const tocLinks = document.querySelectorAll('d-contents a');
|
| 166 |
-
tocLinks.forEach(link => {
|
| 167 |
-
const href = link.getAttribute('href');
|
| 168 |
-
const anchor = href ? href.substring(1) : '';
|
| 169 |
-
|
| 170 |
-
if (tenetTooltips[anchor]) {
|
| 171 |
-
link.setAttribute('data-tooltip', tenetTooltips[anchor]);
|
| 172 |
-
link.style.position = 'relative';
|
| 173 |
-
}
|
| 174 |
-
|
| 175 |
-
link.addEventListener('click', function(e) {
|
| 176 |
-
e.preventDefault();
|
| 177 |
-
const target = document.querySelector(this.getAttribute('href'));
|
| 178 |
-
if (target) {
|
| 179 |
-
target.scrollIntoView({ behavior: 'smooth' });
|
| 180 |
-
}
|
| 181 |
-
});
|
| 182 |
-
});
|
| 183 |
-
|
| 184 |
-
// Add custom tooltips to tenet links in article content
|
| 185 |
-
const articleLinks = document.querySelectorAll('d-article a[href^="#"]');
|
| 186 |
-
articleLinks.forEach(link => {
|
| 187 |
-
const href = link.getAttribute('href');
|
| 188 |
-
const anchor = href ? href.substring(1) : '';
|
| 189 |
-
if (tenetTooltips[anchor]) {
|
| 190 |
-
link.setAttribute('data-tooltip', tenetTooltips[anchor]);
|
| 191 |
-
}
|
| 192 |
-
});
|
| 193 |
-
|
| 194 |
-
// Update active state on scroll
|
| 195 |
-
window.addEventListener('scroll', function() {
|
| 196 |
-
const scrollPos = window.scrollY + 100;
|
| 197 |
-
headings.forEach((heading) => {
|
| 198 |
-
const link = document.querySelector('d-contents a[href="#' + heading.id + '"]');
|
| 199 |
-
if (link) {
|
| 200 |
-
if (heading.offsetTop <= scrollPos &&
|
| 201 |
-
heading.offsetTop + heading.offsetHeight > scrollPos) {
|
| 202 |
-
link.classList.add('active');
|
| 203 |
-
} else {
|
| 204 |
-
link.classList.remove('active');
|
| 205 |
-
}
|
| 206 |
-
}
|
| 207 |
-
});
|
| 208 |
-
});
|
| 209 |
-
}
|
| 210 |
-
}
|
| 211 |
-
|
| 212 |
-
// Initialize Prism syntax highlighting
|
| 213 |
-
function initializeSyntaxHighlighting() {
|
| 214 |
-
if (typeof Prism !== 'undefined') {
|
| 215 |
-
Prism.highlightAll();
|
| 216 |
-
}
|
| 217 |
-
}
|
| 218 |
-
|
| 219 |
-
// Try multiple times to ensure it runs after distill.js
|
| 220 |
-
document.addEventListener('DOMContentLoaded', function() {
|
| 221 |
-
initializeTOC();
|
| 222 |
-
initializeSyntaxHighlighting();
|
| 223 |
-
});
|
| 224 |
-
setTimeout(function() {
|
| 225 |
-
initializeTOC();
|
| 226 |
-
initializeSyntaxHighlighting();
|
| 227 |
-
}, 100);
|
| 228 |
-
setTimeout(function() {
|
| 229 |
-
initializeTOC();
|
| 230 |
-
initializeSyntaxHighlighting();
|
| 231 |
-
}, 500);
|
| 232 |
-
setTimeout(function() {
|
| 233 |
-
initializeTOC();
|
| 234 |
-
initializeSyntaxHighlighting();
|
| 235 |
-
}, 1000);
|
| 236 |
-
</script>`;
|
| 237 |
-
|
| 238 |
-
// Create full HTML document with distill template
|
| 239 |
-
const template = `<!DOCTYPE html>
|
| 240 |
-
<html>
|
| 241 |
-
<head>
|
| 242 |
-
<script src="distill.bundle.js" type="module" fetchpriority="high" blocking></script>
|
| 243 |
-
<script src="main.bundle.js" type="module" fetchpriority="low" defer></script>
|
| 244 |
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/components/prism-core.min.js"></script>
|
| 245 |
-
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
|
| 246 |
-
<script src="https://d3js.org/d3.v7.min.js"></script>
|
| 247 |
-
<meta name="viewport" content="width=device-width, initial-scale=1">
|
| 248 |
-
<meta charset="utf8">
|
| 249 |
-
<title>${appConfig.fullTitle}</title>
|
| 250 |
-
<link rel="stylesheet" href="style.css">
|
| 251 |
-
<link rel="stylesheet" href="transformers-custom.css">
|
| 252 |
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism.min.css">
|
| 253 |
-
</head>
|
| 254 |
-
<body>
|
| 255 |
-
<d-front-matter>
|
| 256 |
-
<script id='distill-front-matter' type="text/json">{
|
| 257 |
-
"title": "${appConfig.fullTitle}",
|
| 258 |
-
"description": "${appConfig.description}",
|
| 259 |
-
"published": "Aug 21, 2025",
|
| 260 |
-
"authors": [{"author": "Pablo Montalvo", "authorURL": "https://huggingface.co/Molbap"},
|
| 261 |
-
{"author": "Lysandre Debut", "authorURL": "https://huggingface.co/lysandre"},
|
| 262 |
-
{"author": "Pedro Cuenca", "authorURL": "https://huggingface.co/pcuenq"}
|
| 263 |
-
{"author": "Yoni Gozlan", "authorURL": "https://huggingface.co/yonigozlan"}]
|
| 264 |
-
}</script>
|
| 265 |
-
</d-front-matter>
|
| 266 |
-
<d-title>
|
| 267 |
-
<h1>${appConfig.fullTitle}</h1>
|
| 268 |
-
<p>${appConfig.description}</p>
|
| 269 |
-
</d-title>
|
| 270 |
-
<d-byline></d-byline>
|
| 271 |
-
<d-article>
|
| 272 |
-
<d-contents>
|
| 273 |
-
<nav role="navigation" class="l-text figcaption">
|
| 274 |
-
<div class="toc-header"><span class="toc-title">Table of Contents</span></div>
|
| 275 |
-
<div class="toc-content">
|
| 276 |
-
<div><a href="#introduction">Introduction</a></div>
|
| 277 |
-
<div style="margin-left: 1.2em;"><a href="#what-you-will-learn">What you will learn</a></div>
|
| 278 |
-
<div><a href="#source-of-truth">0. Source of truth</a></div>
|
| 279 |
-
<div><a href="#one-model-one-file">1. One model, one file</a></div>
|
| 280 |
-
<div><a href="#code-is-product">2. Code is product</a></div>
|
| 281 |
-
<div><a href="#standardize-dont-abstract">3. Standardize, don't abstract</a></div>
|
| 282 |
-
<div><a href="#do-repeat-yourself">4. DRY* (DO Repeat Yourself)</a></div>
|
| 283 |
-
<div><a href="#minimal-user-api">5. Minimal user API</a></div>
|
| 284 |
-
<div><a href="#backwards-compatibility">6. Backwards compatibility</a></div>
|
| 285 |
-
<div><a href="#consistent-public-surface">7. Consistent public surface</a></div>
|
| 286 |
-
<div><a href="#modular">Going modular</a></div>
|
| 287 |
-
<div><a href="#attention-classes">External Attention classes</a></div>
|
| 288 |
-
<div><a href="#encoders-ftw">Encoders win!</a></div>
|
| 289 |
-
</div>
|
| 290 |
-
</nav>
|
| 291 |
-
</d-contents>
|
| 292 |
-
${htmlContent}
|
| 293 |
-
</d-article>
|
| 294 |
-
${tocScript}
|
| 295 |
-
</body>
|
| 296 |
-
</html>`;
|
| 297 |
-
|
| 298 |
-
// Process with Handlebars for fragment insertion
|
| 299 |
-
const handlebars = Handlebars.compile(template);
|
| 300 |
-
return handlebars(fragments);
|
| 301 |
-
}
|
| 302 |
-
},
|
| 303 |
-
],
|
| 304 |
-
}),
|
| 305 |
-
],
|
| 306 |
-
devtool: process.env.NODE_ENV === 'production' ? 'source-map' : 'eval-source-map',
|
| 307 |
-
devServer: {
|
| 308 |
-
static: {
|
| 309 |
-
directory: path.join(__dirname, 'dist'),
|
| 310 |
-
},
|
| 311 |
-
hot: true,
|
| 312 |
-
watchFiles: ['src/**/*'],
|
| 313 |
-
client: {
|
| 314 |
-
overlay: true,
|
| 315 |
-
},
|
| 316 |
-
},
|
| 317 |
-
mode: process.env.NODE_ENV === 'production' ? 'production' : 'development',
|
| 318 |
-
optimization: {
|
| 319 |
-
minimizer: [
|
| 320 |
-
new ImageMinimizerPlugin({
|
| 321 |
-
minimizer: [{
|
| 322 |
-
implementation: ImageMinimizerPlugin.sharpMinify,
|
| 323 |
-
options: {
|
| 324 |
-
encodeOptions: {
|
| 325 |
-
jpeg: {
|
| 326 |
-
quality: 80
|
| 327 |
-
},
|
| 328 |
-
png: {
|
| 329 |
-
quality: 80
|
| 330 |
-
},
|
| 331 |
-
webp: {
|
| 332 |
-
quality: 80
|
| 333 |
-
}
|
| 334 |
-
}
|
| 335 |
-
}
|
| 336 |
-
},
|
| 337 |
-
{
|
| 338 |
-
implementation: ImageMinimizerPlugin.svgoMinify,
|
| 339 |
-
options: {
|
| 340 |
-
encodeOptions: {
|
| 341 |
-
multipass: true,
|
| 342 |
-
plugins: [
|
| 343 |
-
'preset-default',
|
| 344 |
-
]
|
| 345 |
-
}
|
| 346 |
-
}
|
| 347 |
-
}
|
| 348 |
-
]
|
| 349 |
-
}),
|
| 350 |
-
]
|
| 351 |
-
},
|
| 352 |
-
};
|
| 353 |
-
|
| 354 |
-
console.log(process.env.NODE_ENV)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|