welsonjs/WelsonJS.Toolkit/WelsonJS.Launcher/editor.html
2025-04-09 19:58:41 +09:00

358 lines
14 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>WelsonJS Editor</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<link rel="stylesheet" href="http://localhost:3000/ajax/libs/metroui/dev/lib/metro.css" integrity="sha384-4XgOiXH2ZMaWt5s5B35yKi7EAOabhZvx7wO8Jr71q2vZ+uONdRza/6CsK2kpyocd" crossorigin="anonymous">
<link rel="stylesheet" href="http://localhost:3000/ajax/libs/metroui/dev/lib/icons.css" integrity="sha384-FuLND994etg+RtnpPSPMyNBvL+fEz+xGhbN61WUWuDEeZ+wJzcQ8SGqAMuI5hWrt" crossorigin="anonymous">
<link rel="stylesheet" href="http://localhost:3000/ajax/libs/monaco-editor/0.52.2/min/vs/editor/editor.main.css" integrity="sha384-06yHXpYRlHEPaR4AS0fB/W+lMN09Zh5e1XMtfkNQdHV38OlhfkOEW5M+pCj3QskC" crossorigin="anonymous">
<style>
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
#container {
border: 1px solid grey;
height: calc(100% - 139px);
overflow: hidden;
}
#fileInput {
display: none;
}
.banner {
text-align: center;
padding: 10px;
background-color: #f1f1f1;
font-size: 14px;
}
</style>
</head>
<body>
<nav data-role="ribbonmenu">
<ul class="tabs-holder">
<li class="static"><a href="#">WelsonJS</a></li>
<li><a href="#editor-tab">Editor</a></li>
</ul>
<div class="content-holder">
<div class="section" id="editor-tab">
<div class="group">
<button id="btnOpenFile" class="ribbon-button">
<span class="icon mif-folder-open"></span>
<span class="caption">Open File</span>
</button>
<button id="btnSaveFile" class="ribbon-button">
<span class="icon mif-floppy-disks"></span>
<span class="caption">Save File</span>
</button>
<span class="title">File</span>
</div>
<div class="group">
<button id="btnCopilot" class="ribbon-button">
<span class="icon mif-rocket"></span>
<span class="caption">Copilot</span>
</button>
<span class="title">Generative</span>
</div>
<div class="group">
<button id="btnWhois" class="ribbon-button">
<span class="icon mif-earth"></span>
<span class="caption">Whois</span>
</button>
<button id="btnDnsQuery" class="ribbon-button">
<span class="icon mif-earth"></span>
<span class="caption">DNS</span>
</button>
<span class="title">Network</span>
</div>
</div>
</div>
</nav>
<div id="container"></div>
<input type="file" id="fileInput">
<div class="banner"><a href="https://github.com/gnh1201/welsonjs">WelsonJS</a> Code Editor powered by <a href="https://github.com/microsoft/monaco-editor">Microsoft Monaco Editor</a>.</div>
<script>
var require = {
paths: {
vs: 'http://localhost:3000/ajax/libs/monaco-editor/0.52.2/min/vs'
}
};
</script>
<script src="http://localhost:3000/ajax/libs/axios/1.8.4/axios.min.js" integrity="sha384-06w+raHvkSL3+E7mbQ2X6DZwI5A3veU8Ba+NLrAPxxRGw4Xy78sihHDHQMustMM4" crossorigin="anonymous"></script>
<script src="http://localhost:3000/ajax/libs/fast-xml-parser/4.5.1/fxparser.min.js" integrity="sha384-ae/HepOQ8hiJ/VA6yGwPMGXQXOkT/lJpjlcQ7EUgibUcfnBltuozgNj4IgOZ9QLc" crossorigin="anonymous"></script>
<script src="http://localhost:3000/ajax/libs/dompurify/3.2.4/purify.min.js" integrity="sha384-eEu5CTj3qGvu9PdJuS+YlkNi7d2XxQROAFYOr59zgObtlcux1ae1Il3u7jvdCSWu" crossorigin="anonymous"></script>
<script src="http://localhost:3000/ajax/libs/metroui/dev/lib/metro.js" integrity="sha384-grz4KlnFmdCd5ELenGIdPkUL/l+44UC4SniSke/OZQyRYXaQ1EDlGigacn6z4hGB" crossorigin="anonymous"></script>
<script src="http://localhost:3000/ajax/libs/monaco-editor/0.52.2/min/vs/loader.js" integrity="sha384-pHG02SG8pId94Np3AbPmBEJ1yPqaH0IkJGLSNGXYmuGhkazT8Lr/57WYpbkGjJtu" crossorigin="anonymous"></script>
<script src="http://localhost:3000/ajax/libs/monaco-editor/0.52.2/min/vs/editor/editor.main.js" integrity="sha384-fj9z+NUc93I3woCCy5IRQfrQ8Amu1E27tllwgb5gz3d9Vr1ymS13xcF6two3e4KH" crossorigin="anonymous"></script>
<script>
var editor;
var currentFileName = "sayhello.js";
var serverBaseUrl = "http://localhost:3000";
function resizeEditor() {
if (editor) {
var ribbonHeight = document.querySelector('nav').offsetHeight;
var bannerHeight = document.querySelector('.banner').offsetHeight;
var containerHeight = document.documentElement.clientHeight - ribbonHeight - bannerHeight;
document.getElementById('container').style.height = containerHeight + 'px';
editor.layout();
}
}
function getSuggestions(word, range) {
return axios.get(`${serverBaseUrl}/completion/${encodeURIComponent(word)}`)
.then(function (response) {
var parser = new XMLParser();
var result = parser.parse(response.data);
if (!result.suggestions || !result.suggestions.item) {
return {
suggestions: []
};
}
var items = Array.isArray(result.suggestions.item) ? result.suggestions.item : [result.suggestions.item];
var suggestions = items.map(function (item) {
return {
label: item.label,
kind: monaco.languages.CompletionItemKind.Text,
documentation: item.documentation || "",
insertText: '"' + item.insertText + '"',
range: range
};
});
return {
suggestions: suggestions
};
})
.catch(function () {
return {
suggestions: []
};
});
}
require(["vs/editor/editor.main"], function () {
editor = monaco.editor.create(document.getElementById('container'), {
value: ['// lib/sayhello.js', 'function say() {', ' console.log("hello");', '}', '', 'exports.say = say;', '', 'exports.VERSIONINFO = "SayHello (sayhello.js) version 0.1";', 'exports.AUTHOR = "abuse@catswords.net";', 'exports.global = global;', 'exports.require = global.require;'].join('\n'),
language: 'javascript'
});
monaco.languages.registerCompletionItemProvider('javascript', {
provideCompletionItems: function (model, position) {
var word = model.getWordUntilPosition(position);
var range = {
startLineNumber: position.lineNumber,
endLineNumber: position.lineNumber,
startColumn: word.startColumn,
endColumn: word.endColumn
};
return getSuggestions(word.word, range);
}
});
});
window.addEventListener('resize', resizeEditor);
function getFileLanguage(fileName) {
var extension = fileName.split('.').pop().toLowerCase();
var languageMap = {
'js': 'javascript',
'ts': 'typescript',
'html': 'html',
'css': 'css',
'json': 'json',
'py': 'python',
'java': 'java',
'c': 'c',
'cpp': 'cpp',
'cs': 'csharp',
'php': 'php',
'rb': 'ruby',
'go': 'go',
'rs': 'rust'
};
return languageMap[extension] || 'plaintext';
}
function navigate(href) {
var a = document.createElement("a");
a.href = href;
a.target = "_blank";
document.body.appendChild(a);
a.click();
}
function appendTextToEditor(text) {
const position = editor.getPosition();
const range = new monaco.Range(position.lineNumber, position.column, position.lineNumber, position.column);
editor.executeEdits("my-source", [{
range: range,
text: "\n" + text,
forceMoveMarkers: true
}]);
resizeEditor();
}
document.getElementById("fileInput").onchange = function (event) {
var file = event.target.files[0];
if (!file) return;
currentFileName = file.name;
var reader = new FileReader();
reader.onload = function (e) {
var language = getFileLanguage(file.name);
monaco.editor.setModelLanguage(editor.getModel(), language);
editor.setValue(e.target.result);
};
reader.readAsText(file);
};
document.getElementById("btnOpenFile").onclick = function () {
document.getElementById('fileInput').click();
};
document.getElementById("btnSaveFile").onclick = function () {
var text = editor.getValue();
var fileName = prompt("Enter file name:", currentFileName);
if (!fileName) return;
currentFileName = fileName;
var blob = new Blob([text], { type: 'text/plain' });
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = fileName;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
};
document.getElementById("btnCopilot").onclick = function () {
const promptMessage = prompt("Enter a prompt message:", '');
if (!promptMessage || promptMessage.trim() == '') {
alert("A prompt message is required.");
return;
}
appendTextToEditor(`\n//${promptMessage}... Generating text with Copilot...`);
(async function () {
const targetWsUrl = await getTargetByUrl('copilot.microsoft.com');
if (targetWsUrl) {
await sendPromptMessage(targetWsUrl, promptMessage);
} else {
alert("Microsoft Copilot not running. Please visit copilot.microsoft.com first.");
}
})();
};
document.getElementById("btnWhois").onclick = function () {
const hostname = prompt("Enter a hostname or IP address:", '');
if (!hostname || hostname.trim() == '') {
alert("A hostname or IP address is required.");
return;
}
axios.get(`${serverBaseUrl}/whois/${hostname}`).then(response => {
const responseText = DOMPurify.sanitize(response.data, { ALLOWED_TAGS: [], ALLOWED_ATTR: [] });
appendTextToEditor(`/*\n${responseText}\n*/`);
}).catch(error => {
console.error(error);
});
};
document.getElementById("btnDnsQuery").onclick = function () {
const hostname = prompt("Enter a hostname or IP address:", '');
if (!hostname || hostname.trim() == '') {
alert("A hostname or IP address is required.");
return;
}
axios.get(`${serverBaseUrl}/dns-query/${hostname}`).then(response => {
const responseText = response.data;
appendTextToEditor(`/*\n${responseText}\n*/`);
}).catch(error => {
console.error(error);
});
};
async function getTargetByUrl(urlPart) {
const response = await fetch(`${serverBaseUrl}/devtools/json`);
const targets = await response.json();
const target = targets.find(target => target.url.includes(urlPart));
if (target) {
console.log(`Found target: ${target.title} (${target.id})`);
return target.webSocketDebuggerUrl;
} else {
console.log('Target not found');
return null;
}
}
async function sendPromptMessage(wsUrl, promptMessage) {
const socket = new WebSocket(wsUrl);
const steps = [
{
id: 1,
method: 'Input.insertText',
params: {
text: promptMessage
}
},
{
id: 2,
method: 'Input.dispatchKeyEvent',
params: {
type: 'keyDown',
key: 'Enter',
code: 'Enter'
}
},
{
id: 3,
method: 'Runtime.evaluate',
params: {
expression: '((e)=>e[e.length-1].querySelector("code")?.innerText||e[e.length-1].innerText)(document.querySelectorAll("[data-content=ai-message]"))'
}
}
];
socket.onopen = () => {
steps.forEach((step) => {
if (step.id == 3) {
setTimeout(() => {
socket.send(JSON.stringify(step));
}, 9000);
} else {
socket.send(JSON.stringify(step));
}
});
};
socket.onmessage = (event) => {
const response = JSON.parse(event.data);
console.log("Sent successfully:", response.result);
if (response.id == 3) {
appendTextToEditor(response.result.result.value);
socket.close();
}
};
}
</script>
</body>
</html>