diff --git a/editor/index.html b/editor/index.html index ede19d9..f0a6890 100644 --- a/editor/index.html +++ b/editor/index.html @@ -1,14 +1,14 @@ + + + - - - @@ -30,14 +30,30 @@

Editor

+
+ + + +
-
+
-
+
+
+
diff --git a/editor/index.js b/editor/index.js index 08c4f40..bd9b551 100644 --- a/editor/index.js +++ b/editor/index.js @@ -11,8 +11,125 @@ var editor = null, diffEditor = null; "use strict"; var editor = null, diffEditor = null; +var currentMode = null; +var autoSaveTimer = null; +const STORAGE_KEY = 'monaco-editor-state'; -$(document).ready(function() { +function saveEditorState() { + if (!editor || !currentMode) return; + var $ = window.jQuery; + + const state = { + mode: currentMode, + theme: $('.theme-picker').val(), + code: editor.getValue() + }; + + localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); +} + +function loadEditorState() { + const savedState = localStorage.getItem(STORAGE_KEY); + if (!savedState) return null; + + try { + return JSON.parse(savedState); + } catch (e) { + console.error('Failed to parse saved state:', e); + return null; + } +} + +function setupAutoSave() { + if (!editor) return; + + editor.onDidChangeModelContent(function() { + if (autoSaveTimer) { + clearTimeout(autoSaveTimer); + } + + autoSaveTimer = setTimeout(function() { + saveEditorState(); + }, 1000); // 1秒后自动保存 + }); +} + +function generateShareURL() { + if (!editor || !currentMode) return ''; + var $ = window.jQuery; + + const state = { + mode: currentMode, + theme: $('.theme-picker').val(), + code: editor.getValue() + }; + + const encodedState = btoa(unescape(encodeURIComponent(JSON.stringify(state)))); + const baseURL = window.location.origin + window.location.pathname; + + return `${baseURL}?state=${encodedState}`; +} + +function getSharedStateFromURL() { + const urlParams = new URLSearchParams(window.location.search); + const encodedState = urlParams.get('state'); + + if (!encodedState) return null; + + try { + const decodedState = decodeURIComponent(escape(atob(encodedState))); + return JSON.parse(decodedState); + } catch (e) { + console.error('Failed to parse shared state:', e); + return null; + } +} + +function applyState(state, MODES) { + if (!state) return; + var $ = window.jQuery; + + // 找到对应的语言模式 + let modeIndex = 0; + for (let i = 0; i < MODES.length; i++) { + if (MODES[i].modeId === state.mode) { + modeIndex = i; + break; + } + } + + // 设置语言选择器 + $(".language-picker")[0].selectedIndex = modeIndex; + + // 设置主题 + if (state.theme) { + const themeOptions = $(".theme-picker option"); + for (let i = 0; i < themeOptions.length; i++) { + if (themeOptions[i].text === state.theme) { + $(".theme-picker")[0].selectedIndex = i; + changeTheme(i); + break; + } + } + } + + // 加载代码 + if (state.code !== undefined) { + loadSample(MODES[modeIndex], state.code); + } else { + loadSample(MODES[modeIndex]); + } +} + +function initializeEditor() { + // 确保 jQuery 可用 + if (typeof window.jQuery === 'undefined') { + setTimeout(initializeEditor, 100); + return; + } + + var $ = window.jQuery; + require(['vs/editor/editor.main'], function () { var MODES = (function() { var modesIds = monaco.languages.getLanguages().map(function(lang) { return lang.id; }); @@ -35,8 +152,23 @@ $(document).ready(function() { } $(".language-picker").append(o); } - $(".language-picker")[0].selectedIndex = startModeIndex; - loadSample(MODES[startModeIndex]); + + // 检查 URL 中是否有分享的代码 + var sharedState = getSharedStateFromURL(); + var savedState = loadEditorState(); + + if (sharedState) { + // 如果有分享的代码,优先使用分享的代码 + applyState(sharedState, MODES); + } else if (savedState) { + // 如果没有分享的代码,但有保存的状态,恢复保存的状态 + applyState(savedState, MODES); + } else { + // 否则,使用默认值 + $(".language-picker")[0].selectedIndex = startModeIndex; + loadSample(MODES[startModeIndex]); + } + $(".language-picker").change(function() { loadSample(MODES[this.selectedIndex]); }); @@ -45,13 +177,71 @@ $(document).ready(function() { changeTheme(this.selectedIndex); }); - loadDiffSample(); + $("#format-btn").click(function() { + if (editor) { + editor.getAction('editor.action.formatDocument').run(); + } + }); - $('#inline-diff-checkbox').change(function () { - diffEditor.updateOptions({ - renderSideBySide: !$(this).is(':checked') - }); + $("#share-btn").click(function() { + if (!editor || !currentMode) { + alert('编辑器尚未准备好'); + return; + } + + var shareURL = generateShareURL(); + + // 显示分享链接容器 + $('#share-url-container').show(); + $('#share-url-input').val(shareURL); + }); + + // 复制链接按钮 + $("#copy-url-btn").click(function() { + var shareURL = $('#share-url-input').val(); + if (!shareURL) return; + + // 创建一个临时输入框来复制 URL + var tempInput = document.createElement('input'); + tempInput.value = shareURL; + document.body.appendChild(tempInput); + tempInput.select(); + document.execCommand('copy'); + document.body.removeChild(tempInput); + + // 提示用户 + var originalText = $('#copy-url-btn').text(); + $('#copy-url-btn').text('已复制!'); + setTimeout(function() { + $('#copy-url-btn').text(originalText); + }, 2000); }); + + // 导出链接按钮 + $("#export-url-btn").click(function() { + var shareURL = $('#share-url-input').val(); + if (!shareURL) return; + + // 创建一个包含 URL 的文本文件 + var blob = new Blob([shareURL], { type: 'text/plain' }); + var url = window.URL.createObjectURL(blob); + var a = document.createElement('a'); + a.href = url; + a.download = 'editor-share-url.txt'; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + window.URL.revokeObjectURL(url); + }); + + // 移除 diff 编辑器功能,因为相关的示例文件 URL 已失效且页面中没有对应元素 + // loadDiffSample(); + + // $('#inline-diff-checkbox').change(function () { + // diffEditor.updateOptions({ + // renderSideBySide: !$(this).is(':checked') + // }); + // }); }); window.onresize = function () { @@ -62,7 +252,14 @@ $(document).ready(function() { diffEditor.layout(); } }; -}); +} + +// 等待 DOM 加载完成后再初始化 +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', initializeEditor); +} else { + initializeEditor(); +} var preloaded = {}; (function() { @@ -79,6 +276,7 @@ function xhr(url, cb) { if (preloaded[url]) { return cb(null, preloaded[url]); } + var $ = window.jQuery; $.ajax({ type: 'GET', url: url, @@ -91,9 +289,18 @@ function xhr(url, cb) { }); } -function loadSample(mode) { +function loadSample(mode, customCode) { + currentMode = mode.modeId; + var $ = window.jQuery; + + if (customCode !== undefined) { + loadCodeWithMode(mode.modeId, customCode); + return; + } + $('.loading.editor').show(); xhr(mode.sampleURL, function(err, data) { + var $ = window.jQuery; if (err) { if (editor) { if (editor.getModel()) { @@ -108,23 +315,32 @@ function loadSample(mode) { return; } - if (!editor) { - $('#editor').empty(); - editor = monaco.editor.create(document.getElementById('editor'), { - model: null, - }); - } - - var oldModel = editor.getModel(); - var newModel = monaco.editor.createModel(data, mode.modeId); - editor.setModel(newModel); - if (oldModel) { - oldModel.dispose(); - } - $('.loading.editor').fadeOut({ duration: 300 }); + loadCodeWithMode(mode.modeId, data); }) } +function loadCodeWithMode(modeId, code) { + var $ = window.jQuery; + if (!editor) { + $('#editor').empty(); + editor = monaco.editor.create(document.getElementById('editor'), { + model: null, + automaticLayout: true, + scrollBeyondLastLine: false, + }); + setupAutoSave(); + } + + currentMode = modeId; + var oldModel = editor.getModel(); + var newModel = monaco.editor.createModel(code, modeId); + editor.setModel(newModel); + if (oldModel) { + oldModel.dispose(); + } + $('.loading.editor').fadeOut({ duration: 300 }); +} + function loadDiffSample() { var onError = function() { @@ -173,4 +389,5 @@ function loadDiffSample() { function changeTheme(theme) { var newTheme = (theme === 1 ? 'vs-dark' : ( theme === 0 ? 'vs' : 'hc-black' )); monaco.editor.setTheme(newTheme); + saveEditorState(); } \ No newline at end of file