Skip to content

Commit 2874269

Browse files
committed
Merge branch 'master' of github.com:kidneyhex/EspruinoAppLoaderCore into kidneyhex-master
2 parents c04a6f6 + 90eedd4 commit 2874269

File tree

1 file changed

+48
-2
lines changed

1 file changed

+48
-2
lines changed

js/index.js

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,48 @@ function appJSONLoadedHandler() {
9999
});
100100
}
101101

102+
/**
103+
* Extract an app name from a /apps/appname path
104+
* - assumes app names cannot contain periods
105+
* - assumes apps cannot be named "apps"
106+
* - assumes we're in or including the "apps" folder in the href
107+
* Returns the app name string or null if not an app folder.
108+
*/
109+
function extractAppNameFromHref(href) {
110+
if (!href) return null;
111+
112+
try {
113+
const u = new URL(href);
114+
href = u.pathname;
115+
} catch (e) {
116+
// ignore - just use href as-is
117+
}
118+
// very unlikely, but get rid of query/hash
119+
href = href.split('?')[0].split('#')[0].trim();
120+
// remove leading/trailing slashes
121+
href = href.replace(/^\/+|\/+$/g, '');
122+
if (!href) return null; // was just /, throw it out
123+
124+
const parts = href.split('/').filter(Boolean);
125+
if (parts.length === 0) return null;
126+
// allow './' prefixes by dropping leading '.' segments
127+
while (parts.length && parts[0] === '.') parts.shift();
128+
if (parts.length === 0) return null; // skip if it was current dir only
129+
// reject any parent-directory references anywhere
130+
if (parts.some(p => p === '..')) return null;
131+
// prefer an 'apps' segment anywhere in the path; otherwise use first folder
132+
const appsIdx = parts.findIndex(p => p.toLowerCase() === 'apps');
133+
let candidate;
134+
if (appsIdx >= 0 && appsIdx + 1 < parts.length) candidate = parts[appsIdx + 1];
135+
else candidate = parts[0];
136+
if (!candidate) return null;
137+
// if the only thing we found is 'apps', ignore it
138+
if (candidate.toLowerCase() === 'apps') return null;
139+
// skip names with periods
140+
if (candidate.includes('.')) return null;
141+
return candidate;
142+
}
143+
102144
httpGet(Const.APPS_JSON_FILE).then(apps=>{
103145
if (apps.startsWith("---")) {
104146
showToast(Const.APPS_JSON_FILE+" still contains Jekyll markup","warning");
@@ -127,8 +169,12 @@ httpGet(Const.APPS_JSON_FILE).then(apps=>{
127169
let promises = [];
128170
htmlToArray(xmlDoc.querySelectorAll("a")).forEach(a=>{
129171
let href = a.getAttribute("href");
130-
if (!href || href.startsWith("/") || href.startsWith("_") || !href.endsWith("/")) return;
131-
let metadataURL = appsURL+"/"+href+"metadata.json";
172+
const appName = extractAppNameFromHref(href);
173+
// Skip anything that doesn't look like an app or is an _example_app
174+
if (!appName || appName.startsWith("_")) {
175+
return;
176+
}
177+
let metadataURL = appsURL+appName+"/metadata.json";
132178
console.log(" - Loading "+metadataURL);
133179
promises.push(httpGet(metadataURL).then(metadataText=>{
134180
try {

0 commit comments

Comments
 (0)