Skip to content

Commit 5b5cbdc

Browse files
committed
apps -> extensions
1 parent 386f587 commit 5b5cbdc

6 files changed

Lines changed: 51 additions & 51 deletions

File tree

File renamed without changes.

Apps/OpenInverter/OpenInverter.app.js renamed to Extensions/OpenInverter/OpenInverter.app.js

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
// === START_APP_CONFIG ===
1+
// === START_EXTENSION_CONFIG ===
22
// {
33
// "name": "OpenInverter",
44
// "id": "openinverter",
55
// "version": [0, 4, 5],
66
// "author": "JetPax",
77
// "description": "OpenInverter debug and configuration tool for motor control parameters, spot values, CAN mapping, and live plotting",
88
// "icon": "sliders",
9-
// "mipPackage": "github:jetpax/scripto-studio-registry/Apps/OpenInverter/lib",
9+
// "mipPackage": "github:jetpax/scripto-studio-registry/Extensions/OpenInverter/lib",
1010
// "menu": [
1111
// { "id": "parameters", "label": "Parameters", "icon": "sliders" },
1212
// { "id": "spotvalues", "label": "Spot Values", "icon": "activity" },
@@ -17,12 +17,12 @@
1717
// ],
1818
// "styles": ".oi-compact-header { padding: 16px 20px !important; min-height: auto !important; display: flex; justify-content: space-between; align-items: center; } .oi-compact-header h2 { font-size: 18px !important; margin: 0 !important; } .oi-button-row { display: flex; flex-direction: row; gap: 8px; flex-wrap: wrap; align-items: center; } .oi-button-row .secondary-button, .oi-button-row .primary-button { padding: 6px 12px !important; font-size: 12px !important; font-weight: 600; text-transform: none; letter-spacing: normal; display: flex; align-items: center; gap: 6px; } .oi-button-row .secondary-button svg, .oi-button-row .primary-button svg { width: 14px; height: 14px; flex-shrink: 0; } .oi-plot-controls { display: flex; gap: 20px; align-items: center; } .oi-plot-controls .button { display: flex; flex-direction: column; align-items: center; } .oi-plot-controls .codicon { font-size: 20px; } .oi-parameters-container { padding: 20px; } .oi-category-section { margin-bottom: 32px; } .oi-category-title { font-size: 18px; font-weight: 600; color: var(--scheme-primary); margin-bottom: 12px; padding-bottom: 8px; border-bottom: 2px solid var(--scheme-primary); } .oi-parameters-table { border: 1px solid var(--border-color); border-radius: 4px; overflow: hidden; } .oi-table-header, .oi-table-row { display: grid; grid-template-columns: 1.5fr 1fr 0.8fr 1.2fr 0.8fr; gap: 12px; padding: 6px 16px; align-items: center; } .oi-table-header { background: var(--scheme-primary); color: white; font-weight: 600; font-size: 13px; text-transform: uppercase; letter-spacing: 0.5px; } .oi-table-row { border-bottom: 1px solid var(--border-color); transition: background 0.2s; padding: 3px 16px; } .oi-table-row:hover { background: var(--bg-tertiary); } .oi-table-row:last-child { border-bottom: none; } .oi-value-input, .oi-enum-select { width: 100%; padding: 6px 0px; border: 1px solid #34495e; border-radius: 4px; background: #2c3e50; color: #0fdb0f; font-size: 14px; font-family: 'Menlo', 'Monaco', 'Courier New', monospace; } .oi-value-input:focus, .oi-enum-select:focus { outline: none; border-color: var(--scheme-primary); box-shadow: 0 0 0 2px rgba(0, 129, 132, 0.2); } .oi-spotvalues-container { padding: 20px; } .oi-spotvalues-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; } .oi-spotvalue-card { background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding: 16px; transition: all 0.2s; } .oi-spotvalue-card:hover { border-color: var(--scheme-primary); box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); } .oi-spotvalue-name { font-weight: 600; color: var(--scheme-primary); font-size: 13px; margin-bottom: 8px; } .oi-spotvalue-value { font-size: 24px; font-weight: 700; font-family: 'Menlo', Monaco, 'Courier New', monospace; color: white; } .oi-plot-container { display: flex; height: 500px; max-height: calc(100vh - 260px); gap: 20px; padding: 20px; overflow: hidden; } .oi-plot-sidebar { width: 140px; flex-shrink: 0; border-right: 1px solid var(--border-color); padding-right: 20px; overflow-y: auto; } .oi-plot-section-title { font-size: 14px; font-weight: 600; color: var(--scheme-primary); margin: 16px 0 12px 0; text-transform: uppercase; letter-spacing: 0.5px; } .oi-plot-signal-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 24px; } .oi-plot-signal { padding: 8px; border-radius: 4px; transition: background 0.2s; } .oi-plot-signal:hover { background: var(--bg-tertiary); } .oi-plot-signal label { display: flex; align-items: center; gap: 8px; cursor: pointer; font-size: 13px; } .oi-plot-signal input[type=\"checkbox\"] { width: 16px; height: 16px; cursor: pointer; } .oi-plot-signal-name { font-weight: 600; color: var(--text-primary); } .oi-plot-signal-unit { color: var(--text-secondary); font-size: 12px; margin-left: auto; } .oi-plot-settings { display: flex; flex-direction: column; gap: 12px; } .oi-plot-settings label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--text-secondary); } .oi-plot-settings input[type=\"number\"] { padding: 6px 8px; border: 1px solid var(--border-color); border-radius: 4px; background: var(--bg-secondary); color: var(--text-primary); font-size: 13px; } .oi-plot-settings input[type=\"number\"]:focus { outline: none; border-color: var(--scheme-primary); box-shadow: 0 0 0 2px rgba(0, 129, 132, 0.2); } .oi-plot-chart-area { flex: 1; position: relative; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 8px; padding: 16px; min-height: 0; min-width: 0; display: flex; flex-direction: column; } .oi-plot-chart-area canvas { width: 100% !important; height: 100% !important; max-width: 100%; max-height: 100%; }"
1919
// }
20-
// === END_APP_CONFIG ===
20+
// === END_EXTENSION_CONFIG ===
2121

2222
/**
23-
* OpenInverter App - Motor control and debugging interface
23+
* OpenInverter Extension - Motor control and debugging interface
2424
*
25-
* This app provides a complete interface for configuring and monitoring
25+
* This extension provides a complete interface for configuring and monitoring
2626
* OpenInverter motor controllers.
2727
*/
2828

File renamed without changes.

tools/build_index.py

Lines changed: 46 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,12 @@
1414

1515
# Configuration
1616
SCRIPTOS_DIR = 'ScriptOs'
17-
APPS_DIR = 'Apps'
17+
EXTENSIONS_DIR = 'Extensions'
1818
OUTPUT_FILE = 'index.json'
1919
START_MARKER = '# === START_CONFIG_PARAMETERS ==='
2020
END_MARKER = '# === END_CONFIG_PARAMETERS ==='
21-
APP_START_MARKER = '// === START_APP_CONFIG ==='
22-
APP_END_MARKER = '// === END_APP_CONFIG ==='
21+
EXTENSION_START_MARKER = '// === START_EXTENSION_CONFIG ==='
22+
EXTENSION_END_MARKER = '// === END_EXTENSION_CONFIG ==='
2323

2424
def parse_python_dict(content):
2525
"""Parse Python dict syntax to Python dict object"""
@@ -126,16 +126,16 @@ def extract_config_block(file_content):
126126

127127
return None
128128

129-
def extract_app_config_block(file_content):
130-
"""Extract config block from App .js file"""
131-
start_idx = file_content.find(APP_START_MARKER)
132-
end_idx = file_content.find(APP_END_MARKER)
129+
def extract_extension_config_block(file_content):
130+
"""Extract config block from Extension .js file"""
131+
start_idx = file_content.find(EXTENSION_START_MARKER)
132+
end_idx = file_content.find(EXTENSION_END_MARKER)
133133

134134
if start_idx == -1 or end_idx == -1:
135135
return None
136136

137137
# Extract the JSON block (between comment markers)
138-
config_block = file_content[start_idx + len(APP_START_MARKER):end_idx].strip()
138+
config_block = file_content[start_idx + len(EXTENSION_START_MARKER):end_idx].strip()
139139

140140
# Remove comment prefixes (// or //) from each line
141141
lines = []
@@ -150,32 +150,32 @@ def extract_app_config_block(file_content):
150150
try:
151151
return json.loads(json_content)
152152
except json.JSONDecodeError as e:
153-
print(f"Warning: Failed to parse app config JSON: {e}")
153+
print(f"Warning: Failed to parse extension config JSON: {e}")
154154
return None
155155

156-
def parse_app_file(file_path, repo_url=None, branch='main', apps_base_dir=None):
157-
"""Parse an App .js file and extract metadata"""
156+
def parse_extension_file(file_path, repo_url=None, branch='main', extensions_base_dir=None):
157+
"""Parse an Extension .js file and extract metadata"""
158158
try:
159159
with open(file_path, 'r', encoding='utf-8') as f:
160160
content = f.read()
161161

162-
config = extract_app_config_block(content)
162+
config = extract_extension_config_block(content)
163163
if not config:
164164
print(f" ⚠ No config block found in {file_path.name}")
165165
return None
166166

167167
filename = file_path.name
168168

169-
# Determine the app's directory structure (relative to Apps/)
170-
if apps_base_dir:
171-
rel_path = file_path.relative_to(apps_base_dir)
172-
app_dir = rel_path.parent
169+
# Determine the extension's directory structure (relative to Extensions/)
170+
if extensions_base_dir:
171+
rel_path = file_path.relative_to(extensions_base_dir)
172+
extension_dir = rel_path.parent
173173
else:
174-
app_dir = Path('.')
174+
extension_dir = Path('.')
175175

176176
# Extract metadata
177177
name = config.get('name', filename.replace('.app.js', ''))
178-
app_id = config.get('id', name.lower().replace(' ', '-'))
178+
extension_id = config.get('id', name.lower().replace(' ', '-'))
179179
version = config.get('version', [1, 0, 0])
180180
author = config.get('author', '')
181181
description = config.get('description', '')
@@ -184,22 +184,22 @@ def parse_app_file(file_path, repo_url=None, branch='main', apps_base_dir=None):
184184
mip_package = config.get('mipPackage', None)
185185
# Note: styles are not extracted for index.json (loaded from full .app.js instead)
186186

187-
# Generate URL for main app file
187+
# Generate URL for main extension file
188188
if repo_url:
189189
# GitHub raw URL
190190
if 'raw.githubusercontent.com' in repo_url:
191-
url = f"{repo_url}/{branch}/Apps/{str(rel_path).replace(os.sep, '/')}"
191+
url = f"{repo_url}/{branch}/Extensions/{str(rel_path).replace(os.sep, '/')}"
192192
else:
193-
url = f"{repo_url}/raw/{branch}/Apps/{str(rel_path).replace(os.sep, '/')}"
193+
url = f"{repo_url}/raw/{branch}/Extensions/{str(rel_path).replace(os.sep, '/')}"
194194
else:
195-
url = f"/Apps/{str(rel_path).replace(os.sep, '/')}"
195+
url = f"/Extensions/{str(rel_path).replace(os.sep, '/')}"
196196

197-
# Build App entry
197+
# Build Extension entry
198198
# Note: styles are excluded from index.json as they're unused
199-
# The actual CSS is loaded from the full .app.js file when the app is installed
200-
app_entry = {
199+
# The actual CSS is loaded from the full .app.js file when the extension is installed
200+
extension_entry = {
201201
"name": name,
202-
"id": app_id,
202+
"id": extension_id,
203203
"filename": filename,
204204
"version": version,
205205
"author": author,
@@ -211,9 +211,9 @@ def parse_app_file(file_path, repo_url=None, branch='main', apps_base_dir=None):
211211

212212
# Add mipPackage if specified
213213
if mip_package:
214-
app_entry["mipPackage"] = mip_package
214+
extension_entry["mipPackage"] = mip_package
215215

216-
return app_entry
216+
return extension_entry
217217

218218
except Exception as e:
219219
print(f" ✗ Error parsing {file_path.name}: {e}")
@@ -304,10 +304,10 @@ def parse_scripto_file(file_path, repo_url=None, branch='main'):
304304
print(f" ✗ Error parsing {file_path.name}: {e}")
305305
return None
306306

307-
def build_index(scriptos_dir=SCRIPTOS_DIR, apps_dir=APPS_DIR, output_file=OUTPUT_FILE, repo_url=None, branch='main'):
308-
"""Build index.json from ScriptOs and Apps directories"""
307+
def build_index(scriptos_dir=SCRIPTOS_DIR, extensions_dir=EXTENSIONS_DIR, output_file=OUTPUT_FILE, repo_url=None, branch='main'):
308+
"""Build index.json from ScriptOs and Extensions directories"""
309309
scriptos_path = Path(scriptos_dir)
310-
apps_path = Path(apps_dir)
310+
extensions_path = Path(extensions_dir)
311311

312312
if not scriptos_path.exists():
313313
print(f"Error: ScriptOs directory not found: {scriptos_dir}")
@@ -330,32 +330,32 @@ def build_index(scriptos_dir=SCRIPTOS_DIR, apps_dir=APPS_DIR, output_file=OUTPUT
330330
if entry:
331331
scriptos.append(entry)
332332

333-
# Scan Apps (including subdirectories)
334-
apps = []
335-
if apps_path.exists():
336-
print(f"\nScanning {apps_dir}...")
333+
# Scan Extensions (including subdirectories)
334+
extensions = []
335+
if extensions_path.exists():
336+
print(f"\nScanning {extensions_dir}...")
337337
# Search recursively for .app.js files in subdirectories
338-
js_files = list(apps_path.glob('**/*.app.js'))
338+
js_files = list(extensions_path.glob('**/*.app.js'))
339339

340340
if js_files:
341-
print(f"Found {len(js_files)} App files")
341+
print(f"Found {len(js_files)} Extension files")
342342

343343
for js_file in sorted(js_files):
344344
print(f"Processing {js_file.name}...")
345-
entry = parse_app_file(js_file, repo_url, branch, apps_base_dir=apps_path)
345+
entry = parse_extension_file(js_file, repo_url, branch, extensions_base_dir=extensions_path)
346346
if entry:
347-
apps.append(entry)
347+
extensions.append(entry)
348348
else:
349-
print(f"No .app.js files found in {apps_dir}")
349+
print(f"No .app.js files found in {extensions_dir}")
350350
else:
351-
print(f"\nApps directory not found: {apps_dir} (skipping)")
351+
print(f"\nExtensions directory not found: {extensions_dir} (skipping)")
352352

353353
# Build index
354354
index = {
355355
"v": 1,
356356
"updated": int(time.time()),
357357
"scriptos": scriptos,
358-
"apps": apps
358+
"extensions": extensions
359359
}
360360

361361
# Write index.json
@@ -365,15 +365,15 @@ def build_index(scriptos_dir=SCRIPTOS_DIR, apps_dir=APPS_DIR, output_file=OUTPUT
365365
with open(output_path, 'w', encoding='utf-8') as f:
366366
json.dump(index, f, indent=2, ensure_ascii=False)
367367

368-
print(f"\n✓ Generated {output_file} with {len(scriptos)} ScriptOs and {len(apps)} Apps")
368+
print(f"\n✓ Generated {output_file} with {len(scriptos)} ScriptOs and {len(extensions)} Extensions")
369369
return True
370370

371371
def main():
372372
import argparse
373373

374-
parser = argparse.ArgumentParser(description='Build ScriptOs and Apps index.json')
374+
parser = argparse.ArgumentParser(description='Build ScriptOs and Extensions index.json')
375375
parser.add_argument('--scriptos-dir', default=SCRIPTOS_DIR, help='ScriptOs directory')
376-
parser.add_argument('--apps-dir', default=APPS_DIR, help='Apps directory')
376+
parser.add_argument('--extensions-dir', default=EXTENSIONS_DIR, help='Extensions directory')
377377
parser.add_argument('--output', default=OUTPUT_FILE, help='Output index.json file')
378378
parser.add_argument('--repo-url', help='GitHub repository URL (e.g., https://github.com/user/repo)')
379379
parser.add_argument('--branch', default='main', help='Git branch name')
@@ -389,7 +389,7 @@ def main():
389389
# Remove any duplicate /raw/ in the path
390390
repo_url = repo_url.replace('/raw/raw/', '/raw/')
391391

392-
success = build_index(args.scriptos_dir, args.apps_dir, args.output, repo_url, args.branch)
392+
success = build_index(args.scriptos_dir, args.extensions_dir, args.output, repo_url, args.branch)
393393
exit(0 if success else 1)
394394

395395
if __name__ == '__main__':

0 commit comments

Comments
 (0)