Skip to content

gloryknight/IA_file_extractor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 

Repository files navigation

✨ LLM Code Exporter Bookmarklet ✨

License: MIT Stars

Tired of manually copying and pasting multiple code snippets from Large Language Model (LLM) responses like ChatGPT, Claude, Gemini, etc.? This simple bookmarklet extracts all code blocks from the current page, attempts to detect their filenames, packages them into a structured .tar archive, and downloads it – all with one click!

Say goodbye to tedious copy-pasting and lost file structure! 🚀

Features

  • 🖱️ One-Click Extraction: Grab all code blocks instantly.
  • 📄 Filename Detection: Intelligently guesses filenames from text preceding the code blocks (e.g., path/to/your/file.py).
  • 🏷️ Language-Based Fallback: Uses code block language (e.g., language-python) to assign extensions (.py) if no filename is found.
  • 📦 TAR Archive: Packages files into a .tar archive, preserving directory structures mentioned in filenames (e.g., src/utils/helper.js).
  • 🌐 Browser-Based: Runs entirely in your browser, no installation needed.
  • Self-Contained: Includes a minimal TAR implementation – no external libraries required.
  • 📝 UTF-8 Support: Handles UTF-8 characters within the code content.

How to Use

There are two easy ways to install the bookmarklet:

Method 1: Drag and Drop (Recommended):

  1. Drag and Drop following link to your bookmark bar: Export LLM Code

Usage:

  1. Navigate to the page containing the LLM response with code blocks you want to save.
  2. Click the Export LLM Code bookmarklet you created.
  3. A .tar file (e.g., llm_response_export.tar) containing the extracted code files will be downloaded automatically!

Method 2: Copy & Paste

  1. Bookmark Any Page: Create a new bookmark in your browser (Ctrl+D or Cmd+D). Name it something memorable like Export LLM Code.
  2. Edit the Bookmark: Right-click the new bookmark and choose "Edit" or "Properties".
  3. Replace URL: Delete the current content in the "URL" or "Location" field.
  4. Paste the Code: Copy the link location from above and paste it into the "URL" / "Location" field.
  5. Save: Save the changes to the bookmark.

Method 3: Manual Execute

  1. Paste the Code: Copy the minified code below and paste it into the bowsers console (F12 -> Console).:

    !function(){if("/gloryknight/IA_file_extractor"===document.location.pathname)return;let e=/[`\*]?([\w\/.-]+\.\w+)[`\*]?$/i;console.log("Bookmarklet: Starting code extraction...");let t=document.querySelectorAll("pre > code"),l=[],n=1;if(0===t.length){console.log('Bookmarklet: No code blocks found using selector "pre > code".');return}if(t.forEach(t=>{let o=t.closest("pre");if(!o)return;let r=t.textContent;if(!r||""===r.trim()){console.log("Bookmarklet: Skipping empty code block.");return}let i="",$=o.previousElementSibling,s=0;for(;$&&s<3;){let a=$.textContent?.trim();if(a){let c=a.match(e);if(c&&c[1]&&c[1].length<150&&!c[1].includes(" ")&&c[1].includes(".")){i=c[1],console.log(`Bookmarklet: Found potential filename "${i}" in preceding element.`);break}}$=$.previousElementSibling,s++}if(!i){let p=".txt",f=Array.from(t.classList).find(e=>e.startsWith("language-"));if(f){let u=f.substring(9),g={python:".py",javascript:".js",html:".html",css:".css",bash:".sh",shell:".sh",java:".java",csharp:".cs",cpp:".cpp",c:".c",typescript:".ts",json:".json",yaml:".yaml",markdown:".md",sql:".sql",xml:".xml",dockerfile:".dockerfile",plaintext:".txt"};g[u]?p=g[u]:u&&(p="."+u)}i=`file_${n}${p}`,console.log(`Bookmarklet: Could not find filename, using default: "${i}"`)}i=i.replace(/^\/+/,"").replace(/\.\.\//g,""),l.push({name:i,content:r}),n++}),l.length>0)try{let o=function e(t){let l=[];function n(e,t){let l=[],n=0;for(let o=0;o<e.length&&n<t;o++){let r=e.charCodeAt(o);r<128?(l.push(r),n++):console.warn("Non-ASCII character skipped in TAR header string:",e[o])}for(;l.length<t;)l.push(0);return l}function o(e,t){let l=e.toString(8),o="0".repeat(t-1-l.length)+l+"\0";return n(o,t)}t.forEach(e=>{let t=function e(t){let l=[];for(let n=0;n<t.length;n++){let o=t.charCodeAt(n);o<128?l.push(o):o<2048?l.push(192|o>>6,128|63&o):o<65536?l.push(224|o>>12,128|o>>6&63,128|63&o):l.push(240|o>>18,128|o>>12&63,128|o>>6&63,128|63&o)}return l}(e.content),r=t.length,i=e.name,$="";if(i.length>100){let s=-1;for(let a=Math.min(i.length,155)-1;a>=0;a--)if("/"===i[a]){let c=i.substring(0,a),p=i.substring(a+1);if(c.length<=155&&p.length<=100){s=a;break}}-1!==s?($=i.substring(0,s),i=i.substring(s+1)):(console.warn(`Filename "${e.name}" too long and could not be split cleanly for TAR. Truncating.`),$=i.substring(0,155),i=i.substring(155,255))}let f=new Uint8Array(512),u=0,g=[i,100,420,8,0,8,0,8,r,12,Math.floor(Date.now()/1e3),12,"        ",8,"0",1,"",100,"ustar\0",6,"00",2,"user",32,"group",32,0,8,0,8,$,155];for(let h=0;h<g.length;h+=2){let _=g[h],m=g[h+1];"string"==typeof _?f.set(n(_,m),u):f.set(o(_,m),u),u+=m}let d=0;for(let k=0;k<512;k++)d+=f[k];f.set(o(d,8),148),l.push(...f),l.push(...t);let x=(512-r%512)%512;for(let b=0;b<x;b++)l.push(0)});let r=new Uint8Array(512);return l.push(...r,...r),new Uint8Array(l)}(l),r=new Blob([o],{type:"application/x-tar"}),i=(document.title||"llm_export").replace(/[^a-z0-9_-]/gi,"_").replace(/_+/g,"_");i.length>50&&(i=i.substring(0,50)),i=i||"llm_code_export",i+=".tar",function e(t,l){let n=URL.createObjectURL(t),o=document.createElement("a");o.href=n,o.download=l,o.style.display="none",document.body.appendChild(o),o.click(),document.body.removeChild(o),URL.revokeObjectURL(n)}(r,i),console.log(`Bookmarklet: Successfully packaged ${l.length} file(s) into "${i}".`)}catch($){console.error("Bookmarklet Error:",$)}else console.log("Bookmarklet: No non-empty code blocks were found to package.")}();
  2. Execute the Code: Press enter after pasting.

How It Works

The bookmarklet executes JavaScript in the context of the current page:

  1. It finds all <pre><code> elements.
  2. For each code block, it searches the preceding sibling elements for text that looks like a filename (using regex).
  3. If no filename is found, it checks the code block's class for a language (e.g., language-python) and uses that to generate a default filename (file_1.py).
  4. It uses a built-in, minimal JavaScript function to construct a TAR archive (USTAR format) in memory.
  5. File content is encoded as UTF-8.
  6. The generated TAR archive is converted to a Blob.
  7. A hidden link is created with the Blob URL and download attribute, then programmatically clicked to trigger the download.

Limitations

  • Filename Accuracy: Filename detection is heuristic and might fail if the LLM response structure is unusual or filenames aren't near the code block.
  • HTML Structure: Relies on the common <pre><code>...</code></pre> structure. It won't work on pages using different elements for code display.
  • TAR Features: The TAR implementation is basic. It supports USTAR long filenames (up to ~255 characters split between prefix/name) but lacks features like complex permission handling or symbolic links.
  • Browser Security: May be restricted by Content Security Policy (CSP) on some websites.
  • Bookmarklet Length Limits: The code is minified, but extremely complex future versions might hit browser limits.

Contributing

Found a bug or have an idea for improvement? Feel free to:

⭐️ If you find this useful, please consider starring the repository! ⭐️

License

This project is licensed under the MIT License - see the LICENSE file for details.


About

Extract all files from an AI response preserving their folder structure.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published