Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions .github/workflows/pr-branch-suggestion.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
name: PR Branch Suggestion

on:
pull_request_target:
types: [opened]
branches:
- master

jobs:
suggest-branch:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Suggest maintenance branch
uses: actions/github-script@v7
with:
script: |
const comment = `### Branch Targeting Suggestion

You've targeted the \`master\` branch with this PR. Please consider if a version branch might be more appropriate:

- **\`maintenance-9.x\`** - If your change is backward-compatible and won't create compatibility issues between INAV firmware and Configurator 9.x versions. This will allow your PR to be included in the next 9.x release.

- **\`maintenance-10.x\`** - If your change introduces compatibility requirements between firmware and configurator that would break 9.x compatibility. This is for PRs which will be included in INAV 10.x

If \`master\` is the correct target for this change, no action is needed.

---
*This is an automated suggestion to help route contributions to the appropriate branch.*`;

github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: comment
});
103 changes: 0 additions & 103 deletions js/transpiler/editor/monaco_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,108 +12,6 @@
import apiDefinitions from '../api/definitions/index.js';
import { generateTypeDefinitions } from '../api/types.js';

/**
* Load Monaco Editor
* @returns {Promise<Object>} Promise that resolves with monaco object
*/
function loadMonacoEditor() {
return new Promise((resolve, reject) => {
try {
// Check if already loaded
if (window.monaco) {
resolve(window.monaco);
return;
}

// In Vite/browser environment, use relative path to node_modules
// Vite will handle module resolution
const monacoBasePath = '/node_modules/monaco-editor';

// Use the min build which includes everything
const vsPath = monacoBasePath + '/min/vs';

console.log('Loading Monaco from:', vsPath);

// Monaco requires AMD loader, so use that directly
loadMonacoViaAMD(vsPath, resolve, reject);

} catch (error) {
console.error('Failed to load Monaco Editor:', error);
reject(error);
}
});
}

/**
* Load Monaco via AMD loader (fallback method)
* @param {string} vsPath - Path to Monaco's vs directory
* @param {Function} resolve - Promise resolve function
* @param {Function} reject - Promise reject function
*/
function loadMonacoViaAMD(vsPath, resolve, reject) {
// Validate vsPath to prevent potential injection issues
// Only allow alphanumeric, forward slash, dash, dot, and underscore
if (!/^[\/a-zA-Z0-9._-]+$/.test(vsPath)) {
reject(new Error('Invalid Monaco base path'));
return;
}

// Set global MonacoEnvironment before loading
window.MonacoEnvironment = {
getWorkerUrl: function(workerId, label) {
return `data:text/javascript;charset=utf-8,${encodeURIComponent(`
self.MonacoEnvironment = {
baseUrl: '${vsPath}'
};
importScripts('${vsPath}/base/worker/workerMain.js');
`)}`;
}
};

const loaderScript = document.createElement('script');
loaderScript.src = vsPath + '/loader.js';

loaderScript.onerror = () => {
reject(new Error('Failed to load Monaco loader.js'));
};

loaderScript.onload = () => {
try {
// Configure the loader
window.require.config({
paths: {
'vs': vsPath
},
'vs/nls': {
availableLanguages: {}
}
});

// Load the editor
window.require(['vs/editor/editor.main'], function() {
// Monaco is now available as a global
const monaco = window.monaco;

if (!monaco || !monaco.editor) {
console.error('Monaco object not properly initialized');
reject(new Error('Monaco editor object not found'));
return;
}

console.log('Monaco loaded via AMD');
resolve(monaco);
}, function(err) {
console.error('AMD require error:', err);
reject(err);
});
} catch (err) {
reject(err);
}
};

document.head.appendChild(loaderScript);
}

/**
* Initialize Monaco Editor with INAV-specific configuration
* @param {Object} monaco - Monaco editor instance
Expand Down Expand Up @@ -212,7 +110,6 @@ function setupLinting(editor, lintCallback, debounceMs = 500) {

// Export functions
export {
loadMonacoEditor,
initializeMonacoEditor,
addINAVTypeDefinitions,
setupLinting
Expand Down
75 changes: 40 additions & 35 deletions tabs/javascript_programming.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,23 @@ import MSPChainerClass from './../js/msp/MSPchainer.js';
import mspHelper from './../js/msp/MSPHelper.js';
import { GUI, TABS } from './../js/gui.js';
import FC from './../js/fc.js';
import path from 'node:path';
import i18n from './../js/localization.js';
import { Transpiler } from './../js/transpiler/index.js';
import { Decompiler } from './../js/transpiler/transpiler/decompiler.js';
import * as MonacoLoader from './../js/transpiler/editor/monaco_loader.js';
import apiDefinitions from './../js/transpiler/api/definitions/index.js';
import { generateTypeDefinitions } from './../js/transpiler/api/types.js';
import examples from './../js/transpiler/examples/index.js';
import settingsCache from './../js/settingsCache.js';
import * as monaco from 'monaco-editor';
import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker'

self.MonacoEnvironment = {
getWorker(_, label) {
if (label === 'typescript' || label === 'javascript') {
return new tsWorker()
}
return new editorWorker()
}
}

TABS.javascript_programming = {

Expand All @@ -39,40 +46,38 @@ TABS.javascript_programming = {
GUI.active_tab = 'javascript_programming';
}

$('#content').load("./tabs/javascript_programming.html", function () {

self.initTranspiler();

MonacoLoader.loadMonacoEditor()
.then(function(monaco) {
// Initialize editor with INAV configuration
self.editor = MonacoLoader.initializeMonacoEditor(monaco, 'monaco-editor');

// Add INAV type definitions
MonacoLoader.addINAVTypeDefinitions(monaco);

// Set up linting
MonacoLoader.setupLinting(self.editor, function() {
if (self.lintCode) {
self.lintCode();
}
});

// Continue with initialization
self.setupEventHandlers();
self.loadExamples();

self.loadFromFC(function() {
self.isDirty = false;
import('./javascript_programming.html?raw').then(({default: html}) => {
GUI.load(html, () => {
try {
self.initTranspiler();

// Initialize editor with INAV configuration
self.editor = MonacoLoader.initializeMonacoEditor(monaco, 'monaco-editor');

// Add INAV type definitions
MonacoLoader.addINAVTypeDefinitions(monaco);

// Set up linting
MonacoLoader.setupLinting(self.editor, function() {
if (self.lintCode) {
self.lintCode();
}
});

// Continue with initialization
self.setupEventHandlers();
self.loadExamples();

self.loadFromFC(function() {
self.isDirty = false;
GUI.content_ready(callback);
});
} catch (error) {
console.error('Failed to load Monaco Editor:', error);
GUI.content_ready(callback);
});
})
.catch(function(error) {
console.error('Failed to load Monaco Editor:', error);
GUI.content_ready(callback);
});

}

});
});
},

Expand Down