mirror of
https://github.com/cyclotruc/gitingest.git
synced 2026-04-26 15:40:40 +00:00
chore(pre-commit) / refactor(templates): add ESLint pre-commit hook + refactor result.jinja (#379)
* chore(pre-commit) / refactor(templates): add ESLint hook + refactor `result.jinja` * Add `eslint` to `pre-commit` hooks * `getFileName` + `toggleFile` moved to `utils.js` * Run linter
This commit is contained in:
parent
1c80d7a69c
commit
dead917060
10 changed files with 334 additions and 194 deletions
|
|
@ -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."
|
||||
- id: trailing-whitespace
|
||||
description: "Trim trailing whitespace."
|
||||
description: 'Ensure that a file is either empty, or ends with one newline.'
|
||||
|
||||
- id: 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,
|
||||
]
|
||||
|
||||
|
|
|
|||
74
eslint.config.cjs
Normal file
74
eslint.config.cjs
Normal file
|
|
@ -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',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
|
@ -1,57 +1 @@
|
|||
<script>
|
||||
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;
|
||||
}
|
||||
|
||||
// Only include directories that are one level above the previous
|
||||
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 the first two tree lines (header and repository name)
|
||||
if (treeLineElements[0] === element || treeLineElements[1] === element) {
|
||||
return;
|
||||
}
|
||||
|
||||
element.classList.toggle('line-through');
|
||||
element.classList.toggle('text-gray-500');
|
||||
|
||||
const fileName = getFileName(element);
|
||||
const fileIndex = patternFiles.indexOf(fileName);
|
||||
|
||||
if (fileIndex !== -1) {
|
||||
patternFiles.splice(fileIndex, 1);
|
||||
} else {
|
||||
patternFiles.push(fileName);
|
||||
}
|
||||
|
||||
patternInput.value = patternFiles.join(", ");
|
||||
}
|
||||
</script>
|
||||
<div class="mt-10" data-results></div>
|
||||
|
|
|
|||
|
|
@ -1,15 +1,32 @@
|
|||
<style type="text/tailwindcss">
|
||||
@layer components {
|
||||
.badge-new { @apply inline-block -rotate-6 -translate-y-1 mx-1 px-1 bg-[#FE4A60] border border-gray-900 text-white text-[10px] font-bold shadow-[2px_2px_0_0_rgba(0,0,0,1)]; }
|
||||
.landing-page-title { @apply inline-block w-full relative text-center text-4xl sm:text-5xl md:text-6xl lg:text-7xl sm:pt-20 lg:pt-5 font-bold tracking-tighter; }
|
||||
.intro-text { @apply text-center text-gray-600 text-lg max-w-2xl mx-auto; }
|
||||
.sparkle-red { @apply absolute flex-shrink-0 h-auto w-14 sm:w-20 md:w-24 p-2 left-0 lg:ml-32 -translate-x-2 md:translate-x-10 lg:-translate-x-full -translate-y-4 sm:-translate-y-8 md:-translate-y-0 lg:-translate-y-10; }
|
||||
.sparkle-green { @apply absolute flex-shrink-0 right-0 bottom-0 w-10 sm:w-16 lg:w-20 -translate-x-10 lg:-translate-x-12 translate-y-4 sm:translate-y-10 md:translate-y-2 lg:translate-y-4; }
|
||||
.pattern-select { @apply min-w-max appearance-none pr-6 pl-2 py-2 bg-[#e6e8eb] border-r-[3px] border-gray-900 cursor-pointer focus:outline-none; }
|
||||
@layer components {
|
||||
.badge-new {
|
||||
@apply inline-block -rotate-6 -translate-y-1 mx-1 px-1 bg-[#FE4A60] border border-gray-900 text-white text-[10px] font-bold shadow-[2px_2px_0_0_rgba(0,0,0,1)];
|
||||
}
|
||||
.landing-page-title {
|
||||
@apply inline-block w-full relative text-center text-4xl sm:text-5xl md:text-6xl lg:text-7xl sm:pt-20 lg:pt-5 font-bold tracking-tighter;
|
||||
}
|
||||
.intro-text {
|
||||
@apply text-center text-gray-600 text-lg max-w-2xl mx-auto;
|
||||
}
|
||||
.sparkle-red {
|
||||
@apply absolute flex-shrink-0 h-auto w-14 sm:w-20 md:w-24 p-2 left-0 lg:ml-32 -translate-x-2 md:translate-x-10 lg:-translate-x-full -translate-y-4 sm:-translate-y-8 md:-translate-y-0 lg:-translate-y-10;
|
||||
}
|
||||
.sparkle-green {
|
||||
@apply absolute flex-shrink-0 right-0 bottom-0 w-10 sm:w-16 lg:w-20 -translate-x-10 lg:-translate-x-12 translate-y-4 sm:translate-y-10 md:translate-y-2 lg:translate-y-4;
|
||||
}
|
||||
.pattern-select {
|
||||
@apply min-w-max appearance-none pr-6 pl-2 py-2 bg-[#e6e8eb] border-r-[3px] border-gray-900 cursor-pointer focus:outline-none;
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.no-drag { @apply pointer-events-none select-none; -webkit-user-drag: none; }
|
||||
.link-bounce { @apply transition-transform hover:-translate-y-0.5; }
|
||||
@layer utilities {
|
||||
.no-drag {
|
||||
@apply pointer-events-none select-none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
.link-bounce {
|
||||
@apply transition-transform hover:-translate-y-0.5;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -1,22 +1,26 @@
|
|||
// Fetch GitHub stars
|
||||
function formatStarCount(count) {
|
||||
if (count >= 1000) return (count / 1000).toFixed(1) + 'k';
|
||||
return count.toString();
|
||||
}
|
||||
if (count >= 1000) {return `${ (count / 1000).toFixed(1) }k`;}
|
||||
|
||||
async function fetchGitHubStars() {
|
||||
return count.toString();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// auto-run when script loads
|
||||
fetchGitHubStars();
|
||||
if (el) {el.style.display = 'none';}
|
||||
}
|
||||
}
|
||||
|
||||
// auto-run when script loads
|
||||
fetchGitHubStars();
|
||||
|
|
|
|||
|
|
@ -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]);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = `
|
||||
<div class="relative mt-10">
|
||||
<div class="w-full h-full absolute inset-0 bg-black rounded-xl translate-y-2 translate-x-2"></div>
|
||||
|
|
@ -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 = `<div class='mb-6 p-4 bg-red-50 border border-red-200 rounded-lg text-red-700'>${data.error}</div>`;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -194,14 +259,16 @@ function handleSubmit(event, showLoading = false) {
|
|||
|
||||
// Populate directory structure lines as clickable <pre> 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 = `<div class='mb-6 p-4 bg-red-50 border border-red-200 rounded-lg text-red-700'>${error}</div>`;
|
||||
const errorContainer = document.querySelector('[data-results]');
|
||||
|
||||
if (errorContainer) {
|
||||
errorContainer.innerHTML = `<div class='mb-6 p-4 bg-red-50 border border-red-200 rounded-lg text-red-700'>${error}</div>`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -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';
|
||||
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue