Tl;DR You want to go to and play with it. You can use example if you don't have a 7zip archive. unzip this I'll show you how to build this tool below. Intro We would answer some questions first. What is 7zip.html? It is a tool to open archives in your browser. Your data wouldn't leave your machine. Why do we need this? Sometimes you just need to have a look at a specific file in your archive and you don't want to install additional software to do this. How would we do this? We would use a WebAssembly port of a tool. We would create a wrapper around it to make it easier for a user. Core We would use libarchivejs to look inside the archive. Let's try the code from their example. We need to setup to run in the browser. libarchivejs Run libarchivejs in the browser Let us start with webpack environment that would pack everything for us. You can see details in webpack folder . here We need to add an input to start working with files. < = = /> input id "fileInput" type "file" Then we need to add libarchivejs and event listener. { Archive } ; Archive.init({ : , }); fileInput = .getElementById( ); fileInput.addEventListener( , (e) => { file = e.currentTarget.files[ ]; archive = Archive.open(file); obj = archive.extractFiles(); .log(obj); }); import from 'libarchive.js/main.js' workerUrl 'public/worker-bundle.js' const document 'fileInput' 'change' async const 0 const await let await console As a result, we would see similar output: { : {File}, : { : {File}, : {File} }, : {File} } ".gitignore" "addon" "addon.py" "addon.xml" "README.md" Now we want to add functions and components to show folder tree and text file content. We would have two columns element. It would show us the folder tree on the left side and file content on the right side. <div = > <ul id="treeView"><i>No archive chosen</i></ul> <div = > < div> class "twoColumn" < = > div class "column" </ > div class "column" < = > textarea id "fileOutput" </ > textarea /div> </ The last thing before we go back to JavaScript code is to add CSS. { : ; : Courier, sans-serif; : auto; : auto; : ; : ; : ; } { : ; : flex; : row; : space-between; } { : ; : ; : hidden; : ; : ; : ; } { : none; } { : block; } body font-size 16px font-family margin-left margin-right background-color #f6f6f6 width 800px height 100% .twoColumn margin-top 3em display flex-direction justify-content .column width 100% max-width 400px overflow margin-right 5px padding 5px background-color #d3d0ba /* Hide the nested list */ .nested display /* Show the nested list when the user clicks on the caret/arrow (with JavaScript) */ .active display Now we are ready to add functions to show the folder tree. We would add more const first. textarea = .getElementById( ); fileInput = .getElementById( ); treeView = .getElementById( ); const document 'fileOutput' const document 'fileInput' const document 'treeView' We need to add some helper functions before our next step. We add uuid. We would use it to give tree nodes uniq ids. { v4 uuidv4 } ; import as from 'uuid' And we add `isASCII` to filter binary files. { .test(str); } ( ) function isASCII str return /^[\x00-\x7F]*$/ Then we would work on a walk function that would go through the tree recursive and create html elements. We receive the node and check if it is a file or folder. We add elements to html in both cases. If it is a file then we add an event listener to open its content on the right-side panel. If it is a folder then we add an event listener to show/hide its content. Then we give a folder to a walk function to step into it and check its files. And we have nothing that we show `Empty folder`. { root = .getElementById(liId); (!(node File)) { newUlId = uuidv4(); newUl = .createElement( ); newUl.classList.add( ); newUl.id = newUlId; newLi = .createElement( ); root.appendChild(newLi); newLi.classList.add( ); newLi.addEventListener( , { e.preventDefault(); e.stopPropagation(); newLi.childNodes.forEach( { (c.classList.contains( )) { c.classList.toggle( ); } }); }); span = .createElement( ); span.innerText = name; newLi.appendChild(span); newLi.appendChild(newUl); keys = .keys(node); (keys.length > ) { keys.forEach( { walk({ : node[key], : newUlId, : key }); }); } { span = .createElement( ); span.innerHTML = ; root.appendChild(span); } } { li = .createElement( ); li.innerText = node.name; li.addEventListener( , (e) => { e.stopPropagation(); reader = FileReader(); reader.onload = { (isASCII(event.target.result)){ textarea.textContent = event.target.result; } { textarea.textContent = ; } }; reader.readAsText(node); }); root.appendChild(li); } } ( ) function walk { node, liId, name } const document if instanceof const const document 'ul' 'nested' const document 'li' 'folder' "click" ( ) function e => c if 'nested' "active" const document 'span' const Object if 0 ( ) => key node liId name else const document 'span' '<i>Empty folder</i>' else const document 'li' 'click' const new ( ) function event if else "Sorry, we cannot display binary files" That is it. Now we can open the archive in the browser and have a look at the file content. How we can improve it? What are your thoughts? I value your feedback, so let me know what you think! Previously published at https://matvii.hodovani.uk/posts/how-to-create-7ziphtml.html