From 5c066c81e417bc37802009b7beaea865d7dad68f Mon Sep 17 00:00:00 2001 From: Filip Christiansen <22807962+filipchristiansen@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:16:31 +0200 Subject: [PATCH 1/2] chore(pre-commit) / refactor(templates): add ESLint hook + remove `result.jinja` * Add `eslint` to `pre-commit` hooks * Remove `result.jinja` * `getFileName` + `toggleFile` moved to `utils.js` * `getFileName` + `toggleFile` moved to `utils.js` * leftover `
` extracted to `_macros.jinja` as `results_container()` * Run linter --- .pre-commit-config.yaml | 80 +++++---- eslint.config.cjs | 74 +++++++++ src/server/templates/components/_macros.jinja | 4 + src/server/templates/components/result.jinja | 57 ------- .../components/tailwind_components.html | 37 +++-- src/server/templates/git.jinja | 3 +- src/server/templates/index.jinja | 3 +- src/static/js/git.js | 22 +-- src/static/js/git_form.js | 41 ++--- src/static/js/index.js | 3 +- src/static/js/navbar.js | 30 ++-- src/static/js/posthog.js | 23 +-- src/static/js/utils.js | 156 +++++++++++++----- 13 files changed, 339 insertions(+), 194 deletions(-) create mode 100644 eslint.config.cjs delete mode 100644 src/server/templates/components/result.jinja diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6c0d6c13..f38e4d1f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,65 +2,82 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v5.0.0 hooks: - # Files - id: check-added-large-files - description: "Prevent large files from being committed." - args: ["--maxkb=10000"] + description: 'Prevent large files from being committed.' + args: ['--maxkb=10000'] + - id: check-case-conflict - description: "Check for files that would conflict in case-insensitive filesystems." + description: 'Check for files that would conflict in case-insensitive filesystems.' + - id: fix-byte-order-marker - description: "Remove utf-8 byte order marker." + description: 'Remove utf-8 byte order marker.' + - id: mixed-line-ending - description: "Replace mixed line ending." + description: 'Replace mixed line ending.' - # Links - id: destroyed-symlinks - description: "Detect symlinks which are changed to regular files with a content of a path which that symlink was pointing to." + description: 'Detect symlinks which are changed to regular files with a content of a path which that symlink was pointing to.' - # File files for parseable syntax: python - id: check-ast + description: 'Check for parseable syntax.' - # File and line endings - id: end-of-file-fixer - description: "Ensure that a file is either empty, or ends with one newline." + description: 'Ensure that a file is either empty, or ends with one newline.' + - id: trailing-whitespace - description: "Trim trailing whitespace." + description: 'Trim trailing whitespace.' - # Python - id: check-docstring-first - description: "Check a common error of defining a docstring after code." + description: 'Check a common error of defining a docstring after code.' + - id: requirements-txt-fixer - description: "Sort entries in requirements.txt." + description: 'Sort entries in requirements.txt.' - repo: https://github.com/MarcoGorelli/absolufy-imports rev: v0.3.1 hooks: - id: absolufy-imports - description: "Automatically convert relative imports to absolute. (Use `args: [--never]` to revert.)" + description: 'Automatically convert relative imports to absolute. (Use `args: [--never]` to revert.)' - repo: https://github.com/asottile/pyupgrade rev: v3.20.0 hooks: - id: pyupgrade - description: "Automatically upgrade syntax for newer versions." + description: 'Automatically upgrade syntax for newer versions.' args: [--py3-plus, --py36-plus] - repo: https://github.com/pre-commit/pygrep-hooks rev: v1.10.0 hooks: - id: python-check-blanket-noqa - description: "Enforce that `noqa` annotations always occur with specific codes. Sample annotations: `# noqa: F401`, `# noqa: F401,W203`." + description: 'Enforce that `# noqa` annotations always occur with specific codes.' + - id: python-check-blanket-type-ignore - description: "Enforce that `# type: ignore` annotations always occur with specific codes. Sample annotations: `# type: ignore[attr-defined]`, `# type: ignore[attr-defined, name-defined]`." + description: 'Enforce that `# type: ignore` annotations always occur with specific codes.' + - id: python-use-type-annotations - description: "Enforce that python3.6+ type annotations are used instead of type comments." + description: 'Enforce that python3.6+ type annotations are used instead of type comments.' - repo: https://github.com/PyCQA/isort rev: 6.0.1 hooks: - id: isort - description: "Sort imports alphabetically, and automatically separated into sections and by type." + description: 'Sort imports alphabetically, and automatically separated into sections and by type.' + - repo: https://github.com/pre-commit/mirrors-eslint + rev: v9.30.1 + hooks: + - id: eslint + description: 'Lint javascript files.' + files: \.js$ + args: [--max-warnings=0, --fix] + additional_dependencies: + [ + 'eslint@9.30.1', + '@eslint/js@9.30.1', + 'eslint-plugin-import@2.32.0', + 'globals@16.3.0', + ] - repo: https://github.com/djlint/djLint rev: v1.36.4 @@ -71,11 +88,11 @@ repos: rev: v0.45.0 hooks: - id: markdownlint - description: "Lint markdown files." - args: ["--disable=line-length"] + description: 'Lint markdown files.' + args: ['--disable=line-length'] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.1 + rev: v0.12.2 hooks: - id: ruff-check - id: ruff-format @@ -97,17 +114,19 @@ repos: additional_dependencies: [ click>=8.0.0, - "fastapi[standard]>=0.109.1", + 'fastapi[standard]>=0.109.1', + httpx, + pathspec>=0.12.1, pydantic, pytest-asyncio, pytest-mock, python-dotenv, slowapi, starlette>=0.40.0, - tiktoken, - pathspec, + tiktoken>=0.7.0, uvicorn>=0.11.7, ] + - id: pylint name: pylint for tests files: ^tests/ @@ -116,15 +135,16 @@ repos: additional_dependencies: [ click>=8.0.0, - "fastapi[standard]>=0.109.1", + 'fastapi[standard]>=0.109.1', + httpx, + pathspec>=0.12.1, pydantic, pytest-asyncio, pytest-mock, python-dotenv, slowapi, starlette>=0.40.0, - tiktoken, - pathspec, + tiktoken>=0.7.0, uvicorn>=0.11.7, ] diff --git a/eslint.config.cjs b/eslint.config.cjs new file mode 100644 index 00000000..1308480d --- /dev/null +++ b/eslint.config.cjs @@ -0,0 +1,74 @@ +const js = require('@eslint/js'); +const globals = require('globals'); +const importPlugin = require('eslint-plugin-import'); + +module.exports = [ + js.configs.recommended, + + { + files: ['src/static/js/**/*.js'], + + languageOptions: { + parserOptions: { ecmaVersion: 2021, sourceType: 'module' }, + globals: { + ...globals.browser, + changePattern: 'readonly', + copyFullDigest: 'readonly', + copyText: 'readonly', + downloadFullDigest: 'readonly', + handleSubmit: 'readonly', + posthog: 'readonly', + submitExample: 'readonly', + toggleAccessSettings: 'readonly', + toggleFile: 'readonly', + }, + }, + + plugins: { import: importPlugin }, + + rules: { + // Import hygiene (eslint-plugin-import) + 'import/no-extraneous-dependencies': 'error', + 'import/no-unresolved': 'error', + 'import/order': ['warn', { alphabetize: { order: 'asc' } }], + + // Safety & bug-catchers + 'consistent-return': 'error', + 'default-case': 'error', + 'no-implicit-globals': 'error', + 'no-shadow': 'error', + + // Maintainability / complexity + complexity: ['warn', 10], + 'max-depth': ['warn', 4], + 'max-lines': ['warn', 500], + 'max-params': ['warn', 5], + + // Stylistic consistency (auto-fixable) + 'arrow-parens': ['error', 'always'], + curly: ['error', 'all'], + indent: ['error', 4, { SwitchCase: 2 }], + 'newline-per-chained-call': ['warn', { ignoreChainWithDepth: 2 }], + 'no-multi-spaces': 'error', + 'object-shorthand': ['error', 'always'], + 'padding-line-between-statements': [ + 'warn', + { blankLine: 'always', prev: '*', next: 'return' }, + { blankLine: 'always', prev: ['const', 'let', 'var'], next: '*' }, + { blankLine: 'any', prev: ['const', 'let', 'var'], next: ['const', 'let', 'var'] }, + ], + 'quote-props': ['error', 'consistent-as-needed'], + quotes: ['error', 'single', { avoidEscape: true }], + semi: 'error', + + // Modern / performance tips + 'arrow-body-style': ['warn', 'as-needed'], + 'prefer-arrow-callback': 'error', + 'prefer-exponentiation-operator': 'error', + 'prefer-numeric-literals': 'error', + 'prefer-object-has-own': 'warn', + 'prefer-object-spread': 'error', + 'prefer-template': 'error', + }, + }, +]; diff --git a/src/server/templates/components/_macros.jinja b/src/server/templates/components/_macros.jinja index 224fcbba..3a565199 100644 --- a/src/server/templates/components/_macros.jinja +++ b/src/server/templates/components/_macros.jinja @@ -8,3 +8,7 @@ {{ label }} {%- endmacro %} +{# Results container (empty - JS will populate it) #} +{% macro results_container() -%} +
+{%- endmacro %} diff --git a/src/server/templates/components/result.jinja b/src/server/templates/components/result.jinja deleted file mode 100644 index d049df3b..00000000 --- a/src/server/templates/components/result.jinja +++ /dev/null @@ -1,57 +0,0 @@ - -
diff --git a/src/server/templates/components/tailwind_components.html b/src/server/templates/components/tailwind_components.html index 9be88f7a..f0039407 100644 --- a/src/server/templates/components/tailwind_components.html +++ b/src/server/templates/components/tailwind_components.html @@ -1,15 +1,32 @@ diff --git a/src/server/templates/git.jinja b/src/server/templates/git.jinja index 9d5fe653..fedd8e94 100644 --- a/src/server/templates/git.jinja +++ b/src/server/templates/git.jinja @@ -1,4 +1,5 @@ {% extends "base.jinja" %} +{% from 'components/_macros.jinja' import results_container %} {% block content %} {% if error_message %}
@@ -25,5 +26,5 @@

You can also replace 'hub' with 'ingest' in any GitHub URL.

- {% include 'components/result.jinja' %} + {{ results_container() }} {% endblock %} diff --git a/src/static/js/git.js b/src/static/js/git.js index 7ddc6a90..8879063b 100644 --- a/src/static/js/git.js +++ b/src/static/js/git.js @@ -1,27 +1,29 @@ - function waitForStars() { return new Promise((resolve) => { const check = () => { - const stars = document.getElementById("github-stars"); - if (stars && stars.textContent !== "0") resolve(); - else setTimeout(check, 10); + const stars = document.getElementById('github-stars'); + + if (stars && stars.textContent !== '0') {resolve();} + else {setTimeout(check, 10);} }; + check(); }); } -document.addEventListener("DOMContentLoaded", () => { - const urlInput = document.getElementById("input_text"); - const form = document.getElementById("ingestForm"); +document.addEventListener('DOMContentLoaded', () => { + const urlInput = document.getElementById('input_text'); + const form = document.getElementById('ingestForm'); if (urlInput && urlInput.value.trim() && form) { - // Wait for stars to be loaded before submitting + // Wait for stars to be loaded before submitting waitForStars().then(() => { - const submitEvent = new SubmitEvent("submit", { + const submitEvent = new SubmitEvent('submit', { cancelable: true, bubbles: true }); - Object.defineProperty(submitEvent, "target", { + + Object.defineProperty(submitEvent, 'target', { value: form, enumerable: true }); diff --git a/src/static/js/git_form.js b/src/static/js/git_form.js index e8eb78b0..217b4b6b 100644 --- a/src/static/js/git_form.js +++ b/src/static/js/git_form.js @@ -1,44 +1,45 @@ // Strike-through / un-strike file lines when the pattern-type menu flips. function changePattern() { - const files = document.getElementsByName("tree-line"); + const files = document.getElementsByName('tree-line'); files.forEach((el) => { - if (el.textContent.includes("Directory structure:")) return; + if (el.textContent.includes('Directory structure:')) {return;} [ - "line-through", - "text-gray-500", - "hover:text-inherit", - "hover:no-underline", - "hover:line-through", - "hover:text-gray-500", + 'line-through', + 'text-gray-500', + 'hover:text-inherit', + 'hover:no-underline', + 'hover:line-through', + 'hover:text-gray-500', ].forEach((cls) => el.classList.toggle(cls)); }); } // Show/hide the Personal-Access-Token section when the “Private repository” checkbox is toggled. function toggleAccessSettings() { - const container = document.getElementById("accessSettingsContainer"); - const examples = document.getElementById("exampleRepositories"); - const show = document.getElementById('showAccessSettings')?.checked; - container?.classList.toggle("hidden", !show); - examples?.classList.toggle("lg:mt-0", show); + const container = document.getElementById('accessSettingsContainer'); + const examples = document.getElementById('exampleRepositories'); + const show = document.getElementById('showAccessSettings')?.checked; + + container?.classList.toggle('hidden', !show); + examples?.classList.toggle('lg:mt-0', show); } -document.addEventListener("DOMContentLoaded", () => { +document.addEventListener('DOMContentLoaded', () => { document - .getElementById("pattern_type") - ?.addEventListener("change", () => changePattern()); + .getElementById('pattern_type') + ?.addEventListener('change', () => changePattern()); document - .getElementById("showAccessSettings") - ?.addEventListener("change", toggleAccessSettings); + .getElementById('showAccessSettings') + ?.addEventListener('change', toggleAccessSettings); - /* 3. Initial UI sync -------------------------------- */ + // Initial UI sync toggleAccessSettings(); changePattern(); - }); +}); // Make them available to existing inline attributes diff --git a/src/static/js/index.js b/src/static/js/index.js index a0a99cc2..0ad44ae8 100644 --- a/src/static/js/index.js +++ b/src/static/js/index.js @@ -1,5 +1,6 @@ function submitExample(repoName) { - const input = document.getElementById("input_text"); + const input = document.getElementById('input_text'); + if (input) { input.value = repoName; input.focus(); diff --git a/src/static/js/navbar.js b/src/static/js/navbar.js index f0db1a37..2e64eab4 100644 --- a/src/static/js/navbar.js +++ b/src/static/js/navbar.js @@ -1,22 +1,26 @@ // Fetch GitHub stars function formatStarCount(count) { - if (count >= 1000) return (count / 1000).toFixed(1) + 'k'; + if (count >= 1000) {return `${ (count / 1000).toFixed(1) }k`;} + return count.toString(); - } +} - async function fetchGitHubStars() { +async function fetchGitHubStars() { try { - const res = await fetch('https://api.github.com/repos/cyclotruc/gitingest'); - if (!res.ok) throw new Error(`${res.status} ${res.statusText}`); - const data = await res.json(); - document.getElementById('github-stars').textContent = + const res = await fetch('https://api.github.com/repos/cyclotruc/gitingest'); + + if (!res.ok) {throw new Error(`${res.status} ${res.statusText}`);} + const data = await res.json(); + + document.getElementById('github-stars').textContent = formatStarCount(data.stargazers_count); } catch (err) { - console.error('Error fetching GitHub stars:', err); - const el = document.getElementById('github-stars').parentElement; - if (el) el.style.display = 'none'; + console.error('Error fetching GitHub stars:', err); + const el = document.getElementById('github-stars').parentElement; + + if (el) {el.style.display = 'none';} } - } +} - // auto-run when script loads - fetchGitHubStars(); +// auto-run when script loads +fetchGitHubStars(); diff --git a/src/static/js/posthog.js b/src/static/js/posthog.js index bffa541b..5945b3cc 100644 --- a/src/static/js/posthog.js +++ b/src/static/js/posthog.js @@ -1,12 +1,13 @@ +/* eslint-disable */ !function (t, e) { - var o, n, p, r; - if (e.__SV) return; // already loaded + let o, n, p, r; + if (e.__SV) {return;} // already loaded window.posthog = e; e._i = []; e.init = function (i, s, a) { function g(t, e) { - var o = e.split("."); + const o = e.split("."); if (o.length === 2) { t = t[o[0]]; e = o[1]; @@ -20,12 +21,12 @@ p.type = "text/javascript"; p.crossOrigin = "anonymous"; p.async = true; - p.src = s.api_host.replace(".i.posthog.com", "-assets.i.posthog.com") + "/static/array.js"; + p.src = `${ s.api_host.replace(".i.posthog.com", "-assets.i.posthog.com") }/static/array.js`; r = t.getElementsByTagName("script")[0]; r.parentNode.insertBefore(p, r); - var u = e; + let u = e; if (a !== undefined) { u = e[a] = []; } else { @@ -34,13 +35,13 @@ u.people = u.people || []; u.toString = function (t) { - var e = "posthog"; - if (a !== "posthog") e += "." + a; - if (!t) e += " (stub)"; + let e = "posthog"; + if (a !== "posthog") {e += `.${ a }`;} + if (!t) {e += " (stub)";} return e; }; u.people.toString = function () { - return u.toString(1) + ".people (stub)"; + return `${ u.toString(1) }.people (stub)`; }; @@ -58,9 +59,9 @@ "createPersonProfile", "opt_in_capturing", "opt_out_capturing", "has_opted_in_capturing", "has_opted_out_capturing", "clear_opt_in_out_capturing", "debug", "getPageViewId" - ]; + ]; - for (n = 0; n < o.length; n++) g(u, o[n]); + for (n = 0; n < o.length; n++) {g(u, o[n]);} e._i.push([i, s, a]); }; diff --git a/src/static/js/utils.js b/src/static/js/utils.js index cbcc0f20..393fe12d 100644 --- a/src/static/js/utils.js +++ b/src/static/js/utils.js @@ -3,19 +3,22 @@ function copyText(className) { let textToCopy; if (className === 'directory-structure') { - // For directory structure, get the hidden input value + // For directory structure, get the hidden input value const hiddenInput = document.getElementById('directory-structure-content'); - if (!hiddenInput) return; + + if (!hiddenInput) {return;} textToCopy = hiddenInput.value; } else { - // For other elements, get the textarea value - const textarea = document.querySelector('.' + className); - if (!textarea) return; + // For other elements, get the textarea value + const textarea = document.querySelector(`.${ className }`); + + if (!textarea) {return;} textToCopy = textarea.value; } const button = document.querySelector(`button[onclick="copyText('${className}')"]`); - if (!button) return; + + if (!button) {return;} // Copy text navigator.clipboard.writeText(textToCopy) @@ -31,9 +34,10 @@ function copyText(className) { button.innerHTML = originalContent; }, 1000); }) - .catch(err => { - // Show error in button + .catch((err) => { + console.error('Failed to copy text:', err); const originalContent = button.innerHTML; + button.innerHTML = 'Failed to copy'; setTimeout(() => { button.innerHTML = originalContent; @@ -41,17 +45,74 @@ function copyText(className) { }); } +function getFileName(element) { + const indentSize = 4; + let path = ''; + let prevIndentLevel = null; + + while (element) { + const line = element.textContent; + const index = line.search(/[a-zA-Z0-9_.-]/); + const indentLevel = index / indentSize; + + // Stop when we reach or go above the top-level directory + if (indentLevel <= 1) { + break; + } + if (prevIndentLevel === null || indentLevel === prevIndentLevel - 1) { + const fileName = line.substring(index).trim(); + + path = fileName + path; + prevIndentLevel = indentLevel; + } + element = element.previousElementSibling; + } + + return path; +} + +function toggleFile(element) { + const patternInput = document.getElementById('pattern'); + const patternFiles = patternInput.value + ? patternInput.value.split(',').map((item) => item.trim()) + : []; + + const directoryContainer = document.getElementById('directory-structure-container'); + const treeLineElements = Array.from(directoryContainer.children).filter( + (child) => child.tagName === 'PRE', + ); + + // Skip header and repository name + if (treeLineElements.slice(0, 2).includes(element)) { + return; + } + + element.classList.toggle('line-through'); + element.classList.toggle('text-gray-500'); + + const fileName = getFileName(element); + const idx = patternFiles.indexOf(fileName); + + if (idx !== -1) { + patternFiles.splice(idx, 1); + } else { + patternFiles.push(fileName); + } + + patternInput.value = patternFiles.join(', '); +} function handleSubmit(event, showLoading = false) { event.preventDefault(); const form = event.target || document.getElementById('ingestForm'); - if (!form) return; + + if (!form) {return;} // Declare resultsSection before use const resultsSection = document.querySelector('[data-results]'); if (resultsSection) { - // Show in-content loading spinner + // Show in-content loading spinner resultsSection.innerHTML = `
@@ -64,12 +125,14 @@ function handleSubmit(event, showLoading = false) { } const submitButton = form.querySelector('button[type="submit"]'); - if (!submitButton) return; + + if (!submitButton) {return;} const formData = new FormData(form); // Update file size const slider = document.getElementById('file_size'); + if (slider) { formData.delete('max_file_size'); formData.append('max_file_size', slider.value); @@ -78,6 +141,7 @@ function handleSubmit(event, showLoading = false) { // Update pattern type and pattern const patternType = document.getElementById('pattern_type'); const pattern = document.getElementById('pattern'); + if (patternType && pattern) { formData.delete('pattern_type'); formData.delete('pattern'); @@ -102,19 +166,20 @@ function handleSubmit(event, showLoading = false) { } // Submit the form to /api/ingest - fetch('/api/ingest', {method: 'POST', body: formData}) - .then(response => response.json()) - .then(data => { + fetch('/api/ingest', { method: 'POST', body: formData }) + .then((response) => response.json()) + .then((data) => { // Hide loading overlay - if (resultsSection) resultsSection.innerHTML = ''; + if (resultsSection) {resultsSection.innerHTML = '';} submitButton.disabled = false; submitButton.innerHTML = originalContent; - if (!resultsSection) return; + if (!resultsSection) {return;} // Handle error if (data.error) { resultsSection.innerHTML = `
${data.error}
`; + return; } @@ -194,14 +259,16 @@ function handleSubmit(event, showLoading = false) { // Populate directory structure lines as clickable
 elements
             const dirPre = document.getElementById('directory-structure-pre');
+
             if (dirPre && data.tree) {
                 dirPre.innerHTML = '';
-                data.tree.split('\n').forEach(line => {
+                data.tree.split('\n').forEach((line) => {
                     const pre = document.createElement('pre');
+
                     pre.setAttribute('name', 'tree-line');
                     pre.className = 'cursor-pointer hover:line-through hover:text-gray-500';
                     pre.textContent = line;
-                    pre.onclick = function() { toggleFile(this); };
+                    pre.onclick = function () { toggleFile(this); };
                     dirPre.appendChild(pre);
                 });
             }
@@ -209,14 +276,17 @@ function handleSubmit(event, showLoading = false) {
             // Scroll to results
             resultsSection.scrollIntoView({ behavior: 'smooth', block: 'start' });
         })
-        .catch(error => {
+        .catch((error) => {
             // Hide loading overlay
-            if (resultsSection) resultsSection.innerHTML = '';
+            if (resultsSection) {
+                resultsSection.innerHTML = '';
+            }
             submitButton.disabled = false;
             submitButton.innerHTML = originalContent;
-            const resultsSection = document.querySelector('[data-results]');
-            if (resultsSection) {
-                resultsSection.innerHTML = `
${error}
`; + const errorContainer = document.querySelector('[data-results]'); + + if (errorContainer) { + errorContainer.innerHTML = `
${error}
`; } }); } @@ -239,9 +309,10 @@ function copyFullDigest() { setTimeout(() => { button.innerHTML = originalText; }, 2000); - }).catch(err => { - console.error('Failed to copy text: ', err); - }); + }) + .catch((err) => { + console.error('Failed to copy text: ', err); + }); } function downloadFullDigest() { @@ -258,8 +329,9 @@ function downloadFullDigest() { // Create a download link const url = window.URL.createObjectURL(blob); const a = document.createElement('a'); + a.href = url; - a.download = 'codebase-digest.txt'; + a.download = 'digest.txt'; document.body.appendChild(a); a.click(); @@ -288,7 +360,8 @@ function logSliderToSize(position) { const maxPosition = 500; const maxValue = Math.log(102400); // 100 MB - const value = Math.exp(maxValue * Math.pow(position / maxPosition, 1.5)); + const value = Math.exp(maxValue * (position / maxPosition)**1.5); + return Math.round(value); } @@ -297,10 +370,11 @@ function initializeSlider() { const slider = document.getElementById('file_size'); const sizeValue = document.getElementById('size_value'); - if (!slider || !sizeValue) return; + if (!slider || !sizeValue) {return;} function updateSlider() { const value = logSliderToSize(slider.value); + sizeValue.textContent = formatSize(value); slider.style.backgroundSize = `${(slider.value / slider.max) * 100}% 100%`; } @@ -315,24 +389,18 @@ function initializeSlider() { // Add helper function for formatting size function formatSize(sizeInKB) { if (sizeInKB >= 1024) { - return Math.round(sizeInKB / 1024) + 'MB'; + return `${ Math.round(sizeInKB / 1024) }MB`; } - return Math.round(sizeInKB) + 'kB'; -} -// Make sure these are available globally -window.copyText = copyText; - -window.handleSubmit = handleSubmit; -window.initializeSlider = initializeSlider; -window.formatSize = formatSize; -window.downloadFullDigest = downloadFullDigest; + return `${ Math.round(sizeInKB) }kB`; +} // Add this new function function setupGlobalEnterHandler() { - document.addEventListener('keydown', function (event) { + document.addEventListener('keydown', (event) => { if (event.key === 'Enter' && !event.target.matches('textarea')) { const form = document.getElementById('ingestForm'); + if (form) { handleSubmit(new Event('submit'), true); } @@ -345,3 +413,11 @@ document.addEventListener('DOMContentLoaded', () => { initializeSlider(); setupGlobalEnterHandler(); }); + + +// Make sure these are available globally +window.handleSubmit = handleSubmit; +window.toggleFile = toggleFile; +window.copyText = copyText; +window.copyFullDigest = copyFullDigest; +window.downloadFullDigest = downloadFullDigest; From edfd88dd609637ab9186dfbc03c9b77586ddbf11 Mon Sep 17 00:00:00 2001 From: Filip Christiansen <22807962+filipchristiansen@users.noreply.github.com> Date: Fri, 4 Jul 2025 17:32:17 +0200 Subject: [PATCH 2/2] pr fix --- src/server/templates/components/_macros.jinja | 4 ---- src/server/templates/components/result.jinja | 1 + src/server/templates/git.jinja | 3 +-- src/server/templates/index.jinja | 3 +-- 4 files changed, 3 insertions(+), 8 deletions(-) create mode 100644 src/server/templates/components/result.jinja diff --git a/src/server/templates/components/_macros.jinja b/src/server/templates/components/_macros.jinja index 3a565199..224fcbba 100644 --- a/src/server/templates/components/_macros.jinja +++ b/src/server/templates/components/_macros.jinja @@ -8,7 +8,3 @@ {{ label }} {%- endmacro %} -{# Results container (empty - JS will populate it) #} -{% macro results_container() -%} -
-{%- endmacro %} diff --git a/src/server/templates/components/result.jinja b/src/server/templates/components/result.jinja new file mode 100644 index 00000000..a5a0a803 --- /dev/null +++ b/src/server/templates/components/result.jinja @@ -0,0 +1 @@ +
diff --git a/src/server/templates/git.jinja b/src/server/templates/git.jinja index fedd8e94..9d5fe653 100644 --- a/src/server/templates/git.jinja +++ b/src/server/templates/git.jinja @@ -1,5 +1,4 @@ {% extends "base.jinja" %} -{% from 'components/_macros.jinja' import results_container %} {% block content %} {% if error_message %}
@@ -26,5 +25,5 @@

You can also replace 'hub' with 'ingest' in any GitHub URL.

- {{ results_container() }} + {% include 'components/result.jinja' %} {% endblock %}