Regex-Generator
++ Zwei Wortlisten werden zu einem Muster verrechnet: alles aus der + ersten Liste passt, alles aus der zweiten nicht. +
+
+ + Zwei Wortlisten werden zu einem Muster verrechnet: alles aus der + ersten Liste passt, alles aus der zweiten nicht. +
+
+ The whole finder CHANGELOG
SHA256SUMS to SHA256SUMS.txt--json to commandCUSTOM_TEMPLATESSearch on all Drives on Windows from 0.3.3, it~/.finder/templates/ or ./.finder/templates/ without recompiling the program.json5 files are automatically detected and loaded on startupparser.go: Dedicated argument parsing logichandlers.go: Isolated command handlerscommands.go: Clean routing (reduced from 300+ to 60 lines)h, -h, --help in addition to helpls in addition to list--file in addition to -f--config in addition to -c.IsHelp(), .IsList(), .IsCheck(), .IsFileLoad(), .IsDirectLoad(), .IsTemplateSearch().GetFileArg(), .GetDirectLoadArg(), .GetTemplateName()--verbose flag for extended outputtemplateloader.go)LoadUserTemplates(): Discovers user templates from filesystemJSONtemplateLoaderWithUserTemplates(): Intelligent loading with user overrideLoadAllWithUserTemplates(): Combined built-in + custom template discoveryHandleCommand()) unchangedThis version brings the biggest improvement since 0.2.0:
Template System & CLI Foundations
More Templates Better Console Output Help Message
Programm Init
the start
',styles:[m]},configeditor:{id:"configeditor",type:"component",load:()=>c(()=>import("./configeditor.js"),__vite__mapDeps([2,3]),import.meta.url),data:null,styles:[S]},creator:{id:"creator",type:"component",load:()=>c(()=>import("./creator.js"),__vite__mapDeps([4,5]),import.meta.url),data:null,styles:[]},"docs/config":{id:"docs/config",type:"markdown",html:'Port for the findergen server to view and create templates.
When set to true, the results of will be saved as a cache and can then be used afterwards
When set to true, the cache data of finder will be saved in a Git DB. Git is required for this.
Finder instances which will run at the same time when creating cache for all templates
',styles:[m]},"docs/index":{id:"docs/index",type:"markdown",html:'soon
',styles:[m]},home:{id:"home",type:"component",load:()=>c(()=>import("./home.js"),__vite__mapDeps([6,7]),import.meta.url),data:null,styles:[]},index:{id:"index",type:"component",load:()=>c(()=>import("./index.js"),[],import.meta.url),data:`# AGENTS — Finder Template Authoring Guide
+const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cacheviewer.js","./cacheviewer.css","./configeditor.js","./configeditor.css","./creator.js","./creator.css","./home.js","./home.css","./regexcreator.js","./regexcreator.css","./samfile.js","./jquery.module.js","./samfile.css","./markdowneditor.js","./markdowneditor.css","./tellraw.js","./tellraw.css","./viewer.js","./viewer.css"])))=>i.map(i=>d[i]);
+const x="modulepreload",T=function(e,s){return new URL(e,s).href},j={},c=function(s,n,a){let u=Promise.resolve();if(n&&n.length>0){const p=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),i=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));u=Promise.allSettled(n.map(o=>{if(o=T(o,a),o in j)return;j[o]=!0;const r=o.endsWith(".css"),_=r?'[rel="stylesheet"]':"";if(!!a)for(let h=p.length-1;h>=0;h--){const f=p[h];if(f.href===o&&(!r||f.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${o}"]${_}`))return;const d=document.createElement("link");if(d.rel=r?"stylesheet":x,r||(d.as="script"),d.crossOrigin="",d.href=o,i&&d.setAttribute("nonce",i),document.head.appendChild(d),r)return new Promise((h,f)=>{d.addEventListener("load",h),d.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${o}`)))})}))}function g(p){const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=p,window.dispatchEvent(l),!l.defaultPrevented)throw p}return u.then(p=>{for(const l of p||[])l.status==="rejected"&&g(l.reason);return s().catch(g)})},m=""+new URL("markdownrootstyle.css",import.meta.url).href,S=""+new URL("markdownstyle.css",import.meta.url).href,b={cacheviewer:{id:"cacheviewer",type:"component",load:()=>c(()=>import("./cacheviewer.js"),__vite__mapDeps([0,1]),import.meta.url),data:null,styles:[]},changelog:{id:"changelog",type:"markdown",html:'CHANGELOG
The whole finder CHANGELOG
Newest prob 0.3.17
- added regex support
0.3.16 - 08.09.2026
- added cache creation
- added config editor
- added cache viewer
- Moved every site on the finder website to TSX instead
- add code to the ssg plugin which runs on build time - 07.09.2026
- the search function should return an array of
- added size plugin for the frontend
- added syntax highliting for the markdown codeblocks
- updated some templates
- renamed checksums file in the release from
SHA256SUMS to SHA256SUMS.txt - added some helpfule vite plugins
- added file content checksum check
- fixed that to old template warning because it showed up the finder and the template where in the same version
- added SHA512 checksums
0.3.15 - 02.09.2025
- added new Templates
- added a HTML Server with go backend to create and view all templates
- added json output support to finder, just add
--json to command - added tags and min version to a lot of the templates
- the Templates are now saved as minified json
0.3.14 - 25.06.2026
0.3.13 - 22.06.2026
0.3.12 - 22.06.2026
0.3.11 - 10.04.2026
0.3.10 - 10.04.2026
0.3.9 - 09.04.2026
- fixed Binary Search
0.3.8 - 27.02.2026
- added Checksums
0.3.7 - 24.02.2026
- only for releasing
0.3.6 - 24.02.2026
- added Size option to the Templates
- updated README File
- updates
CUSTOM_TEMPLATES - added a new entry to the Template: min finder version which should
- added Version package
0.3.5 - 18.02.2026
- made a Folder public for public finder modules
- added Template for
- flax
- added Time which the searching took
- resturctured the argparser
- added version Command
- added Argparser package
- removed loading templates directly from the Console or via a custom filepath!
- json output is broken in this Release, but will we fixed in future Releases
- formatted the tag Search output correctly
0.3.4 - 16.02.2026
- changed Go Version to 1.18
- fixed
Search on all Drives on Windows from 0.3.3, it - added Async Search
- made color package public
0.3.3 - 15.02.2026
- added JSON Shema
- added File Options
- Search on all Drives on Windows
- added Tag Search
0.3.2 - 15.02.2026
- little Fixes
0.3.1 - 15.02.2026
✨ Features
Runtime Custom Template System
- Custom Templates without Recompilation: Users can now create templates in
~/.finder/templates/ or ./.finder/templates/ without recompiling the program - Automatic Template Discovery: New
.json5 files are automatically detected and loaded on startup - User Templates Override: User-defined templates can override built-in templates with the same name
- Precedence System: User templates take precedence over built-in templates
CLI Reorganization & Modernization
- Modular CLI Architecture: Complete restructuring from monolithic design
parser.go: Dedicated argument parsing logichandlers.go: Isolated command handlerscommands.go: Clean routing (reduced from 300+ to 60 lines)
- Command Aliases: New shorter forms for common commands
h, -h, --help in addition to helpls in addition to list--file in addition to -f--config in addition to -c
- CLIOptions Struct: Structured argument representation with predicates
.IsHelp(), .IsList(), .IsCheck(), .IsFileLoad(), .IsDirectLoad(), .IsTemplateSearch().GetFileArg(), .GetDirectLoadArg(), .GetTemplateName()
- Verbose Mode: New
--verbose flag for extended output
Enhanced Help System
- Better Help Structure: Organized into COMMANDS, FILE & CONFIG OPERATIONS, GLOBAL FLAGS
- Table Layout: Improved readability with consistent formatting
- Custom Templates Info: Documentation for user template setup
- Detailed Descriptions: Each command with clear explanation
Enhanced List & Check Commands
- Separated Display: Built-in and custom templates are listed separately
- Template Sources: Source attribute shows whether template is built-in or custom
- Helpful Hints: Paths for custom template setup are displayed
- Improved Validation: Check command validates with source information
🧪 Testing
- 40+ new unit tests for CLI parser logic
- Parser Tests: Comprehensive coverage for command recognition, flag parsing, argument extraction
- Integration Tests: End-to-end tests for command execution
- Routing Tests: Tests for handler mapping
- Error Handling Tests: Validation of error handling and user feedback
📖 Documentation
- ARCHITECTURE.md: Detailed technical documentation of the new CLI structure
- REORGANIZATION.md: Comprehensive before/after comparison and explanation
- QUICKSTART.md: Practical guide for adding new commands
- CUSTOM_TEMPLATES.md: User guide for custom template creation
- Inline Code Comments: Improved code documentation
🔧 Infrastructure
- Enhanced Template Loader (
templateloader.go)LoadUserTemplates(): Discovers user templates from filesystemJSONtemplateLoaderWithUserTemplates(): Intelligent loading with user overrideLoadAllWithUserTemplates(): Combined built-in + custom template discovery
- Template Override Mechanism: User templates can replace built-in templates
- Graceful Error Handling: Missing user template directories are not fatal
🎯 Quality Improvements
- Clean Code Structure: Single Responsibility Principle consistently applied
- Better Testability: Each module can be tested in isolation
- Extensibility: New commands can be added in 5 simple steps
- Backward Compatibility: External API (
HandleCommand()) unchanged
👥 User Experience
- Better Error Messages: Context-sensitive error messages with suggestions
- Helpful Hints: Tips for common tasks (e.g., where to place templates)
- Flexible Command Syntax: Multiple synonyms for each command
- Consistent Output Formatting: Unified design across all commands
📊 Performance
- No Recompilation Required: Custom templates are loaded at runtime
- Efficient Template Discovery: Fast filesystem traversal
- Minimal Overhead: Template loading has negligible performance impact
🐛 Bug Fixes & Improvements
- Improved error handling in template loading
- Better handling of missing or malformed user templates
- Consistent error messages across all commands
- Fixed edge cases in CLI argument parsing
📝 Breaking Changes
- No Breaking Changes: All existing commands work unchanged
- Internal structure completely refactored, but public API remains stable
🙏 Highlights
This version brings the biggest improvement since 0.2.0:
- Users can now create their own templates
- Codebase is more maintainable and extensible
- Test coverage drastically improved
0.3.0 - 23.01.2026
Template System & CLI Foundations
0.2.0 - 23.01.2026
More Templates Better Console Output Help Message
0.1.0 - 17.11.2025
Programm Init
0.0.0 - 30.11.2025
the start
',styles:[m]},configeditor:{id:"configeditor",type:"component",load:()=>c(()=>import("./configeditor.js"),__vite__mapDeps([2,3]),import.meta.url),data:null,styles:[S]},creator:{id:"creator",type:"component",load:()=>c(()=>import("./creator.js"),__vite__mapDeps([4,5]),import.meta.url),data:null,styles:[]},"docs/config":{id:"docs/config",type:"markdown",html:'Config fields
Port
Port for the findergen server to view and create templates.
Cache
When set to true, the results of will be saved as a cache and can then be used afterwards
Create Cache Database
When set to true, the cache data of finder will be saved in a Git DB. Git is required for this.
Finder Instances
Finder instances which will run at the same time when creating cache for all templates
',styles:[m]},"docs/index":{id:"docs/index",type:"markdown",html:'Finder Docs
soon
',styles:[m]},home:{id:"home",type:"component",load:()=>c(()=>import("./home.js"),__vite__mapDeps([6,7]),import.meta.url),data:null,styles:[]},index:{id:"index",type:"component",load:()=>c(()=>import("./index.js"),[],import.meta.url),data:`# AGENTS — Finder Template Authoring Guide
This document is for AI assistants such as ChatGPT, Claude, Copilot,
and similar tools that need to create valid Finder templates.
@@ -639,4 +639,4 @@ docs in the root files.
// You dont have to use it obviously
"create_cache_db": false
}
For more and detailed Information and more config values check out the config editor here
Mistakes
I thing i would change is to use raw JSON for the templates instead of JSON with comments, which i called JSON5 back then, but it is no real JSON5.
Development
Run tests:
go test ./...
Generate coverage report:
go test -coverprofile=coverage ./...
-go tool cover -html=coverage
Build:
go build ./cmd/finder
Check the available Templates
go run ./cmd/finder check
Contributing
- Found a missing or inaccurate template? Please open an issue.
- Add new templates via PR. Keep them in JSON5 and provide a short
Roadmap / Ideas
- use temporary Template via the Command Line
- Caching/Indexing for faster searches
- Web UI for template management
- Template schema and validation
License
See LICENSE.
Project: https://github.com/shadowdara/finder
Extra Info
The Project fs-tools was more or less the prototype for finder.
Info Video
(a Youtube Video)
`,styles:[m]},samfile:{id:"samfile",type:"component",load:()=>c(()=>import("./samfile.js"),__vite__mapDeps([8,9,10]),import.meta.url),data:null,styles:[]},"tools/markdowneditor":{id:"tools/markdowneditor",type:"component",load:()=>c(()=>import("./markdowneditor.js"),__vite__mapDeps([11,12]),import.meta.url),data:null,styles:[]},"tools/minecraft/tellraw":{id:"tools/minecraft/tellraw",type:"component",load:()=>c(()=>import("./tellraw.js"),__vite__mapDeps([13,9,14]),import.meta.url),data:null,styles:[]},viewer:{id:"viewer",type:"component",load:()=>c(()=>import("./viewer.js"),__vite__mapDeps([15,16]),import.meta.url),data:null,styles:[]}},y=Symbol("html");function t(e,s,...n){if(typeof e=="function")return e({...s??{},children:n});const a=new Set(["disabled","checked","selected","readonly","required","multiple","hidden","autofocus","open"]),u=Object.entries(s??{}).filter(([i])=>i!=="children"&&i!=="key").map(([i,o])=>{if(o==null)return"";const r=i==="className"?"class":i;return typeof o=="boolean"&&a.has(r)?o?` ${r}`:"":typeof o=="boolean"?` ${r}="${o}"`:o===!1?"":` ${r}="${C(String(o))}"`}).join(""),g=n.flat(1/0).filter(i=>i!=null&&i!==!1).map(i=>w(i)?i.value:v(String(i))).join(""),l=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]).has(e)?`<${e}${u}>`:`<${e}${u}>${g}${e}>`;return q(l)}function E(e){const s=(e.children??[]).flat(1/0).filter(n=>n!=null&&n!==!1).map(n=>w(n)?n.value:v(String(n))).join("");return q(s)}function q(e){return{[y]:!0,value:e,toString(){return e}}}function w(e){return typeof e=="object"&&e!==null&&y in e}function C(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(//g,">")}function v(e){return e.replace(/&/g,"&").replace(//g,">")}function H(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function k(e){return q(e)}function I(e){for(const s of e){const n=new URL(s,import.meta.url).href;if(document.head.querySelector(`link[data-page-style="${CSS.escape(n)}"]`))continue;const a=document.createElement("link");a.rel="stylesheet",a.href=n,a.dataset.pageStyle=n,document.head.appendChild(a)}}function A(e){e.innerHTML=t("main",null,t("h1",null,"404"),t("p",null,"No page id was provided."),t("a",{href:"/"},"Go home"))}function L(e,s){const n=Object.keys(s).filter(a=>a!=="__404__").map(a=>t("li",null,t("a",{href:a==="index"?"/":`/${a}`},a))).join("");e.innerHTML=t("main",null,t("h1",null,"404"),t("p",null,"Page not found."),t("h2",null,"Available pages"),t("ul",null,k(n)),t("a",{href:"/"},"Go home"))}function O(e,s){e.innerHTML=t("main",null,t("h1",null,"404"),t("p",null,"Page ",s," not found."),t("a",{href:"/"},"Go home"))}function F(e,s,n){console.error(`[pages] Failed to load page "${s}"`,n),e.innerHTML=t("main",null,t("h1",null,"Failed to load page"),t("p",null,'Could not load "$',s,'".'),t("a",{href:"/"},"Go home"),t("pre",null,`[pages] Failed to load page "${s}"`),t("pre",null,n))}function R(e,s){s.type==="markdown"&&(e.innerHTML=t(E,null,t("a",{href:"../"},"Home"),t("article",{class:"markdown"},k(s.html??""))))}async function G(){const e=document.getElementById("app");if(e==null)throw new Error("Missing #app element");const s=window.PAGE_ID;if(!s){A(e);return}if(s==="__404__"){L(e,b);return}const n=b[s];if(!n){console.error(`[pages] Unknown page id: ${s}`),O(e,s);return}try{if(I(n.styles),n.type==="markdown"){R(e,n);return}await(await n.load()).default(e,n.data)}catch(a){F(e,s,a)}}G();export{E as F,H as e,t as j,k as r};
+go tool cover -html=coverageBuild:
go build ./cmd/finderCheck the available Templates
go run ./cmd/finder checkSee LICENSE.
Project: https://github.com/shadowdara/finder
The Project fs-tools was more or less the prototype for finder.
(a Youtube Video)
`,styles:[m]},regexcreator:{id:"regexcreator",type:"component",load:()=>c(()=>import("./regexcreator.js"),__vite__mapDeps([8,9]),import.meta.url),data:null,styles:[]},samfile:{id:"samfile",type:"component",load:()=>c(()=>import("./samfile.js"),__vite__mapDeps([10,11,12]),import.meta.url),data:null,styles:[]},"tools/markdowneditor":{id:"tools/markdowneditor",type:"component",load:()=>c(()=>import("./markdowneditor.js"),__vite__mapDeps([13,14]),import.meta.url),data:null,styles:[]},"tools/minecraft/tellraw":{id:"tools/minecraft/tellraw",type:"component",load:()=>c(()=>import("./tellraw.js"),__vite__mapDeps([15,11,16]),import.meta.url),data:null,styles:[]},viewer:{id:"viewer",type:"component",load:()=>c(()=>import("./viewer.js"),__vite__mapDeps([17,18]),import.meta.url),data:null,styles:[]}},y=Symbol("html");function t(e,s,...n){if(typeof e=="function")return e({...s??{},children:n});const a=new Set(["disabled","checked","selected","readonly","required","multiple","hidden","autofocus","open"]),u=Object.entries(s??{}).filter(([i])=>i!=="children"&&i!=="key").map(([i,o])=>{if(o==null)return"";const r=i==="className"?"class":i;return typeof o=="boolean"&&a.has(r)?o?` ${r}`:"":typeof o=="boolean"?` ${r}="${o}"`:o===!1?"":` ${r}="${C(String(o))}"`}).join(""),g=n.flat(1/0).filter(i=>i!=null&&i!==!1).map(i=>w(i)?i.value:v(String(i))).join(""),l=new Set(["area","base","br","col","embed","hr","img","input","link","meta","param","source","track","wbr"]).has(e)?`<${e}${u}>`:`<${e}${u}>${g}${e}>`;return q(l)}function E(e){const s=(e.children??[]).flat(1/0).filter(n=>n!=null&&n!==!1).map(n=>w(n)?n.value:v(String(n))).join("");return q(s)}function q(e){return{[y]:!0,value:e,toString(){return e}}}function w(e){return typeof e=="object"&&e!==null&&y in e}function C(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(//g,">")}function v(e){return e.replace(/&/g,"&").replace(//g,">")}function D(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function k(e){return q(e)}function I(e){for(const s of e){const n=new URL(s,import.meta.url).href;if(document.head.querySelector(`link[data-page-style="${CSS.escape(n)}"]`))continue;const a=document.createElement("link");a.rel="stylesheet",a.href=n,a.dataset.pageStyle=n,document.head.appendChild(a)}}function A(e){e.innerHTML=t("main",null,t("h1",null,"404"),t("p",null,"No page id was provided."),t("a",{href:"/"},"Go home"))}function L(e,s){const n=Object.keys(s).filter(a=>a!=="__404__").map(a=>t("li",null,t("a",{href:a==="index"?"/":`/${a}`},a))).join("");e.innerHTML=t("main",null,t("h1",null,"404"),t("p",null,"Page not found."),t("h2",null,"Available pages"),t("ul",null,k(n)),t("a",{href:"/"},"Go home"))}function O(e,s){e.innerHTML=t("main",null,t("h1",null,"404"),t("p",null,"Page ",s," not found."),t("a",{href:"/"},"Go home"))}function F(e,s,n){console.error(`[pages] Failed to load page "${s}"`,n),e.innerHTML=t("main",null,t("h1",null,"Failed to load page"),t("p",null,'Could not load "$',s,'".'),t("a",{href:"/"},"Go home"),t("pre",null,`[pages] Failed to load page "${s}"`),t("pre",null,n))}function R(e,s){s.type==="markdown"&&(e.innerHTML=t(E,null,t("a",{href:"../"},"Home"),t("article",{class:"markdown"},k(s.html??""))))}async function P(){const e=document.getElementById("app");if(e==null)throw new Error("Missing #app element");const s=window.PAGE_ID;if(!s){A(e);return}if(s==="__404__"){L(e,b);return}const n=b[s];if(!n){console.error(`[pages] Unknown page id: ${s}`),O(e,s);return}try{if(I(n.styles),n.type==="markdown"){R(e,n);return}await(await n.load()).default(e,n.data)}catch(a){F(e,s,a)}}P();export{E as F,D as e,t as j,k as r}; diff --git a/cmd/findergen/frontend/assets/regexcreator.css b/cmd/findergen/frontend/assets/regexcreator.css new file mode 100644 index 00000000..4e49215c --- /dev/null +++ b/cmd/findergen/frontend/assets/regexcreator.css @@ -0,0 +1 @@ +:root{--bg: #f5f6f2;--panel: #ffffff;--ink: #14181c;--muted: #5b6169;--line: #dbddd6;--teal: #1f6f63;--teal-soft: #e4efec;--brick: #9c3d33;--brick-soft: #f5e7e4;--sans: "Space Grotesk", system-ui, sans-serif;--mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, monospace;--radius: 10px}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font-family:var(--sans);-webkit-font-smoothing:antialiased}#app{max-width:880px;margin:0 auto;padding:3.5rem 1.5rem 5rem}.intro h1{font-size:1.9rem;font-weight:600;margin:0 0 .6rem;letter-spacing:-.01em}.intro p{margin:0 0 2.5rem;max-width:46ch;color:var(--muted);line-height:1.5}.stage{display:flex;flex-direction:column;gap:1.25rem}.sets{display:grid;grid-template-columns:1fr auto 1fr;align-items:stretch;gap:1rem}.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:1.1rem 1.2rem 1.3rem}.card label{display:block;font-size:.85rem;font-weight:500;margin-bottom:.55rem;color:var(--muted)}.card--accept{border-left:3px solid var(--teal)}.card--disallow{border-left:3px solid var(--brick)}textarea{width:100%;resize:vertical;min-height:9rem;border:none;outline:none;background:transparent;font-family:var(--mono);font-size:.92rem;line-height:1.6;color:var(--ink)}textarea::placeholder{color:#b7bab3}.operator{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:.15rem;color:var(--muted);padding-top:1.2rem}.operator__glyph{font-family:var(--mono);font-size:1.7rem;line-height:1}.operator__label{font-size:.78rem}.settings{display:flex;justify-content:flex-end}.checkbox{display:flex;align-items:center;gap:.5rem;font-size:.88rem;color:var(--muted);cursor:pointer}.checkbox input{accent-color:var(--teal);width:1rem;height:1rem}.flow-line{align-self:center;width:1px;height:1.5rem;background:var(--line)}.card--output{border-left:3px solid var(--ink)}.card__head{display:flex;align-items:baseline;justify-content:space-between;margin-bottom:.6rem}.card__head label{margin-bottom:0}#output{display:block;font-family:var(--mono);font-size:.95rem;line-height:1.6;word-break:break-all;white-space:pre-wrap;min-height:1.6em}.card--output[data-state=empty] #output:before{content:'Mindestens ein Wort unter "Akzeptieren" eingeben.';color:var(--muted);font-family:var(--sans);font-size:.88rem}.card--output[data-state=error] #output{color:var(--brick)}#copy-btn{border:1px solid var(--line);background:var(--panel);color:var(--ink);font-family:var(--sans);font-size:.82rem;padding:.35rem .7rem;border-radius:6px;cursor:pointer}#copy-btn:hover:not(:disabled){border-color:var(--ink)}#copy-btn:disabled{opacity:.4;cursor:not-allowed}.tester-row{display:flex;gap:.7rem;align-items:center}#tester{flex:1;border:1px solid var(--line);border-radius:6px;padding:.55rem .7rem;font-family:var(--mono);font-size:.92rem;color:var(--ink);background:var(--panel)}#tester:focus{outline:2px solid var(--ink);outline-offset:1px}.badge{font-size:.85rem;font-weight:500;padding:.4rem .75rem;border-radius:999px;white-space:nowrap;background:var(--line);color:var(--muted)}.badge[data-state=match]{background:var(--teal-soft);color:var(--teal)}.badge[data-state=no-match]{background:var(--brick-soft);color:var(--brick)}@media (max-width: 640px){.sets{grid-template-columns:1fr}.operator{flex-direction:row;padding-top:0}}@media (prefers-reduced-motion: reduce){*{transition:none!important}} diff --git a/cmd/findergen/frontend/assets/regexcreator.js b/cmd/findergen/frontend/assets/regexcreator.js new file mode 100644 index 00000000..6cc0b4eb --- /dev/null +++ b/cmd/findergen/frontend/assets/regexcreator.js @@ -0,0 +1,8 @@ +import{j as e}from"./main_entry.js";function m(){return{children:new Map,isEnd:!1}}function y(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function v(t){const n=m();for(const a of t){let s=n;for(const r of a){let l=s.children.get(r);l||(l=m(),s.children.set(r,l)),s=l}s.isEnd=!0}return n}function x(t){if(t.children.size===0)return"";const n=[],a=[];for(const[s,r]of t.children)if(r.children.size===0&&r.isEnd)a.push(y(s));else{const o=x(r),u=o.includes("|")?`(?:${o})`:o,c=r.isEnd?"?":"";n.push(`${y(s)}${u}${c}`)}return a.length===1?n.push(a[0]):a.length>1&&n.push(`[${a.join("")}]`),n.join("|")}function L(t){if(!t||t.length===0)return null;const n=v(t);return x(n)||null}function C(t,n=[],a={}){if(t.length===0)throw new Error("accept-Array darf nicht leer sein.");const s=a.flags??"",r=s.includes("i"),l=new Set(n.map(c=>r?c.toLocaleLowerCase():c)),o=t.filter(c=>{const i=r?c.toLocaleLowerCase():c;return!l.has(i)});if(o.length===0)throw new Error("Alle akzeptierten Wörter werden abgelehnt.");const u=L(o);if(!u)throw new Error("Keine gültigen akzeptierten Wörter.");return new RegExp(`^(?:${u})$`,s)}function S(t){t.innerHTML=e("main",{class:"regexcreator-page"},e("header",{class:"intro"},e("h1",null,e("span",null,"Regex-Generator")," /"," ",e("span",null,e("a",{href:"../"},"Home"))),e("p",null,"Zwei Wortlisten werden zu einem Muster verrechnet: alles aus der ersten Liste passt, alles aus der zweiten nicht.")),e("main",{class:"stage"},e("section",{class:"sets"},e("div",{class:"card card--accept"},e("label",{for:"accept"},"Akzeptieren"),e("textarea",{id:"accept",rows:"8",spellcheck:"false",placeholder:"ein Wort pro Zeile"},"cat",` +`,"car",` +`,"cart",` +`,"dog",` +`,"do")),e("div",{class:"operator","aria-hidden":"true"},e("span",{class:"operator__glyph"},"∖"),e("span",{class:"operator__label"},"ohne")),e("div",{class:"card card--disallow"},e("label",{for:"disallow"},"Ablehnen"),e("textarea",{id:"disallow",rows:"8",spellcheck:"false",placeholder:"ein Wort pro Zeile"},"cot",` +`,"cats",` +`,"dot"))),e("div",{class:"settings"},e("label",{class:"checkbox"},e("input",{type:"checkbox",id:"ignore-case"}),e("span",null,"Groß-/Kleinschreibung ignorieren"))),e("div",{class:"flow-line","aria-hidden":"true"}),e("section",{class:"card card--output",id:"output-wrap","data-state":"ready"},e("div",{class:"card__head"},e("label",{for:"output"},"Ergebnis"),e("button",{id:"copy-btn",type:"button"},"Kopieren")),e("code",{id:"output"})),e("section",{class:"card card--tester"},e("label",{for:"tester"},"Testen"),e("div",{class:"tester-row"},e("input",{id:"tester",type:"text",placeholder:"Text eingeben …",autocomplete:"off"}),e("span",{id:"badge",class:"badge","data-state":"idle"},"–")))));const n=t.querySelector("#accept"),a=t.querySelector("#disallow"),s=t.querySelector("#ignore-case"),r=t.querySelector("#output-wrap"),l=t.querySelector("#output"),o=t.querySelector("#copy-btn"),u=t.querySelector("#tester"),c=t.querySelector("#badge");let i=null,w;function b(p){return p.split(` +`).map(d=>d.trim()).filter(d=>d.length>0)}function h(){const p=b(n.value),d=b(a.value),E=s.checked?"i":"";if(p.length===0){i=null,l.textContent="",r.dataset.state="empty",o.disabled=!0,f();return}try{i=C(p,d,{flags:E}),l.textContent=i.source,r.dataset.state="ready",o.disabled=!1}catch(g){i=null,l.textContent=g instanceof Error?g.message:String(g),r.dataset.state="error",o.disabled=!0}f()}function f(){const p=u.value;if(!i||p.length===0){c.textContent="–",c.dataset.state="idle";return}const d=i.test(p);c.textContent=d?"passt":"passt nicht",c.dataset.state=d?"match":"no-match"}n.addEventListener("input",h),a.addEventListener("input",h),s.addEventListener("change",h),u.addEventListener("input",f),o.addEventListener("click",async()=>{i&&(await navigator.clipboard.writeText(i.source),o.textContent="Kopiert",window.clearTimeout(w),w=window.setTimeout(()=>{o.textContent="Kopieren"},1200))}),h()}export{S as default}; diff --git a/cmd/findergen/frontend/dependencies.txt b/cmd/findergen/frontend/dependencies.txt index cea58f18..c8f77313 100644 --- a/cmd/findergen/frontend/dependencies.txt +++ b/cmd/findergen/frontend/dependencies.txt @@ -161,7 +161,7 @@ fast-levenshtein@2.0.6 -- MIT fdir@6.5.0 -- MIT file-entry-cache@8.0.0 -- MIT find-up@5.0.0 -- MIT -finder-template-generator@0.3.16 -- UNLICENSED +finder-template-generator@0.3.17 -- UNLICENSED flat-cache@4.0.1 -- MIT flatted@3.4.4 -- ISC fs.realpath@1.0.0 -- ISC diff --git a/cmd/findergen/frontend/regexcreator/index.html b/cmd/findergen/frontend/regexcreator/index.html new file mode 100644 index 00000000..514c4291 --- /dev/null +++ b/cmd/findergen/frontend/regexcreator/index.html @@ -0,0 +1 @@ +
Zwei Wortlisten werden zu einem Muster verrechnet: alles aus der
ersten Liste passt, alles aus der zweiten nicht.
@@ -23,7 +28,7 @@ export default function render(el: HTMLDivElement) {
spellcheck="false"
placeholder="ein Wort pro Zeile"
>
- cat car cart dog do
+ cat{"\n"}car{"\n"}cart{"\n"}dog{"\n"}do
@@ -40,7 +45,7 @@ export default function render(el: HTMLDivElement) {
spellcheck="false"
placeholder="ein Wort pro Zeile"
>
- cot cats dot
+ cot{"\n"}cats{"\n"}dot
diff --git a/finder-template-generator-ssg/src/lib/regex.ts b/finder-template-generator-ssg/src/lib/regex.ts
index d8649f40..6cd677c5 100644
--- a/finder-template-generator-ssg/src/lib/regex.ts
+++ b/finder-template-generator-ssg/src/lib/regex.ts
@@ -31,7 +31,7 @@ function createNode(): TrieNode {
/** Escaped ein einzelnes Zeichen für sichere Verwendung in RegExp */
function escapeRegexChar(ch: string): string {
- return ch.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+ return ch.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
/** Baut aus einem Array von Strings einen Trie */
@@ -60,7 +60,7 @@ function buildTrie(words: readonly string[]): TrieNode {
* - optionale Verzweigungen (wenn Knoten selbst Wortende ist) mit `?`
*/
function trieToFragment(node: TrieNode): string {
- if (node.children.size === 0) return '';
+ if (node.children.size === 0) return "";
const branchParts: string[] = [];
const singleChars: string[] = [];
@@ -72,8 +72,10 @@ function trieToFragment(node: TrieNode): string {
singleChars.push(escapeRegexChar(key));
} else {
const subFragment = trieToFragment(child);
- const wrapped = subFragment.includes('|') ? `(?:${subFragment})` : subFragment;
- const optional = child.isEnd ? '?' : '';
+ const wrapped = subFragment.includes("|")
+ ? `(?:${subFragment})`
+ : subFragment;
+ const optional = child.isEnd ? "?" : "";
branchParts.push(`${escapeRegexChar(key)}${wrapped}${optional}`);
}
}
@@ -81,10 +83,10 @@ function trieToFragment(node: TrieNode): string {
if (singleChars.length === 1) {
branchParts.push(singleChars[0]);
} else if (singleChars.length > 1) {
- branchParts.push(`[${singleChars.join('')}]`);
+ branchParts.push(`[${singleChars.join("")}]`);
}
- return branchParts.join('|');
+ return branchParts.join("|");
}
/** Erzeugt aus einer Wortliste ein Regex-Fragment (oder null bei leerer Liste) */
@@ -109,23 +111,35 @@ export interface GenerateRegexOptions {
export function generateRegex(
accept: readonly string[],
disallow: readonly string[] = [],
- options: GenerateRegexOptions = {}
+ options: GenerateRegexOptions = {},
): RegExp {
- const acceptFragment = wordsToFragment(accept);
- if (!acceptFragment) {
- throw new Error('accept-Array darf nicht leer sein.');
+ if (accept.length === 0) {
+ throw new Error("accept-Array darf nicht leer sein.");
}
- const disallowFragment = wordsToFragment(disallow);
+ const flags = options.flags ?? "";
+ const ignoreCase = flags.includes("i");
+
+ const disallowSet = new Set(
+ disallow.map((word) => (ignoreCase ? word.toLocaleLowerCase() : word)),
+ );
- // Boolesche Verknüpfung: Accept AND NOT Disallow
- const negativeLookahead = disallowFragment
- ? `(?!^(?:${disallowFragment})$)`
- : '';
+ const effectiveAccept = accept.filter((word) => {
+ const key = ignoreCase ? word.toLocaleLowerCase() : word;
+ return !disallowSet.has(key);
+ });
+
+ if (effectiveAccept.length === 0) {
+ throw new Error("Alle akzeptierten Wörter werden abgelehnt.");
+ }
- const pattern = `^${negativeLookahead}(?:${acceptFragment})$`;
+ const acceptFragment = wordsToFragment(effectiveAccept);
+
+ if (!acceptFragment) {
+ throw new Error("Keine gültigen akzeptierten Wörter.");
+ }
- return new RegExp(pattern, options.flags ?? '');
+ return new RegExp(`^(?:${acceptFragment})$`, flags);
}
// // ------------------------------------------------------------
diff --git a/finder-template-generator-ssg/src/templates.js b/finder-template-generator-ssg/src/templates.js
index 2b1f7d90..ddd92cbb 100644
--- a/finder-template-generator-ssg/src/templates.js
+++ b/finder-template-generator-ssg/src/templates.js
@@ -3016,6 +3016,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"llama.json5": {
@@ -3042,6 +3043,7 @@ export default {
"name": "scripts"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"llvm.json5": {
@@ -3068,6 +3070,7 @@ export default {
"name": "tools"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"loom.json5": {
@@ -3082,6 +3085,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"lua.json5": {
@@ -3096,6 +3100,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"makecode.json5": {
@@ -3104,6 +3109,7 @@ export default {
"*.json"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"mapbox.json5": {
@@ -3119,6 +3125,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"markdown-docs.json5": {
@@ -3134,6 +3141,7 @@ export default {
"name": "content"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"marko.json5": {
@@ -3149,6 +3157,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"matlab.json5": {
@@ -3158,6 +3167,7 @@ export default {
"*.mlx"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"mcdatapack.json5": {
@@ -3212,6 +3222,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"metabase.json5": {
@@ -3220,6 +3231,7 @@ export default {
"docker-compose.yml"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"microservices.json5": {
@@ -3243,6 +3255,7 @@ export default {
"level.dat"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"mistral.json5": {
@@ -3262,6 +3275,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"mlflow.json5": {
@@ -3288,6 +3302,7 @@ export default {
"name": "experiments"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"mocha.json5": {
@@ -3303,6 +3318,7 @@ export default {
"name": "test"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"modal.json5": {
@@ -3321,6 +3337,7 @@ export default {
"name": "functions"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"mongodb.json5": {
@@ -3335,6 +3352,7 @@ export default {
"name": "schemas"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"monogame.json5": {
@@ -3349,7 +3367,12 @@ export default {
"name": "Content"
}
],
- "name": "*"
+ "min_version": "0.3.16",
+ "name": "*",
+ "tags": [
+ "game-engine",
+ "C#"
+ ]
},
"monorepo.json5": {
"description": "Monorepo project (multiple packages)",
@@ -3364,6 +3387,7 @@ export default {
"name": "packages"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"motioncanvas.json5": {
@@ -3379,6 +3403,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"move.json5": {
@@ -3396,6 +3421,7 @@ export default {
"name": "sources"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"mysql.json5": {
@@ -3411,6 +3437,7 @@ export default {
"name": "migrations"
}
],
+ "min_version": "0.3.16",
"name": "*",
"tags": [
"sql"
@@ -3538,6 +3565,7 @@ export default {
"name": "contracts"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"nim.json5": {
@@ -3764,6 +3792,7 @@ export default {
"otel-collector-config.yml"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"pagerduty.json5": {
@@ -3772,6 +3801,7 @@ export default {
"pagerduty.yml"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"panda3d.json5": {
@@ -3786,7 +3816,12 @@ export default {
"name": "models"
}
],
- "name": "*"
+ "min_version": "0.3.16",
+ "name": "*",
+ "tags": [
+ "game-engine",
+ "python"
+ ]
},
"pandas.json5": {
"description": "Pandas data analysis library",
@@ -3795,6 +3830,7 @@ export default {
"*.py"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"panel.json5": {
@@ -3813,6 +3849,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"parcel.json5": {
@@ -3828,6 +3865,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"payload.json5": {
@@ -3843,6 +3881,7 @@ export default {
"name": "src"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"perl.json5": {
@@ -3858,6 +3897,7 @@ export default {
"name": "lib"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"perplexity.json5": {
@@ -3875,6 +3915,7 @@ export default {
"name": "queries"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"perseus.json5": {
@@ -3987,6 +4028,7 @@ export default {
"name": "tests"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"pnpm-workspace.json5": {
@@ -4002,6 +4044,7 @@ export default {
"name": "packages"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"pocketbase.json5": {
@@ -4016,6 +4059,7 @@ export default {
"name": "pb_migrations"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"podman.json5": {
@@ -4025,6 +4069,7 @@ export default {
"podman-compose.yml"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"poetry.json5": {
@@ -4034,6 +4079,7 @@ export default {
"poetry.lock"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"polars.json5": {
@@ -4061,6 +4107,7 @@ export default {
"docker-compose.yml"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"postgrest.json5": {
@@ -4069,6 +4116,7 @@ export default {
"postgrest.conf"
],
"folders": [],
+ "min_version": "0.3.16",
"name": "*"
},
"prefect.json5": {
@@ -4087,6 +4135,7 @@ export default {
"name": "flows"
}
],
+ "min_version": "0.3.16",
"name": "*"
},
"presto.json5": {
From 2d2177acd9c8b548d5fa0ae34a0e716cf4d8dc0d Mon Sep 17 00:00:00 2001
From: ShadowDara <128976697+ShadowDara@users.noreply.github.com>
Date: Tue, 8 Sep 2026 23:19:27 +0200
Subject: [PATCH 04/14] added info to help
---
cmd/findergen/cli.go | 4 ++--
internal/cli/commands.go | 18 +++++++++---------
pub/argparser/parse.go | 17 +++++++++++------
3 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/cmd/findergen/cli.go b/cmd/findergen/cli.go
index e4f4167f..2c92ab3c 100644
--- a/cmd/findergen/cli.go
+++ b/cmd/findergen/cli.go
@@ -19,11 +19,11 @@ func parseCliArgs() Conf {
// NEW
root := argparser.NewCommand("findergen",
- "the http server for finder to create and view templates", false)
+ "the http server for finder to create and view templates", "Check out github for more infos or the finder website:\nhttps://github.com/shadowdara/finder\nhttps://shadowdara.github.io/finder", false)
// Add Version Command
versionCmd := argparser.NewCommand(
- "--version", "to get the Version of the Program", false, "-v", "v", "version")
+ "--version", "to get the Version of the Program", "", false, "-v", "v", "version")
// Port
root.Number("port", 0, "Change the Server Port", false, "p")
diff --git a/internal/cli/commands.go b/internal/cli/commands.go
index d843592e..b4538b70 100644
--- a/internal/cli/commands.go
+++ b/internal/cli/commands.go
@@ -32,7 +32,7 @@ func HandleCommand(args []string) {
// NEW
root := argparser.NewCommand("finder",
- "a simple go program to find your files via file structures", false)
+ "a simple go program to find your files via file structures", "Check out github for more infos or the finder website:\nhttps://github.com/shadowdara/finder\nhttps://shadowdara.github.io/finder", false)
// Add option for JSON Output
root.GlobalBool("json", false, "Enable JSON Output", "j")
@@ -51,12 +51,12 @@ func HandleCommand(args []string) {
// Add Version Command
versionCmd := argparser.NewCommand(
- "--version", "to get the Version of the Program", false, "-v", "v", "version")
+ "--version", "to get the Version of the Program", "", false, "-v", "v", "version")
// Temaplte Command
templateCmd := argparser.NewCommand("template",
"to search for a template - for the case that the name for a template is overwritten by another argument name",
- false, "tpl")
+ "", false, "tpl")
// Create Cache
templateCmd.Bool("create-cache", false, "Create the Cache", false, "cc")
@@ -69,26 +69,26 @@ func HandleCommand(args []string) {
// Check Command
checkCmd := argparser.NewCommand("check",
- "to check all available Templates if their syntax is correct", false)
+ "to check all available Templates if their syntax is correct", "", false)
// list, ls Command
listCmd := argparser.NewCommand("list",
- "list all available templates", false, "ls")
+ "list all available templates", "", false, "ls")
// tags, tag Command
tagsCmd := argparser.NewCommand("tags",
- "show all tags in the console", false, "tag")
+ "show all tags in the console", "", false, "tag")
// Tag Search
tagSearchCmd := argparser.NewCommand("-t",
- "search for tags with the next argument", false)
+ "search for tags with the next argument", "", false)
// BinarySearch
binarySearchCmd := argparser.NewCommand(
- "-b", "search for executables in path", false)
+ "-b", "search for executables in path", "", false)
// Config Path
- configpathCmd := argparser.NewCommand("cp", "Get the path to the global config", false)
+ configpathCmd := argparser.NewCommand("cp", "Get the path to the global config", "", false)
root.AddSubcommand(versionCmd)
root.AddSubcommand(templateCmd)
diff --git a/pub/argparser/parse.go b/pub/argparser/parse.go
index a00d845f..01ab7f10 100644
--- a/pub/argparser/parse.go
+++ b/pub/argparser/parse.go
@@ -53,28 +53,31 @@ type Command struct {
Hidden bool // If true, command is hidden from help output
Aliases []string // Alternative names (e.g. "rm" for "remove")
Description string // Description shown in help output
+ Descend string // Additional lines displayed at the end of help output
Flags map[string]*Flag // Registered flags
Subcommands map[string]*Command // Registered subcommands
Parent *Command // Parent command (used to build full path)
Args []string // Positional arguments
- PassThrough bool // If true, preserve all parsed arguments unchanged
+ PassThrough bool // If true, preserve all parsed arguments unchanged
}
// NewCommand creates a new Command.
//
// Parameters:
//
-// name → command name
-// desc → description for help output
-// hidden → whether the command should be hidden
-// aliases → optional aliases
-func NewCommand(name, desc string, hidden bool, aliases ...string) *Command {
+// name → command name
+// desc → description for help output
+// descend → lines which are displayed at the end of the help output
+// hidden → whether the command should be hidden
+// aliases → optional aliases
+func NewCommand(name, desc string, descend string, hidden bool, aliases ...string) *Command {
cmd := &Command{
Name: name,
Hidden: hidden,
Aliases: aliases,
Description: desc,
+ Descend: descend,
Flags: make(map[string]*Flag),
Subcommands: make(map[string]*Command),
}
@@ -505,6 +508,8 @@ func (c *Command) PrintHelp() {
fmt.Fprintln(w)
}
+ fmt.Println(c.Descend)
+
w.Flush()
}
From be035fa6457e553560380cd102d2fee386572ea0 Mon Sep 17 00:00:00 2001
From: ShadowDara <128976697+ShadowDara@users.noreply.github.com>
Date: Tue, 8 Sep 2026 23:35:27 +0200
Subject: [PATCH 05/14] tets
---
finder-template-generator-ssg/pages/viewer.tsx | 4 ++--
templates/npm.json5 | 8 +++++++-
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/finder-template-generator-ssg/pages/viewer.tsx b/finder-template-generator-ssg/pages/viewer.tsx
index dd9156fb..59fb6b60 100644
--- a/finder-template-generator-ssg/pages/viewer.tsx
+++ b/finder-template-generator-ssg/pages/viewer.tsx
@@ -82,11 +82,11 @@ function renderStatic(el: HTMLDivElement) {
Durchsuche und erkunde alle verfügbaren Templates.
+ {isStatic
+ ? "Browse and explore all available templates."
+ : "Search and explore all available templates."}
+ Versuche einen anderen Suchbegriff. Try a different search term. Durchsuche und erkunde alle verfügbaren Templates. Versuche einen anderen Suchbegriff. Der Template-Server ist momentan nicht erreichbar. The template server is currently not reachable. The whole finder CHANGELOG This version brings the biggest improvement since 0.2.0: Template System & CLI Foundations More Templates Better Console Output Help Message Programm Init the start Port for the findergen server to view and create templates. When set to true, the results of will be saved as a cache and can then be used afterwards When set to true, the cache data of finder will be saved in a Git DB. Git is required for this. Finder instances which will run at the same time when creating cache for all templates soon The whole finder CHANGELOG This version brings the biggest improvement since 0.2.0: Template System & CLI Foundations More Templates Better Console Output Help Message Programm Init the start Port for the findergen server to view and create templates. When set to true, the results of will be saved as a cache and can then be used afterwards When set to true, the cache data of finder will be saved in a Git DB. Git is required for this. Finder instances which will run at the same time when creating cache for all templates soon Finder is a small command-line tool written in Go to locate projects based on predefined folder/file structure templates. In short: you can search for repositories (e.g. feel free to help the Project by committing Code for the project are Templates. Feel although free to submit Templates via Issues! Build from source: Or install with The produced binary is Basic syntax: Example — find Git repositories: The program searches the current directory recursively and prints matches based on the template name. Default templates are stored in Finder is a small command-line tool written in Go to locate projects based on predefined folder/file structure templates. In short: you can search for repositories (e.g. feel free to help the Project by committing Code for the project are Templates. Feel although free to submit Templates via Issues! Build from source: Or install with The produced binary is Basic syntax: Example — find Git repositories: The program searches the current directory recursively and prints matches based on the template name. Default templates are stored in For more and detailed Information and more config values check out the config editor here I thing i would change is to use raw JSON for the templates instead of JSON with comments, which i called JSON5 back then, but it is no real JSON5. Run tests: Generate coverage report: Build: Check the available Templates See Project: The Project fs-tools was more or less the prototype for finder. (a Youtube Video) Build: Check the available Templates See Project: The Project fs-tools was more or less the prototype for finder. (a Youtube Video) Folder opened - Tab is closing or close it manually if this didnt work! Some Infos about the Programm This is the Homepage of the Server The whole finder CHANGELOG This version brings the biggest improvement since 0.2.0: Template System & CLI Foundations More Templates Better Console Output Help Message Programm Init the start Port for the findergen server to view and create templates. When set to true, the results of will be saved as a cache and can then be used afterwards When set to true, the cache data of finder will be saved in a Git DB. Git is required for this. Finder instances which will run at the same time when creating cache for all templates soon The whole finder CHANGELOG This version brings the biggest improvement since 0.2.0: Template System & CLI Foundations More Templates Better Console Output Help Message Programm Init the start Port for the findergen server to view and create templates. When set to true, the results of will be saved as a cache and can then be used afterwards When set to true, the cache data of finder will be saved in a Git DB. Git is required for this. Finder instances which will run at the same time when creating cache for all templates soon Finder is a small command-line tool written in Go to locate projects based on predefined folder/file structure templates. In short: you can search for repositories (e.g. feel free to help the Project by committing Code for the project are Templates. Feel although free to submit Templates via Issues! Build from source: Or install with The produced binary is Basic syntax: Example — find Git repositories: The program searches the current directory recursively and prints matches based on the template name. Default templates are stored in Finder is a small command-line tool written in Go to locate projects based on predefined folder/file structure templates. In short: you can search for repositories (e.g. feel free to help the Project by committing Code for the project are Templates. Feel although free to submit Templates via Issues! Build from source: Or install with The produced binary is Basic syntax: Example — find Git repositories: The program searches the current directory recursively and prints matches based on the template name. Default templates are stored in For more and detailed Information and more config values check out the config editor here I thing i would change is to use raw JSON for the templates instead of JSON with comments, which i called JSON5 back then, but it is no real JSON5. Run tests: Generate coverage report: Build: Check the available Templates See Project: The Project fs-tools was more or less the prototype for finder. (a Youtube Video) Build: Check the available Templates See Project: The Project fs-tools was more or less the prototype for finder. (a Youtube Video) Infos about the Programm Closes the Program completly
+ See 0
+
+ See 0
+ Folder opened - Tab is closing or close it manually if this didnt work! Folder opened - Tab is closing or close it manually if this didn't work!Templates
- Keine Templates gefunden
- No templates found
+ Templates
-
-
- Keine Templates gefunden
- Templates konnten nicht geladen werden.
- Templates could not be loaded.
+ CHANGELOG
Newest prob 0.3.17
0.3.16 - 08.09.2026
SHA256SUMS to SHA256SUMS.txt0.3.15 - 02.09.2025
--json to command0.3.14 - 25.06.2026
0.3.13 - 22.06.2026
0.3.12 - 22.06.2026
0.3.11 - 10.04.2026
0.3.10 - 10.04.2026
0.3.9 - 09.04.2026
0.3.8 - 27.02.2026
0.3.7 - 24.02.2026
0.3.6 - 24.02.2026
CUSTOM_TEMPLATES0.3.5 - 18.02.2026
0.3.4 - 16.02.2026
Search on all Drives on Windows from 0.3.3, it0.3.3 - 15.02.2026
0.3.2 - 15.02.2026
0.3.1 - 15.02.2026
✨ Features
Runtime Custom Template System
~/.finder/templates/ or ./.finder/templates/ without recompiling the program.json5 files are automatically detected and loaded on startupCLI Reorganization & Modernization
parser.go: Dedicated argument parsing logichandlers.go: Isolated command handlerscommands.go: Clean routing (reduced from 300+ to 60 lines)h, -h, --help in addition to helpls in addition to list--file in addition to -f--config in addition to -c.IsHelp(), .IsList(), .IsCheck(), .IsFileLoad(), .IsDirectLoad(), .IsTemplateSearch().GetFileArg(), .GetDirectLoadArg(), .GetTemplateName()--verbose flag for extended outputEnhanced Help System
Enhanced List & Check Commands
🧪 Testing
📖 Documentation
🔧 Infrastructure
templateloader.go)LoadUserTemplates(): Discovers user templates from filesystemJSONtemplateLoaderWithUserTemplates(): Intelligent loading with user overrideLoadAllWithUserTemplates(): Combined built-in + custom template discovery🎯 Quality Improvements
HandleCommand()) unchanged👥 User Experience
📊 Performance
🐛 Bug Fixes & Improvements
📝 Breaking Changes
🙏 Highlights
0.3.0 - 23.01.2026
0.2.0 - 23.01.2026
0.1.0 - 17.11.2025
0.0.0 - 30.11.2025
Config fields
Port
Cache
Create Cache Database
Finder Instances
Finder Docs
# AGENTS — Finder Template Authoring Guide
+const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cacheviewer.js","./cacheviewer.css","./configeditor.js","./configeditor.css","./creator.js","./creator.css","./home.js","./home.css","./about.js","./mcappheader.js","./mcappheader.css","./index2.js","./worlds.js","./regexcreator.js","./regexcreator.css","./samfile.js","./jquery.module.js","./samfile.css","./markdowneditor.js","./markdowneditor.css","./tellraw.js","./tellraw.css","./viewer.js","./viewer.css"])))=>i.map(i=>d[i]);
+const x="modulepreload",T=function(e,s){return new URL(e,s).href},j={},r=function(s,n,a){let u=Promise.resolve();if(n&&n.length>0){const p=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),i=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));u=Promise.allSettled(n.map(o=>{if(o=T(o,a),o in j)return;j[o]=!0;const c=o.endsWith(".css"),_=c?'[rel="stylesheet"]':"";if(!!a)for(let h=p.length-1;h>=0;h--){const f=p[h];if(f.href===o&&(!c||f.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${o}"]${_}`))return;const d=document.createElement("link");if(d.rel=c?"stylesheet":x,c||(d.as="script"),d.crossOrigin="",d.href=o,i&&d.setAttribute("nonce",i),document.head.appendChild(d),c)return new Promise((h,f)=>{d.addEventListener("load",h),d.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${o}`)))})}))}function g(p){const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=p,window.dispatchEvent(l),!l.defaultPrevented)throw p}return u.then(p=>{for(const l of p||[])l.status==="rejected"&&g(l.reason);return s().catch(g)})},m=""+new URL("markdownrootstyle.css",import.meta.url).href,S=""+new URL("markdownstyle.css",import.meta.url).href,b={cacheviewer:{id:"cacheviewer",type:"component",load:()=>r(()=>import("./cacheviewer.js"),__vite__mapDeps([0,1]),import.meta.url),data:null,styles:[]},changelog:{id:"changelog",type:"markdown",html:'CHANGELOG
Newest prob 0.3.17
0.3.16 - 08.09.2026
SHA256SUMS to SHA256SUMS.txt0.3.15 - 02.09.2025
--json to command0.3.14 - 25.06.2026
0.3.13 - 22.06.2026
0.3.12 - 22.06.2026
0.3.11 - 10.04.2026
0.3.10 - 10.04.2026
0.3.9 - 09.04.2026
0.3.8 - 27.02.2026
0.3.7 - 24.02.2026
0.3.6 - 24.02.2026
CUSTOM_TEMPLATES0.3.5 - 18.02.2026
0.3.4 - 16.02.2026
Search on all Drives on Windows from 0.3.3, it0.3.3 - 15.02.2026
0.3.2 - 15.02.2026
0.3.1 - 15.02.2026
✨ Features
Runtime Custom Template System
~/.finder/templates/ or ./.finder/templates/ without recompiling the program.json5 files are automatically detected and loaded on startupCLI Reorganization & Modernization
parser.go: Dedicated argument parsing logichandlers.go: Isolated command handlerscommands.go: Clean routing (reduced from 300+ to 60 lines)h, -h, --help in addition to helpls in addition to list--file in addition to -f--config in addition to -c.IsHelp(), .IsList(), .IsCheck(), .IsFileLoad(), .IsDirectLoad(), .IsTemplateSearch().GetFileArg(), .GetDirectLoadArg(), .GetTemplateName()--verbose flag for extended outputEnhanced Help System
Enhanced List & Check Commands
🧪 Testing
📖 Documentation
🔧 Infrastructure
templateloader.go)LoadUserTemplates(): Discovers user templates from filesystemJSONtemplateLoaderWithUserTemplates(): Intelligent loading with user overrideLoadAllWithUserTemplates(): Combined built-in + custom template discovery🎯 Quality Improvements
HandleCommand()) unchanged👥 User Experience
📊 Performance
🐛 Bug Fixes & Improvements
📝 Breaking Changes
🙏 Highlights
0.3.0 - 23.01.2026
0.2.0 - 23.01.2026
0.1.0 - 17.11.2025
0.0.0 - 30.11.2025
Config fields
Port
Cache
Create Cache Database
Finder Instances
Finder Docs
`,styles:[m]},readme:{id:"readme",type:"markdown",html:`# AGENTS — Finder Template Authoring Guide
This document is for AI assistants such as ChatGPT, Claude, Copilot,
and similar tools that need to create valid Finder templates.
@@ -617,7 +617,7 @@ If the task is to add a template to this project, keep in mind:
This repo has built-in examples in the templates folder and the project
docs in the root files.
-finder
.git), project layouts, or your own custom structures using templates.Commiting
Features
internal/structure/templates.Requirements
Installation
go build ./cmd/findergo install (Go 1.18+):go install github.com/shadowdara/finder/cmd/finder@latestfinder (on Windows finder.exe).Usage
finder <template-name>finder gitTemplates
internal/structure/templates. Templates are JSON5 files with fields such as name, files, and folders. A simple template to find Git repositories looks like:
`,styles:[m]},"mcapp/about":{id:"mcapp/about",type:"component",load:()=>r(()=>import("./about.js"),__vite__mapDeps([8,9,10]),import.meta.url),data:null,styles:[]},"mcapp/index":{id:"mcapp/index",type:"component",load:()=>r(()=>import("./index2.js"),__vite__mapDeps([11,9,10]),import.meta.url),data:null,styles:[]},"mcapp/worlds":{id:"mcapp/worlds",type:"component",load:()=>r(()=>import("./worlds.js"),__vite__mapDeps([12,9,10]),import.meta.url),data:null,styles:[]},readme:{id:"readme",type:"markdown",html:`// Template for Git
+finder
.git), project layouts, or your own custom structures using templates.Commiting
Features
internal/structure/templates.Requirements
Installation
go build ./cmd/findergo install (Go 1.18+):go install github.com/shadowdara/finder/cmd/finder@latestfinder (on Windows finder.exe).Usage
finder <template-name>finder gitTemplates
internal/structure/templates. Templates are JSON5 files with fields such as name, files, and folders. A simple template to find Git repositories looks like:// Template for Git
{
"name": "*",
"folders": [{ "name": ".git" }]
@@ -639,4 +639,4 @@ docs in the root files.
// You dont have to use it obviously
"create_cache_db": false
}Mistakes
Development
go test ./...go test -coverprofile=coverage ./...
-go tool cover -html=coveragego build ./cmd/findergo run ./cmd/finder checkContributing
Roadmap / Ideas
License
LICENSE.https://github.com/shadowdara/finderExtra Info
Info Video
go build ./cmd/findergo run ./cmd/finder checkContributing
Roadmap / Ideas
License
LICENSE.https://github.com/shadowdara/finderExtra Info
Info Video
About
+ MC APP
+ Features
+
+
+
+
+
+
+
+
+
+ Icon
+ Folder Name
+ Last Modified
+ Size
+ Path
+
+
+
+
{lastFolder}
+ {world.last_modified}
+ {size}
+
+
+ {path}
+
+
+ >
+ );
+
+ tbody.appendChild(tr);
+ });
+ } catch (err) {
+ console.error("Fehler beim Laden:", err);
+ }
+ });
+}
diff --git a/finder-template-generator-ssg/public/install.sh b/finder-template-generator-ssg/public/install.sh
index 1b080010..69e88ea6 100644
--- a/finder-template-generator-ssg/public/install.sh
+++ b/finder-template-generator-ssg/public/install.sh
@@ -86,3 +86,8 @@ echo
echo "Finder installed successfully!"
echo
echo " $INSTALL_DIR/finder"
+
+if [[ ":$PATH:" != *":$INSTALL_DIR:"* ]]; then
+ echo "export PATH=\"\$PATH:$INSTALL_DIR\"" >> "$HOME/.bashrc"
+ export PATH="$PATH:$INSTALL_DIR"
+fi
diff --git a/finder-template-generator-ssg/src/components/mcappheader.jsx b/finder-template-generator-ssg/src/components/mcappheader.jsx
new file mode 100644
index 00000000..f596b168
--- /dev/null
+++ b/finder-template-generator-ssg/src/components/mcappheader.jsx
@@ -0,0 +1,24 @@
+import { escapeHtml, jsx, raw, Fragment } from "../jsx-runtime";
+import "./mcappstyle.css";
+
+export default function render() {
+ return (
+ <>
+ CHANGELOG
Newest prob 0.3.17
0.3.16 - 08.09.2026
SHA256SUMS to SHA256SUMS.txt0.3.15 - 02.09.2025
--json to command0.3.14 - 25.06.2026
0.3.13 - 22.06.2026
0.3.12 - 22.06.2026
0.3.11 - 10.04.2026
0.3.10 - 10.04.2026
0.3.9 - 09.04.2026
0.3.8 - 27.02.2026
0.3.7 - 24.02.2026
0.3.6 - 24.02.2026
CUSTOM_TEMPLATES0.3.5 - 18.02.2026
0.3.4 - 16.02.2026
Search on all Drives on Windows from 0.3.3, it0.3.3 - 15.02.2026
0.3.2 - 15.02.2026
0.3.1 - 15.02.2026
✨ Features
Runtime Custom Template System
~/.finder/templates/ or ./.finder/templates/ without recompiling the program.json5 files are automatically detected and loaded on startupCLI Reorganization & Modernization
parser.go: Dedicated argument parsing logichandlers.go: Isolated command handlerscommands.go: Clean routing (reduced from 300+ to 60 lines)h, -h, --help in addition to helpls in addition to list--file in addition to -f--config in addition to -c.IsHelp(), .IsList(), .IsCheck(), .IsFileLoad(), .IsDirectLoad(), .IsTemplateSearch().GetFileArg(), .GetDirectLoadArg(), .GetTemplateName()--verbose flag for extended outputEnhanced Help System
Enhanced List & Check Commands
🧪 Testing
📖 Documentation
🔧 Infrastructure
templateloader.go)LoadUserTemplates(): Discovers user templates from filesystemJSONtemplateLoaderWithUserTemplates(): Intelligent loading with user overrideLoadAllWithUserTemplates(): Combined built-in + custom template discovery🎯 Quality Improvements
HandleCommand()) unchanged👥 User Experience
📊 Performance
🐛 Bug Fixes & Improvements
📝 Breaking Changes
🙏 Highlights
0.3.0 - 23.01.2026
0.2.0 - 23.01.2026
0.1.0 - 17.11.2025
0.0.0 - 30.11.2025
Config fields
Port
Cache
Create Cache Database
Finder Instances
Finder Docs
# AGENTS — Finder Template Authoring Guide
+const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["./cacheviewer.js","./cacheviewer.css","./configeditor.js","./configeditor.css","./creator.js","./creator.css","./home.js","./home.css","./about.js","./mcappheader.js","./mcappheader.css","./index2.js","./info.js","./worlds.js","./regexcreator.js","./regexcreator.css","./samfile.js","./jquery.module.js","./samfile.css","./markdowneditor.js","./markdowneditor.css","./tellraw.js","./tellraw.css","./viewer.js","./viewer.css"])))=>i.map(i=>d[i]);
+const T="modulepreload",x=function(e,s){return new URL(e,s).href},j={},r=function(s,n,a){let u=Promise.resolve();if(n&&n.length>0){const p=document.getElementsByTagName("link"),l=document.querySelector("meta[property=csp-nonce]"),i=(l==null?void 0:l.nonce)||(l==null?void 0:l.getAttribute("nonce"));u=Promise.allSettled(n.map(o=>{if(o=x(o,a),o in j)return;j[o]=!0;const c=o.endsWith(".css"),_=c?'[rel="stylesheet"]':"";if(!!a)for(let h=p.length-1;h>=0;h--){const f=p[h];if(f.href===o&&(!c||f.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${o}"]${_}`))return;const d=document.createElement("link");if(d.rel=c?"stylesheet":T,c||(d.as="script"),d.crossOrigin="",d.href=o,i&&d.setAttribute("nonce",i),document.head.appendChild(d),c)return new Promise((h,f)=>{d.addEventListener("load",h),d.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${o}`)))})}))}function g(p){const l=new Event("vite:preloadError",{cancelable:!0});if(l.payload=p,window.dispatchEvent(l),!l.defaultPrevented)throw p}return u.then(p=>{for(const l of p||[])l.status==="rejected"&&g(l.reason);return s().catch(g)})},m=""+new URL("markdownrootstyle.css",import.meta.url).href,S=""+new URL("markdownstyle.css",import.meta.url).href,b={cacheviewer:{id:"cacheviewer",type:"component",load:()=>r(()=>import("./cacheviewer.js"),__vite__mapDeps([0,1]),import.meta.url),data:null,styles:[]},changelog:{id:"changelog",type:"markdown",html:'CHANGELOG
Newest prob 0.3.17
0.3.16 - 08.09.2026
SHA256SUMS to SHA256SUMS.txt0.3.15 - 02.09.2025
--json to command0.3.14 - 25.06.2026
0.3.13 - 22.06.2026
0.3.12 - 22.06.2026
0.3.11 - 10.04.2026
0.3.10 - 10.04.2026
0.3.9 - 09.04.2026
0.3.8 - 27.02.2026
0.3.7 - 24.02.2026
0.3.6 - 24.02.2026
CUSTOM_TEMPLATES0.3.5 - 18.02.2026
0.3.4 - 16.02.2026
Search on all Drives on Windows from 0.3.3, it0.3.3 - 15.02.2026
0.3.2 - 15.02.2026
0.3.1 - 15.02.2026
✨ Features
Runtime Custom Template System
~/.finder/templates/ or ./.finder/templates/ without recompiling the program.json5 files are automatically detected and loaded on startupCLI Reorganization & Modernization
parser.go: Dedicated argument parsing logichandlers.go: Isolated command handlerscommands.go: Clean routing (reduced from 300+ to 60 lines)h, -h, --help in addition to helpls in addition to list--file in addition to -f--config in addition to -c.IsHelp(), .IsList(), .IsCheck(), .IsFileLoad(), .IsDirectLoad(), .IsTemplateSearch().GetFileArg(), .GetDirectLoadArg(), .GetTemplateName()--verbose flag for extended outputEnhanced Help System
Enhanced List & Check Commands
🧪 Testing
📖 Documentation
🔧 Infrastructure
templateloader.go)LoadUserTemplates(): Discovers user templates from filesystemJSONtemplateLoaderWithUserTemplates(): Intelligent loading with user overrideLoadAllWithUserTemplates(): Combined built-in + custom template discovery🎯 Quality Improvements
HandleCommand()) unchanged👥 User Experience
📊 Performance
🐛 Bug Fixes & Improvements
📝 Breaking Changes
🙏 Highlights
0.3.0 - 23.01.2026
0.2.0 - 23.01.2026
0.1.0 - 17.11.2025
0.0.0 - 30.11.2025
Config fields
Port
Cache
Create Cache Database
Finder Instances
Finder Docs
`,styles:[m]},"mcapp/about":{id:"mcapp/about",type:"component",load:()=>r(()=>import("./about.js"),__vite__mapDeps([8,9,10]),import.meta.url),data:null,styles:[]},"mcapp/index":{id:"mcapp/index",type:"component",load:()=>r(()=>import("./index2.js"),__vite__mapDeps([11,9,10]),import.meta.url),data:null,styles:[]},"mcapp/worlds":{id:"mcapp/worlds",type:"component",load:()=>r(()=>import("./worlds.js"),__vite__mapDeps([12,9,10]),import.meta.url),data:null,styles:[]},readme:{id:"readme",type:"markdown",html:`# AGENTS — Finder Template Authoring Guide
This document is for AI assistants such as ChatGPT, Claude, Copilot,
and similar tools that need to create valid Finder templates.
@@ -617,7 +617,7 @@ If the task is to add a template to this project, keep in mind:
This repo has built-in examples in the templates folder and the project
docs in the root files.
-finder
.git), project layouts, or your own custom structures using templates.Commiting
Features
internal/structure/templates.Requirements
Installation
go build ./cmd/findergo install (Go 1.18+):go install github.com/shadowdara/finder/cmd/finder@latestfinder (on Windows finder.exe).Usage
finder <template-name>finder gitTemplates
internal/structure/templates. Templates are JSON5 files with fields such as name, files, and folders. A simple template to find Git repositories looks like:
`,styles:[m]},"mcapp/about":{id:"mcapp/about",type:"component",load:()=>r(()=>import("./about.js"),__vite__mapDeps([8,9,10]),import.meta.url),data:null,styles:[]},"mcapp/index":{id:"mcapp/index",type:"component",load:()=>r(()=>import("./index2.js"),__vite__mapDeps([11,9,10]),import.meta.url),data:null,styles:[]},"mcapp/info":{id:"mcapp/info",type:"component",load:()=>r(()=>import("./info.js"),__vite__mapDeps([12,9,10]),import.meta.url),data:null,styles:[]},"mcapp/worlds":{id:"mcapp/worlds",type:"component",load:()=>r(()=>import("./worlds.js"),__vite__mapDeps([13,9,10]),import.meta.url),data:null,styles:[]},readme:{id:"readme",type:"markdown",html:`// Template for Git
+finder
.git), project layouts, or your own custom structures using templates.Commiting
Features
internal/structure/templates.Requirements
Installation
go build ./cmd/findergo install (Go 1.18+):go install github.com/shadowdara/finder/cmd/finder@latestfinder (on Windows finder.exe).Usage
finder <template-name>finder gitTemplates
internal/structure/templates. Templates are JSON5 files with fields such as name, files, and folders. A simple template to find Git repositories looks like:// Template for Git
{
"name": "*",
"folders": [{ "name": ".git" }]
@@ -639,4 +639,4 @@ docs in the root files.
// You dont have to use it obviously
"create_cache_db": false
}Mistakes
Development
go test ./...go test -coverprofile=coverage ./...
-go tool cover -html=coveragego build ./cmd/findergo run ./cmd/finder checkContributing
Roadmap / Ideas
License
LICENSE.https://github.com/shadowdara/finderExtra Info
Info Video
go build ./cmd/findergo run ./cmd/finder checkContributing
Roadmap / Ideas
License
LICENSE.https://github.com/shadowdara/finderExtra Info
Info Video
Features
>
diff --git a/finder-template-generator-ssg/pages/mcapp/info.jsx b/finder-template-generator-ssg/pages/mcapp/info.jsx
new file mode 100644
index 00000000..19c003e7
--- /dev/null
+++ b/finder-template-generator-ssg/pages/mcapp/info.jsx
@@ -0,0 +1,42 @@
+import { escapeHtml, jsx, raw, Fragment } from "../../src/jsx-runtime";
+import Header from "../../src/components/mcappheader.jsx";
+import * as f from "../../src/components/mcappstyle.js";
+
+export default function render(el) {
+ el.innerHTML = (
+ <>
+ Info
+ Commands
+ 0
+ 1
+ 2
+ exit
+ quit
+ status
+
-
+
{lastFolder}
{world.last_modified}
@@ -91,5 +100,7 @@ export default function render(el) {
} catch (err) {
console.error("Fehler beim Laden:", err);
}
- });
+ }
+
+ loadWorlds();
}
diff --git a/finder-template-generator-ssg/src/components/mcappheader.jsx b/finder-template-generator-ssg/src/components/mcappheader.jsx
index f596b168..59253571 100644
--- a/finder-template-generator-ssg/src/components/mcappheader.jsx
+++ b/finder-template-generator-ssg/src/components/mcappheader.jsx
@@ -8,13 +8,13 @@ export default function render() {
diff --git a/internal/mcapp/args.go b/internal/mcapp/args.go
new file mode 100644
index 00000000..afaf3c26
--- /dev/null
+++ b/internal/mcapp/args.go
@@ -0,0 +1,100 @@
+package mcapp
+
+// import (
+// "fmt"
+// "log"
+// )
+
+// // ParseArgs interpretiert Befehle.
+// // Rückgabewert: true = Programm beenden
+// func ParseArgs(args []string, serverRunning *bool) bool {
+// if len(args) == 0 {
+// return false
+// }
+
+// cmd := args[0]
+
+// switch cmd {
+// case "exit", "quit", "0":
+// Stop()
+// log.Println("Programm existed.")
+// return true
+
+// case "status":
+// fmt.Println("=================================================")
+// fmt.Println("Status Response")
+// if *serverRunning {
+// fmt.Println("HTTP Server is running")
+// } else {
+// fmt.Println("HTTP Server is off")
+// }
+// fmt.Println("=================================================")
+
+// case "clean":
+// fmt.Println("Should delete caches\nimplemented soon")
+
+// case "server", "1":
+// if *serverRunning {
+// log.Println("HTTP Server läuft bereits.")
+// } else {
+// go Server()
+// *serverRunning = true
+// log.Println("HTTP Server starting.")
+// }
+
+// case "serverstop":
+// if *serverRunning {
+// Stop()
+// *serverRunning = false
+// log.Println("HTTP Server gestoppt.")
+// } else {
+// log.Println("HTTP Server ist nicht aktiv.")
+// }
+
+// case "open", "2":
+// if !*serverRunning {
+// log.Println("HTTP Server is not running - Starting")
+// go Server()
+// *serverRunning = true
+// }
+// log.Println("Opening Browser on http://127.0.0.1:4413")
+// go OpenBrowser("http://127.0.0.1:4413")
+
+// case "help":
+// fmt.Println("Verfügbare Befehle:")
+// fmt.Println(" status - zeigt den aktuellen Status")
+// fmt.Println(" server (1) - startet den HTTP Server")
+// fmt.Println(" serverstop - stoppt den HTTP Server")
+// fmt.Println(" open (2) - öffnet die UI im Browser")
+// fmt.Println(" exit, quit - beendet das Programm")
+// fmt.Println(
+// ` worlds - searches for all MC worlds on your computer and
+// and caches then -> only in default paths
+// worlds-f - searches for all MC worlds on your computer and
+// worlds-full and caches then -> in all paths
+// clean - to delete all the cache files`)
+
+// case "worlds":
+// go func() {
+// log.Println("Searching for Worlds in default paths...")
+// var worlds = SearchWorlds()
+// log.Println("Worlds Found: ", worlds)
+// SaveWorlds(worlds)
+// log.Println("Finished Searching for Worlds")
+// }()
+
+// case "worlds-f", "worlds-full":
+// go func() {
+// log.Println("Searching for Worlds everywhere...")
+// var worlds = SearchWorlds(true)
+// log.Println("Worlds Found: ", worlds)
+// SaveWorlds(worlds)
+// log.Println("Finished Searching for Worlds")
+// }()
+
+// default:
+// log.Printf("Unbekanntes Kommando: %s\n", cmd)
+// }
+
+// return false
+// }
diff --git a/internal/mcapp/worlds.go b/internal/mcapp/worlds.go
new file mode 100644
index 00000000..77d8b6bd
--- /dev/null
+++ b/internal/mcapp/worlds.go
@@ -0,0 +1,172 @@
+package mcapp
+
+import (
+ "crypto/sha1"
+ "encoding/json"
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/shadowdara/finder/internal/templates"
+ "github.com/shadowdara/finder/pub/fsd"
+)
+
+type World struct {
+ Path string `json:"path"`
+ IconPath string `json:"icon"`
+ Size int64 `json:"size,omitempty"`
+ LastModified string `json:"last_modified,omitempty"`
+}
+
+func normalizeWorldIconPath(p string) string {
+ normalized := filepath.ToSlash(p)
+ normalized = strings.ReplaceAll(normalized, "\\", "/")
+ for strings.Contains(normalized, "//") {
+ normalized = strings.ReplaceAll(normalized, "//", "/")
+ }
+ return normalized
+}
+
+func makeWorld(dir string) World {
+ // Basisverzeichnis der Welt
+
+ // Icon-Pfad in der Welt
+ icon := filepath.Join(dir, "icon.png")
+
+ // Zielordner im Webcache
+ webcacheDir, err := GetCachePath()
+ if err != nil {
+ fmt.Println("Fehler beim Abrufen des Webcache-Pfads:", err)
+ return World{}
+ }
+ os.MkdirAll(webcacheDir, os.ModePerm)
+
+ iconsDir := filepath.Join(webcacheDir, "icons")
+
+ if err := os.MkdirAll(iconsDir, 0o755); err != nil {
+ fmt.Println("Fehler beim Erstellen des Icon-Verzeichnisses:", err)
+ return World{}
+ }
+
+ // Eindeutiger Dateiname: Ordnername + Hash vom Pfad
+ base := filepath.Base(dir) // Ordnername
+ safeBase := strings.ReplaceAll(base, " ", "_")
+
+ h := sha1.Sum([]byte(dir)) // Hash vom kompletten Verzeichnis-Pfad
+ hashPart := fmt.Sprintf("%x", h[:6]) // kurze Hash-Version (12 Hex-Zeichen)
+
+ fileName := fmt.Sprintf("%s_%s.png", safeBase, hashPart)
+ iconTarget := filepath.Join(iconsDir, fileName)
+
+ fmt.Println(icon)
+ fmt.Println(iconTarget)
+
+ // Icon kopieren, wenn es existiert
+ if _, err := os.Stat(icon); err != nil {
+ fmt.Printf("Icon nicht gefunden: %s (%v)\n", icon, err)
+ } else {
+ fmt.Printf("Icon gefunden: %s\n", icon)
+
+ if _, err := os.Stat(iconTarget); os.IsNotExist(err) {
+ fmt.Printf("Kopiere nach: %s\n", iconTarget)
+
+ if err := fsd.CopyFile(icon, iconTarget); err != nil {
+ fmt.Printf("Fehler beim Kopieren: %v\n", err)
+ }
+ } else if err != nil {
+ fmt.Printf("Fehler beim Prüfen des Ziel-Icons: %v\n", err)
+ } else {
+ fmt.Printf("Icon existiert bereits: %s\n", iconTarget)
+ }
+ }
+
+ // relative Pfad
+ relPath, err := filepath.Rel(webcacheDir, iconTarget)
+ if err != nil {
+ fmt.Println("Fehler beim Berechnen des relativen Pfads:", err)
+ relPath = filepath.Base(iconTarget) // Fallback
+ }
+ relPath = normalizeWorldIconPath(relPath)
+
+ info, err := os.Stat(dir)
+ if err != nil {
+ fmt.Println("Error getting file info:", err)
+ }
+
+ size, err := fsd.DirSize(dir)
+ if err != nil {
+ fmt.Println("Fehler:", err)
+ }
+
+ return World{
+ Path: dir,
+ IconPath: relPath,
+ Size: size,
+ LastModified: info.ModTime().Format("2006-01-02 15:04:05"),
+ }
+}
+
+// Save these to a file
+func SaveWorlds(paths []string) {
+ cachePath, err := GetCachePath()
+ if err != nil {
+ fmt.Println("Fehler beim Abrufen des benutzerdefinierten Pfads:", err)
+ return
+ }
+ os.MkdirAll(cachePath, os.ModePerm)
+
+ filePath := filepath.Join(cachePath, "worlds.json")
+ file, err := os.Create(filePath)
+ if err != nil {
+ fmt.Println("Fehler beim Erstellen der Datei:", err)
+ return
+ }
+ defer file.Close()
+
+ // Pfade in Structs umwandeln
+ var worlds []World
+ for _, p := range paths {
+ worlds = append(worlds, makeWorld(p))
+ }
+
+ encoder := json.NewEncoder(file)
+ encoder.SetIndent("", " ")
+ if err := encoder.Encode(worlds); err != nil {
+ fmt.Println("Fehler beim Schreiben der JSON:", err)
+ }
+}
+
+// Welten laden
+func LoadWorlds() []World {
+ dir, err := GetCachePath()
+ if err != nil {
+ fmt.Println("Fehler beim Abrufen des benutzerdefinierten Pfads:", err)
+ return nil
+ }
+ filePath := filepath.Join(dir, "worlds.json")
+
+ file, err := os.Open(filePath)
+ if err != nil {
+ fmt.Println("Fehler beim Öffnen der Datei:", err)
+ return nil
+ }
+ defer file.Close()
+
+ var worlds []World
+ decoder := json.NewDecoder(file)
+ if err := decoder.Decode(&worlds); err != nil {
+ fmt.Println("Fehler beim Einlesen der JSON:", err)
+ return nil
+ }
+
+ return worlds
+}
+
+func GetCachePath() (string, error) {
+ path, err := templates.GetCustomPath()
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(path, "webcache"), nil
+}
diff --git a/internal/mcapp/worlds_test.go b/internal/mcapp/worlds_test.go
new file mode 100644
index 00000000..cec7ae8a
--- /dev/null
+++ b/internal/mcapp/worlds_test.go
@@ -0,0 +1,11 @@
+package mcapp
+
+import "testing"
+
+func TestNormalizeWorldIconPath(t *testing.T) {
+ p := `icons\\my_world_abc123.png`
+ got := normalizeWorldIconPath(p)
+ if got != "icons/my_world_abc123.png" {
+ t.Fatalf("normalizeWorldIconPath() = %q, want %q", got, "icons/my_world_abc123.png")
+ }
+}
diff --git a/pub/fsd/folder.go b/pub/fsd/folder.go
index 4e1b992b..65ef1929 100644
--- a/pub/fsd/folder.go
+++ b/pub/fsd/folder.go
@@ -2,7 +2,10 @@ package fsd
import (
"fmt"
+ "io"
+ "os"
"os/exec"
+ "path/filepath"
"runtime"
)
@@ -25,3 +28,80 @@ func OpenFolder(path string) error {
return cmd.Start()
}
+
+func OpenBrowser(url string) {
+ var cmd string
+ var args []string
+
+ switch runtime.GOOS {
+ case "windows":
+ cmd = "rundll32"
+ args = []string{"url.dll,FileProtocolHandler", url}
+ case "darwin": // macOS
+ cmd = "open"
+ args = []string{url}
+ default: // Linux
+ cmd = "xdg-open"
+ args = []string{url}
+ }
+
+ exec.Command(cmd, args...).Start()
+}
+
+// CopyFile kopiert src → dst
+func CopyFile(src, dst string) error {
+ if _, err := os.Stat(dst); err == nil {
+ // existiert schon → skip
+ return nil
+ }
+
+ // Quelle öffnen
+ sourceFile, err := os.Open(src)
+ if err != nil {
+ return fmt.Errorf("konnte Quelle nicht öffnen: %w", err)
+ }
+ defer sourceFile.Close()
+
+ // Ziel anlegen (überschreibt falls existiert)
+ destFile, err := os.Create(dst)
+ if err != nil {
+ return fmt.Errorf("konnte Ziel nicht anlegen: %w", err)
+ }
+ defer destFile.Close()
+
+ // Inhalt kopieren
+ _, err = io.Copy(destFile, sourceFile)
+ if err != nil {
+ return fmt.Errorf("fehler beim Kopieren: %w", err)
+ }
+
+ // sicherstellen, dass alles auf Platte geschrieben wurde
+ err = destFile.Sync()
+ if err != nil {
+ return fmt.Errorf("fehler beim Sync: %w", err)
+ }
+
+ return nil
+}
+
+func DirSize(path string) (int64, error) {
+ var size int64
+ err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if !info.IsDir() {
+ size += info.Size()
+ }
+ return nil
+ })
+ return size, err
+}
+
+func GetBinaryDir() string {
+ ex, err := os.Executable() // Pfad zum Binary
+ if err != nil {
+ panic(err)
+ }
+ return filepath.Dir(ex) // nur das Verzeichnis
+}
From 24a495cbfc6b1ebe6ef9a600b62ea34a6876964d Mon Sep 17 00:00:00 2001
From: ShadowDara <128976697+ShadowDara@users.noreply.github.com>
Date: Wed, 9 Sep 2026 16:01:55 +0200
Subject: [PATCH 10/14] fixed path opener
---
cmd/findergen/main.go | 40 ++++++++-----------
.../pages/mcapp/worlds.jsx | 7 +++-
pub/fsd/folder.go | 17 ++++----
3 files changed, 29 insertions(+), 35 deletions(-)
diff --git a/cmd/findergen/main.go b/cmd/findergen/main.go
index 82ee1a70..bd85b5c7 100644
--- a/cmd/findergen/main.go
+++ b/cmd/findergen/main.go
@@ -206,39 +206,33 @@ func main() {
return
}
- var payload struct {
- Path string `json:"path"`
- }
+ path := r.URL.Query().Get("path")
- if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
- log.Printf("openfolder: invalid JSON: %v", err)
- http.Error(w, "Invalid JSON", http.StatusBadRequest)
+ if path == "" {
+ http.Error(w, "Missing path", http.StatusBadRequest)
return
}
- err := fsd.OpenFolder(payload.Path)
+ log.Printf("openfolder path = %q", path)
- if err != nil {
+ if err := fsd.OpenFolder(path); err != nil {
+ log.Printf("openfolder: %v", err)
http.Error(w, "Failed to open folder", http.StatusInternalServerError)
return
- } else {
- // HTML mit Auto-Close zurückgeben
- w.Header().Set("Content-Type", "text/html")
- w.WriteHeader(http.StatusOK)
- fmt.Fprintf(w, `
+ }
+
+ w.Header().Set("Content-Type", "text/html; charset=utf-8")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprint(w, `
-
-
@@ -88,7 +88,10 @@ export default function render(el) {
{world.last_modified}
{size}
-
+
{path}
diff --git a/pub/fsd/folder.go b/pub/fsd/folder.go
index 65ef1929..f3ee2c22 100644
--- a/pub/fsd/folder.go
+++ b/pub/fsd/folder.go
@@ -10,23 +10,20 @@ import (
)
func OpenFolder(path string) error {
- var cmd *exec.Cmd
-
switch runtime.GOOS {
case "windows":
- // Explorer öffnen
- cmd = exec.Command("explorer", path)
+ cmd := exec.Command("cmd", "/c", "start", "", path)
+ return cmd.Start()
+
case "darwin":
- // macOS Finder öffnen
- cmd = exec.Command("open", path)
+ return exec.Command("open", path).Start()
+
case "linux":
- // Linux: Standard-Dateimanager
- cmd = exec.Command("xdg-open", path)
+ return exec.Command("xdg-open", path).Start()
+
default:
return fmt.Errorf("OS %s wird nicht unterstützt", runtime.GOOS)
}
-
- return cmd.Start()
}
func OpenBrowser(url string) {
From a50028e7538e696f511c08da698cdcfbc401df56 Mon Sep 17 00:00:00 2001
From: ShadowDara <128976697+ShadowDara@users.noreply.github.com>
Date: Wed, 9 Sep 2026 16:04:12 +0200
Subject: [PATCH 11/14] safe
---
cmd/findergen/frontend/assets/mcappheader.js | 2 +-
cmd/findergen/frontend/assets/worlds.js | 2 +-
finder-template-generator-ssg/data/backend.json | 14 +++++++-------
finder-template-generator-ssg/data/gh-pages.json | 12 ++++++------
.../src/components/mcappheader.jsx | 3 +++
5 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/cmd/findergen/frontend/assets/mcappheader.js b/cmd/findergen/frontend/assets/mcappheader.js
index 4f869929..990a15c2 100644
--- a/cmd/findergen/frontend/assets/mcappheader.js
+++ b/cmd/findergen/frontend/assets/mcappheader.js
@@ -1 +1 @@
-import{j as l,F as r}from"./main_entry.js";function u(){return l(r,null,l("header",null,l("nav",null,l("ul",null,l("li",null,l("a",{href:"./"},"Home")),l("li",null,l("a",{href:"./worlds"},"Worlds")),l("li",null,l("a",{href:"./about"},"About"))))))}export{u as r};
+import{j as l,F as r}from"./main_entry.js";function u(){return l(r,null,l("header",null,l("nav",null,l("ul",null,l("li",null,l("a",{href:"./"},"Home")),l("li",null,l("a",{href:"./worlds"},"Worlds")),l("li",null,l("a",{href:"./about"},"About")),l("li",null,l("a",{href:"../"},"|-|"))))))}export{u as r};
diff --git a/cmd/findergen/frontend/assets/worlds.js b/cmd/findergen/frontend/assets/worlds.js
index 998bf527..3a35a7e9 100644
--- a/cmd/findergen/frontend/assets/worlds.js
+++ b/cmd/findergen/frontend/assets/worlds.js
@@ -1 +1 @@
-import{j as t,F as r}from"./main_entry.js";import{r as f}from"./mcappheader.js";function L(d){d.innerHTML=t(r,null,t(f,null),t("main",null,t("table",null,t("thead",null,t("tr",null,t("th",null,"Icon"),t("th",null,"Folder Name"),t("th",null,"Last Modified"),t("th",null,"Size"),t("th",null,"Path"))),t("tbody",{id:"world-list"}))));async function c(){try{let n="";const _=(await(await fetch(n+"/api/system")).json()).os==="windows",h=await(await fetch(n+"/api/mcapp/worlds")).json(),s=document.getElementById("world-list");s.innerHTML="",h.forEach(l=>{const a=document.createElement("tr");let u=l.icon,o=l.path;const i=l.path.split(/[/\\]+/),p=i[i.length-2],m=encodeURIComponent(o.replace(/[/\\]level\.dat$/i,""));let e=l.size;e>=1024*1024?e=(e/(1024*1024)).toFixed(2)+" MB":e>=1024?e=(e/1024).toFixed(2)+" KB":e=e+" B",a.innerHTML=t(r,null,t("td",null,t("img",{src:`/___static___/webcache/icons/${u}`,width:"32"})),t("td",null,p),t("td",null,l.last_modified),t("td",null,e),t("td",null,t("a",{target:"_blanc",href:`/api/openfolder?path=${m}`},o))),s.appendChild(a)})}catch(n){console.error("Fehler beim Laden:",n)}}c()}export{L as default};
+import{j as t,F as r}from"./main_entry.js";import{r as f}from"./mcappheader.js";function L(d){d.innerHTML=t(r,null,t(f,null),t("main",null,t("table",null,t("thead",null,t("tr",null,t("th",null,"Icon"),t("th",null,"Folder Name"),t("th",null,"Last Modified"),t("th",null,"Size"),t("th",null,"Path"))),t("tbody",{id:"world-list"}))));async function c(){try{let l="";const _=(await(await fetch(l+"/api/system")).json()).os==="windows",h=await(await fetch(l+"/api/mcapp/worlds")).json(),s=document.getElementById("world-list");s.innerHTML="",h.forEach(n=>{const a=document.createElement("tr");let u=n.icon,o=n.path;const i=n.path.split(/[/\\]+/),p=i[i.length-2],m=encodeURIComponent(o.replace(/[/\\]level\.dat$/i,""));let e=n.size;e>=1024*1024?e=(e/(1024*1024)).toFixed(2)+" MB":e>=1024?e=(e/1024).toFixed(2)+" KB":e=e+" B",a.innerHTML=t(r,null,t("td",null,t("img",{src:l+`/___static___/webcache/${u}`,width:"32"})),t("td",null,p),t("td",null,n.last_modified),t("td",null,e),t("td",null,t("a",{target:"_blanc",href:l+`/api/openfolder?path=${m}`},o))),s.appendChild(a)})}catch(l){console.error("Fehler beim Laden:",l)}}c()}export{L as default};
diff --git a/finder-template-generator-ssg/data/backend.json b/finder-template-generator-ssg/data/backend.json
index 14747482..10007775 100644
--- a/finder-template-generator-ssg/data/backend.json
+++ b/finder-template-generator-ssg/data/backend.json
@@ -1,16 +1,16 @@
{
- "generatedAt": "2026-09-09T13:32:40.010Z",
+ "generatedAt": "2026-09-09T14:03:43.833Z",
"total": {
"files": 50,
- "bytes": 253189,
- "kilobytes": 247.25,
+ "bytes": 253226,
+ "kilobytes": 247.29,
"megabytes": 0.24
},
"byExtension": [
{
"extension": ".js",
"files": 17,
- "bytes": 189534,
+ "bytes": 189571,
"percentage": 74.86
},
{
@@ -29,7 +29,7 @@
"extension": ".html",
"files": 18,
"bytes": 6824,
- "percentage": 2.7
+ "percentage": 2.69
},
{
"extension": ".sh",
@@ -172,7 +172,7 @@
{
"path": "assets/worlds.js",
"extension": ".js",
- "bytes": 1141
+ "bytes": 1139
},
{
"path": "assets/index.js",
@@ -282,7 +282,7 @@
{
"path": "assets/mcappheader.js",
"extension": ".js",
- "bytes": 264
+ "bytes": 303
},
{
"path": "assets/about.js",
diff --git a/finder-template-generator-ssg/data/gh-pages.json b/finder-template-generator-ssg/data/gh-pages.json
index 5df3d5b0..7e22b220 100644
--- a/finder-template-generator-ssg/data/gh-pages.json
+++ b/finder-template-generator-ssg/data/gh-pages.json
@@ -1,16 +1,16 @@
{
- "generatedAt": "2026-09-09T13:32:47.957Z",
+ "generatedAt": "2026-09-09T14:03:51.448Z",
"total": {
"files": 50,
- "bytes": 319026,
- "kilobytes": 311.55,
+ "bytes": 319063,
+ "kilobytes": 311.58,
"megabytes": 0.3
},
"byExtension": [
{
"extension": ".js",
"files": 17,
- "bytes": 255191,
+ "bytes": 255228,
"percentage": 79.99
},
{
@@ -172,7 +172,7 @@
{
"path": "assets/worlds.js",
"extension": ".js",
- "bytes": 1141
+ "bytes": 1139
},
{
"path": "assets/index.js",
@@ -282,7 +282,7 @@
{
"path": "assets/mcappheader.js",
"extension": ".js",
- "bytes": 264
+ "bytes": 303
},
{
"path": "assets/about.js",
diff --git a/finder-template-generator-ssg/src/components/mcappheader.jsx b/finder-template-generator-ssg/src/components/mcappheader.jsx
index 59253571..b0cdd2c8 100644
--- a/finder-template-generator-ssg/src/components/mcappheader.jsx
+++ b/finder-template-generator-ssg/src/components/mcappheader.jsx
@@ -16,6 +16,9 @@ export default function render() {